Skip to content

11. Deployment

In development, two servers work together: the [Vite] development server (the client) and the JSON server (the API). In production, there is only one:

Image

1. Build the client. In the [rdvmedecins-react] folder:

npm run build

The console displays:

> rdvmedecins-react@1.0.0 build
> tsc --noEmit && vite build

vite v8.3.1 building client environment for production...
transforming...
✓ 205 modules transformed.
rendering chunks...
computing gzip size...
dist/index.html                             1.13 kB │ gzip:   0.58 kB
dist/assets/index-B3xI0Dco.css              0.48 kB │ gzip:   0.28 kB
dist/assets/libraries-CqLr8KVv.css        230.06 kB │ gzip:  30.68 kB
dist/assets/persons.config-Citeh_Yy.js      0.51 kB │ gzip:   0.25 kB
dist/assets/rolldown-runtime-CbXtAM7H.js    0.58 kB │ gzip:   0.36 kB
dist/assets/PersonFields-X0Ub6xSi.js        1.69 kB │ gzip:   0.69 kB
dist/assets/Persons-COxkkHus.js             2.00 kB │ gzip:   0.82 kB
dist/assets/PatientArea-BpWOm0FI.js         2.37 kB │ gzip:   0.97 kB
dist/assets/Register-DJgfayxN.js            2.46 kB │ gzip:   1.08 kB
dist/assets/PersonForm-CAd8EZMm.js          2.81 kB │ gzip:   1.33 kB
dist/assets/MyAccount-qsmn4TtZ.js           3.78 kB │ gzip:   1.35 kB
dist/assets/index-D-CLbbe-.js              38.11 kB │ gzip:  12.08 kB
dist/assets/libraries-CadH_l3h.js         394.23 kB │ gzip: 123.37 kB

✓ built in 598ms

First, [tsc --noEmit] checks the types for the entire project: [Vite] does not do this; it simply removes the syntax from [TypeScript]. A type error stops the build. Then [Vite] builds the entire application in the [dist/] folder: a [index.html] page, style sheets, and optimized [JavaScript] files:

  • [libraries-....js]: the library code ([React], [React Router], [TanStack Query], [i18next]...), stored in a separate file by the configuration of [vite.config.ts]. It rarely changes: from one version of the application to the next, the browser keeps it in the cache. [libraries-....css]: the stylesheet for [Bootstrap];
  • [index-....js]: OUR code, used for pages loaded immediately (login, calendar) and the rest of the application;
  • Each page loaded on demand ([lazy], see [routes.tsx]) has its own file ([MyAccount-....js]...), downloaded on the first visit; [PersonFields-....js] and [persons.config-....js] contain code common to several of these pages;
  • Upon startup, the browser downloads approximately 170 KB once compressed by the server (gzip column), of which 150 KB is for libraries;
  • Each file’s name contains a hash of its contents ([index-D-CLbbe-.js]): a new version will have a different name, and a browser will never be able to cache an outdated version. Only [index.html] retains its name: it is this file that references the others.

You can try the version built with [npm run preview] (http://localhost:4173, using the same proxy to the JSON server).

2. Upload it to the server. Copy the CONTENTS of the [dist/] folder into a [client/] folder at the root of the JSON server ([rdvmedecins-nestjs-json/client/index.html], [rdvmedecins-nestjs-json/client/assets/...]), then restart the server. It displays:

[Nest] LOG [RdvMedecins] React client served from .../rdvmedecins-nestjs-json/client
[Nest] LOG [RdvMedecins] JSON server started: http://localhost:8080/api

The complete application is now available at http://localhost:8080. The server serves the client’s files and returns [index.html] for any other URL outside of /api: reloading the /schedule page works (it is the client’s browser that displays it). For the curious reader, it is the [src/web/client-spa.ts] file on the server that performs this task.

3. In a real production environment, don’t forget the file [.env] on the server:

  • a long, random [JWT_SECRET];
  • an empty [CAPTCHA_TEST];
  • [COOKIE_SECURE=true] if the site is served via HTTPS (it must be: passwords are being transmitted);
  • [TRUST_PROXY=true] if the server is behind a proxy ([nginx]...), so that the attempt limit sees the clients’ actual IP address.

We then launch the compiled server: [npm run build], followed by [npm run start:prod].