Skip to content

Architecture

Jonathan Sharpe edited this page Aug 24, 2024 · 12 revisions

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.

Development Mode

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.

Development request lifecycle

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
Loading

Production Mode

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

Production request lifecycle

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
Loading
Clone this wiki locally