DEV Community

Guille Acosta
Guille Acosta

Posted on

TIL: setting up proxy server on vite

So, Today I learned how to setup a proxy server on vite. I was tired of seeing this kind of lines over an over:

axios.get('localhost:5001/api/products/1234')

so, first approach was to create a .env.local and set there a env variable like this:

VITE_API_BASE_URL="localhost:5001"

this way my initial code would look like:

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL
axios.get(`${API_BASE_URL}/api/products/1234`)
Enter fullscreen mode Exit fullscreen mode

but this approach add this new line each time I need to get the API_BASE_URL.

So I decided to setup a proxy server. This is useful not only for "making URLs shorter" but for overcoming CORS issues if your api is in a host other than "localhost".

export default defineConfig({
  plugins: ...,
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:5001',
        changeOrigin: true,
        secure: false,
      }
    }
  }
})
Enter fullscreen mode Exit fullscreen mode

Loading target from .env

let's say you would like to change that target prop based on the environment you are running the application.

You can do it by checking the command or the mode, but I recommend load the .env file and using the VITE_API_BASE_URL we already defined.

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '');

  return {
    plugins: ...,
    server: {
      proxy: {
        '/api': {
          target: env.VITE_API_BASE_URL,
          changeOrigin: true,
          secure: false,
        },
Enter fullscreen mode Exit fullscreen mode

this way, the target will depend on the VITE_API_BASE_URL defined on the .env which should be different on production, staging or local.

Fixing "http proxy error ECONNRESET"

Even if the request are succeding (by checking the network inspector) there is an error logged by vite on the terminal.

http proxy error ECONNRESET at TLSWrap.onStreamRead

for every single request which gets proxied.

So the answer posted here does the trick.

You will need first to add https as a dev dependency by doing: npm i -D https

and then importing on the top of vite.config.js:

import http from "https";
Enter fullscreen mode Exit fullscreen mode

and then adding the agent prop on the proxy key /api we just created:

server: {
      proxy: {
        '/api': {
          target: env.VITE_API_BASE_URL,
          changeOrigin: true,
          secure: false,
          agent: new http.Agent()
        },
Enter fullscreen mode Exit fullscreen mode

Hope this helps somebody to save some minutes on your next project. Happy coding!

Official docs can be found here: vite server proxy options

Top comments (4)

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

Guille, échale un vistazo a wj-config. Es un sistema de configuración completo que te libera de dotenv y archivos .env a cambio de usar archivos JSON.

Collapse
 
ghacosta profile image
Guille Acosta

Thanks, Jose! Didn't hear about this lib, definitely will check it out.

Collapse
 
webjose profile image
José Pablo Ramírez Vargas • Edited

Good. It provides per-environment configuration, so you can configure your URL's there and even stop needing the proxy. You can make it so the development environment creates absolute URL's, but production environment creates relative URLs.

config.json

{
    "api": {
        rootPath: "/api",
        "resourceA": {
            "rootPath": "/resourceA",
            "getAll": ""
            "get": "/{id}"
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

config.development.json

{
    "api": {
        "host": "localhost",
        "port": 3005,
        "rootPath": ""
    }
}
Enter fullscreen mode Exit fullscreen mode

Then your building module, config.js:

import wjConfig, { Environment } from 'wj-config';
import mainConfig from './config.json';

// Define your environment names.
const env = new Environment(window.env.APP_ENV, [
    'development',
    'test',
    'preprod',
    'production'
]);

const config = await wjConfig()
    .addObject(mainConfig)
    .name('Main')
    .includeEnvironment(env)
    .addPerEnvironment((b, e) => b.addFetchedConfig(`./config.${e}.json`, false))
    .createUrlFunctions('api')
    .build();

export default config;
Enter fullscreen mode Exit fullscreen mode

Then you get URL-building functions to get all resourceA records, or to get by ID.

import config from './config';

...
const getAllUrl = config.api.resourceA.getAll();
console.log(getAllUrl);
// development: http://localhost:3005/resourceA
// non-development (like production): /api/resourceA
const getResAByIdUrl = config.api.resourceA.get({ id: 123 });
console.log(getResAByIdUrl);
// development: http://localhost:3005/resourceA/123
// non-development: /api/resourceA/123
Enter fullscreen mode Exit fullscreen mode

Pretty cool, right?

The window.env.APP_ENV is explained in several places in GitHub.

This example is Vite + Vue.

Collapse
 
devdufutur profile image
Rudy Nappée

One of reasons I looooove vite. So simple, it just works as you expect...