-
Notifications
You must be signed in to change notification settings - Fork 73
Architecture
This starter kit is designed to create a monolithic web application. Why? Having a single app in a single repo makes the following easier:
- Dev setup - clone a single repo and you're ready to go;
- Routing - no need for CORS configuration or service discovery to connect the frontend and backend (see my blog post for more information on configuring single-page apps);
- CI/CD - no need for synchronising between multiple repos; and
- Code consistency - a single set of ESLint and Babel configuration, so you can use the same language features and code style throughout.
There are other ways to build apps with different trade-offs, e.g. microservice architectures have grown in popularity, but this is often a sensible starting point.
In development mode, started using npm run dev
, Node and the Vite dev server are used to run the client and server separately, with requests to /api
endpoints proxied to the backend.
Using a proxy like this gives us development-production parity; we don't to add need any special configuration for either client or server to run the app locally.
The diagram below shows what happens when a page gets loaded in Architecture#Development Mode:
sequenceDiagram
actor Browser
Browser ->> +Vite dev server: GET :3000/...
note right of Vite dev server: Responds to every client-side route ("page") with index.html
Vite dev server -> Vite dev server: Served from ./web
Vite dev server -->> -Browser: index.html
Browser ->> +Vite dev server: GET :3000/{thing}.js
Vite dev server -> Vite dev server: Transpiled and served from ./web/src
Vite dev server -->> -Browser: {thing}.js
Browser ->> +Vite dev server: GET :3000/api/...
note right of Vite dev server: /api routes are CRUD endpoints
Vite dev server ->> +Express: Proxy -> GET :3100/api/...
Express ->> +Database: Query
Database -->> -Express: Data
Express -->> -Vite dev server: JSON
Vite dev server -->> -Browser: JSON
In production mode, started using npm run serve
, the client code is transpiled and bundled (using Vite) into ./api/static/
. Express serves both the API endpoints and the bundled client code.
This usage of build
and start
is to match the buildpack process used by e.g. Heroku, which basically carries out the following:
-
npm install
- install all of the dependencies -
npm run build
- build the production code from the raw source -
npm prune --production
- strip out the development dependencies -
npm start
- run the production code
The diagram below shows what happens when a page gets loaded in Architecture#Production Mode:
sequenceDiagram
actor Browser
Browser ->> +Server: GET /...
Server -> Server: Loaded from ./api/static/
note right of Server: Responds to every client-side route ("page") with index.html
Server -->> -Browser: index.html
Browser ->> +Server: GET /{thing}.js
Server -> Server: Loaded from ./api/static/
note right of Server: Bundled client code
Server -->> -Browser: {thing}.js
Browser ->> +Server: GET /api/...
Server ->> +Database: Query
Database -->> -Server: Data
note right of Server: /api routes are CRUD endpoints
Server -->> -Browser: JSON