Deploy Node.js Apps
Node.js is a highly-efficient JavaScript runtime environment that executes JavaScript code as a server. Node.js is served using Phusion Passenger inside NGINX.
Popular Node.js recipes include Express, Next.js, Nuxt.js, SvelteKit. Please read our Runner's Guide first if you haven't.
This guide only covers running a Node.js server, not about statically rendered pages like from Create React App
, Webpack
, Parcel
or Gatsby
.
If your application is intented to be as a static site, you should read our Static Site Guide instead.
Recipes
- Express
- Next.js
- Nuxt.js
- SvelteKit
Init in Development Mode
source: clear
features:
- node lts
nginx:
root: public_html/public
passenger:
enabled: on
app_env: development
app_start_command: env PORT=$PORT npx nodemon ./bin/www
commands:
- npx express-generator --view=pug --css=less --git .
- npm i
- npm add -D nodemon
A simple express website with nodemon for development.
Switch to Production Mode
nginx:
root: public_html/public
passenger:
enabled: on
app_start_command: env PORT=$PORT npm start
This switches Express to production mode.
Init in Development Mode
source: clear
features:
- node lts
nginx:
root: public_html/public
passenger:
enabled: on
app_env: development
app_start_command: env PORT=$PORT yarn dev
commands:
- yarn create next-app .
A bootstrapped Next.js website run in development mode (HMR works automatically).
Switch to Production Mode
nginx:
root: public_html/public
passenger:
enabled: on
app_start_command: env PORT=$PORT yarn start
locations:
- match: /_next/
alias: public_html/.next/
commands:
- yarn build
This builds and switches Next.js to production mode.
Init in Development Mode
source: clear
features:
- node lts
nginx:
root: public_html/public
passenger:
enabled: on
app_env: development
app_start_command: env PORT=$PORT yarn dev
commands:
- npx nuxi init .
- yarn
A bootstrapped Nuxt.js website run in development mode.
WIP: HMR does not work with Nuxt.js yet.
Switch to Production Mode
nginx:
root: public_html/.output/public
passenger:
enabled: on
app_start_command: env PORT=$PORT node server/index.mjs
commands:
- yarn build
This builds and switches Nuxt.js to production mode.
Init in Development Mode
source: clear
features:
- node lts
nginx:
root: public_html/static
passenger:
enabled: 'on'
app_env: development
app_start_command: 'yarn dev --port $PORT --host'
commands:
- yes "" | yarn create svelte > /dev/null
- yarn
A bootstrapped SvelteKit website run in development mode (HMR works automatically).
Switch to Production Mode
nginx:
root: public_html/.svelte-kit/output/client
passenger:
enabled: on
app_start_command: yarn preview --port $PORT --host
app_root: public_html
commands:
- yarn build
This builds and switches SvelteKit to production mode.
Let's extract those recipes meaning individually.
Node environment
The default Node version is 16.x
, which is the default provided from the OS.
To change Node version used to the latest (LTS) one, put this in runner:
features:
- node lts
It will install node in userland and all binaries will use it instead of the default one.
You can also install other or specific version of Node.js e.g. node latest
, node beta
, node 16.3.2
. This action will install Node.js in userland with the help of webi script and enabling Corepack so package managers (npm & yarn & pnpm) can be used alongside userland node.
NGINX Setup
Binding Node.js through NGINX is done by Passenger. To make the binding work, you need to make sure that your app can open port number using given environment variable (.e.g. PORT
), and you point the root of your public file to a public
directory.
root: public_html/public
nginx:
passenger:
enabled: on
app_start_command: env PORT=$PORT npm start
If your setup is complex (e.g. using multiple websites in a domain) you can tell which exactly the app_root
directory your app is serving from. Just make sure your root directory is outside of your app directory.
root: public_html/client/dist
nginx:
locations:
- match: /api
passenger:
enabled: on
app_start_command: env PORT=$PORT npm start
app_root: public_html/server
Some frameworks like Next.js
likes to serve a hidden static directory e.g. /_next
. We can reduce server load by creating an extra /_next
location so those files is directly handled (and properly cached) by NGINX.
nginx:
locations:
# optimizing static cache
- match: /_next/
alias: public_html/.next/
There's so much more to cover about NGINX configuration! read more at NGINX page.
Package Install
Package installs can be done just like usual npm/yarn/pnpm install
command. For a little advice, using these extra options is recommended in production:
npm ci
yarn install --immutable
Clear packager cache
In meantime if your development has stable enough, you may want to clear the packager cache to save space.
npm cache clean --force
yarn cache clean --force
pnpm cache clean --force
Node.js Error Logs
When your Node.js crashed during startup, a helpful error will be displayed in the browser. This aids you to diagnose if some configuration is wrong.
(TODO) Unfortunately, we haven't found a way to capture Node.js error logs yet. You can (should?) do error logging to files using builtin Node.js Console API or use Winston.