When developing a modern web application, it’s common to use a frontend (Vue, React) that communicates with a backend (Nest.js) via REST APIs. Often, the two projects live in parallel, requiring them to be run in development mode. Without specific configuration, API calls between the frontend and backend will be blocked.

In my case, with a frontend in Vue 3 and NestJS as backend, as small Vite configuration helps to overcome the problem in local development.

Configuration of the Vue 3 frontend (Vite)

Important point, the two technologies used for my project are based on Vite. As a result, by default, both projects try to use port 3000 in development mode. First, I have to change the port used by Vite in the Vue project (the frontend) to a new one (port 4200 in my case).

// vite.config.js
export default defineConfig({
  // all the config...
  server: {
    port: 4200, // new custom port for development
  }
})

The CORS request problem

Now the two projects can run at the same time without port conflicts. The NestJS backend run on the default port (localhost:3000) and the Vue frontend on the newly defined one (localhost:4200), but the problem isn’t solved yet. The API calls from the frontend to the backend generate errors like this :

Access to fetch at 'http://localhost:3000/status' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

This error is due to security rules on the browser. Without cross-origin configuration on the server, it’s not possible to fetch url with different domain, protocol or port.

One solution is to enable CORS on the backend server, but this solution requires to add some code at server side to manage a configuration that is not required in production. Indeed, it’s never a good idea to have a specific behavior only for development use cases.

Solution with Vite

The solution is very simple with the proxy feature in the Vite development server: Vite is capable of proxifying the API and avoid CORS requests to be sent to the backend. To do that, I’ve added another piece of configuration to the frontend vite.config.js file:

// vite.config.js
export default defineConfig({
  // autres configurations...
  server: {
    port: 4200, // port du frontend
    proxy: {
      '/api': {
        target: 'http://localhost:3000', // NestJS backend address
        changeOrigin: true,
      }
    }
  }
})

With this config all trafic to “http://localhost:4200/api/…” will be proxified to “http://localhost:3000/api/…”.

As a result, all requests come from the same origin (localhost:4200) and no CORS errors are thrown by the browser.