Build front-end assets with Vite, npm, pnpm, Yarn or Bun

llms.txt

Most applications today ship JavaScript and CSS that has to be compiled before it is useful: Vite for a Laravel app, the Next.js or Nuxt.js build for a Node site, a static site generator. SrvYard builds these assets on the server during every deployment, inside the new release, so the files exist before the site switches to it. What you decide is which package manager installs the dependencies and which command builds.

This article shows the settings, the exact lines they add to the deploy script, how private registries are authenticated, how Node and the package managers get onto the server, and how to diagnose a build that fails or is killed.

Before you begin

  • A site with a package.json. The default script only runs the front-end steps when the file exists in the application folder.
  • A lock file in the repository (package-lock.json, pnpm-lock.yaml, yarn.lock or bun.lock). The install commands are the strict kind (npm ci, --frozen-lockfile) and fail when the lock file is missing or out of date.
  • Node and the package manager on the server. They come from the server's Runtimes tab (see Node.js versions and package managers). A package manager that is not installed is the most common cause of a missing build.
  • Enough memory. Builds are hungry. A small server may need swap or a bigger plan, see step 5.

1. Choose the package manager and the build command

Open the site's Settings and choose npm in the side menu.

The Front-end build card
The package manager and the build command used by the generated deploy script.
  1. Frontend package manager. One of none, npm, pnpm, yarn and bun. The choice decides the install and build commands.
  2. Build command. Leave it empty to use the manager's default, or type your own, for example npm run build -- --mode production. The field's placeholder shows the default.
  3. Save. Saves both. If the deploy script is still the one SrvYard generated, it is regenerated to match: "Build settings saved and the deploy script updated." If you edited the script yourself, SrvYard leaves it alone and tells you: "Build settings saved. This site has a customised deploy script, so edit the script to use them."
The package manager list
Five choices; none skips the front-end build entirely.
  1. The choices and what they run:
Choice Install Default build
none nothing nothing
npm npm ci npm run build
pnpm pnpm install --frozen-lockfile pnpm build
yarn yarn install --frozen-lockfile yarn build
bun bun install --frozen-lockfile bun run build

A custom build command may contain letters, digits, spaces and . _ : / @ = , + -, up to 255 characters, with no .. and no double spaces. Pipes, semicolons and && are not accepted: put anything more complicated in a script file or an npm script and call that.

2. See what the deploy script does

Open Settings > Deployments and read the Deploy script card.

The deploy script with the front-end block
The generated script runs the install and the build only when package.json exists.
  1. The script. For a Laravel site and npm, after composer install the script contains:
if [ -f package.json ]; then
    if command -v npm >/dev/null 2>&1; then
        npm ci
        npm run build
    else
        echo "npm is not installed on this server, so the front-end assets were not built."
    fi
fi

Three things follow from it:

  • A missing package manager does not fail a PHP site's deployment. It prints the message above and carries on, so a site can go live without its CSS. If the page looks unstyled after a deployment, read the log for that line.
  • For Next.js and Nuxt.js the missing manager does fail the deployment, with "npm is not installed for this site. Install Node.js and the package manager from the server's Runtimes tab.", because those sites cannot run without a build.
  • The build runs in the new release folder, so the live site is untouched until the build succeeds. The whole script has 780 seconds.
Tip

If a build is slow or memory hungry, build in your CI pipeline instead and set the package manager to none, so the deployment itself stays quick. See Deploy from GitHub Actions and other CI.

3. Use environment variables at build time

Vite and Next.js read their public variables (VITE_*, NEXT_PUBLIC_*) while building and bake them into the output. On a zero-downtime site the release's .env is a link to the shared file, so those values come from the saved environment. Save the environment first, then deploy: a change made after the build does not appear in the assets until the next build.

Other variables are not in the build's environment unless the file is read by the tool. To make every .env value available to your own script commands, turn on Make .env variables available to the deployment script in the Deploy script card.

4. Private registries

A package from a private npm registry needs a token.

The npm authentication card
Store a token for a private registry. It is kept encrypted.
  1. Registry URL. For example https://npm.pkg.github.com.
  2. Auth token. The token for that registry. It is stored encrypted and never shown again.
  3. Save credential. The credential is written to .npmrc: in the site folder, or in the home folder of a site with its own user. Remove it from the list with its bin button when it is no longer needed.

Composer packages from a private repository use the neighbouring Composer section in the same way (repository host, username, password or token), written to auth.json. Both need the permission to manage packages.

5. When the build fails

A build killed for lack of memory
Exit code 137 means the build was killed for lack of memory.
  1. The failure message. "npm run build failed with exit code 137 (out of memory)." Exit code 137 is the operating system killing a process that used more memory than the machine had.

Fixes, in order of effort:

  • Build elsewhere. Compile in CI and keep the heavy work off the server (see the tip above).
  • Add swap to the server, or stop other services during the build.
  • Raise the memory limit of Node for the build, for example by setting the Build command to NODE_OPTIONS=--max-old-space-size=2048 npm run build.
  • Use a bigger server. See Disk full, out of memory or a slow server.

Troubleshooting

  • "npm is not installed on this server, so the front-end assets were not built." Install Node on the server's Runtimes tab, or set the package manager to none if the site has no front end.
  • npm ci fails with "package.json and package-lock.json are not in sync". Run npm install locally and commit the updated lock file.
  • pnpm: command not found or yarn: command not found. The package manager is enabled through Corepack (pnpm and Yarn) or its own installer (Bun) from the Runtimes tab. Enable it there.
  • The build works locally and fails on the server. Check the Node version: the server uses the one set for the site, not yours. Pin it in package.json under engines.
  • "That build command is not valid." It contains a character that is not allowed (a pipe, semicolon or &&) or two spaces in a row.
  • The assets are old after a deployment. The build did not run (no package.json in the application folder, package manager none), or the script was edited and no longer calls the build. Read the log.
  • The script was not updated after you saved. It is a custom script. Edit the lines yourself or press Reset to default in the Deploy script card, which discards your edits.
Last updated 2026-10-247 min readNeed help? Contact support