← Registry
gh-actions-nodejs-build
clearedBuilds Node.js frontends or packages in GitHub Actions using actions/setup-node, npm or yarn installs, and working-directory for monorepo apps. Defaults Node to latest LTS unless package.json engines or the user pins a version. Use when authoring Node CI, frontend builds, or combining multiple JS packages in one job.
---
name: gh-actions-nodejs-build
description: >-
Builds Node.js frontends or packages in GitHub Actions using actions/setup-node,
npm or yarn installs, and working-directory for monorepo apps. Defaults Node to
latest LTS unless package.json engines or the user pins a version. Use when
authoring Node CI, frontend builds, or combining multiple JS packages in one job.
---
# GitHub Actions: Node.js build
Official action: [actions/setup-node](https://github.com/actions/setup-node).
## Node version (priority)
1. **User-requested** version (conversation or workflow variable)—use that.
2. **`package.json`** **`engines.node`** when it is a **strict** requirement—honor the range or exact version.
3. **Default:** **`node-version: 'lts/*'`** so CI tracks current Node LTS without manual bumps.
Optionally set **`node-version-file: package.json`** (or **`.nvmrc`**) when the repo already pins the version there—still prefer **`lts/*`** if there is no **`engines`** constraint and no pin file.
Re-check **`uses:`** for **`actions/setup-node`** with **`update-github-actions-versions`**.
## Minimal pattern
On **`ubuntu-latest`** (or Linux-compatible self-hosted runners):
1. **`actions/checkout`**
2. **`actions/setup-node`** with **`node-version`** (or **`node-version-file`**) and optional **`cache`** (see [reference.md](reference.md)).
3. **Install** — **`npm ci`** when **`package-lock.json`** exists; otherwise **`npm install`**. Use **`yarn install --frozen-lockfile`** when **`yarn.lock`** exists.
4. **Build** — **`npm run <script>`** or **`yarn run <script>`** matching **`package.json`** **`scripts`** (often **`build`**).
Use **`working-directory:`** on steps (or **`defaults.run.working-directory`**) for each app in a monorepo.
## Multiple packages in one job
Repeat **Install + Build** with different **`working-directory`** values (e.g. one package on **npm**, another on **yarn**)—see [reference.md](reference.md).
## Step identifiers
Set **`id:`** on **setup-node**, **install**, and **build** steps per **`ci-cd-pipeline-foundation`**.
## Outputs and artifacts
If deploy needs a **dist** folder, **`actions/upload-artifact`** or pass the path to a later step (static hosting, Docker, Azure, etc.).
**Azure Static Web Apps:** keep **`staticwebapp.config.json`** at the app root and copy it into **`dist`** after build so **`navigationFallback`** applies—otherwise SPA deep links fail. See [Azure Static Web Apps configuration](https://learn.microsoft.com/azure/static-web-apps/configuration#example-configuration-file). For Azure DevOps SWA deploy, see **`ado-azure-static-web-apps`**.
## Vite / heavy frontends
- Cache **`node_modules/.vite`** (or your bundler cache) with **`actions/cache`**, keyed by lockfile + config—see [reference.md](reference.md).
- Pass **`VITE_*`** (or **`NODE_ENV`**) through **`env:`** on the build step; use **`${{ vars.* }}`** for non-secrets.
## Job-level Node pin
Teams may set **`env.NODE_VERSION`** and pass **`${{ env.NODE_VERSION }}`** to **`setup-node`**—honor that over **`lts/*`** when intentional.
## YAML examples
See [reference.md](reference.md).