> **For AI agents:** The documentation index is at [https://docs.digitalocean.com/llms.txt](https://docs.digitalocean.com/llms.txt). Markdown versions of pages use the same URL with `index.html.md` in place of the HTML page (for example, append `index.html.md` to the directory path instead of opening the HTML document). # Node.js Buildpack on App Platform App Platform is a fully managed Platform-as-a-Service (PaaS) that deploys applications from Git repositories or container images. It automatically builds, deploys, and scales components while handling all underlying infrastructure. App Platform supports two ways to build an image for your app: [Cloud Native Buildpacks](https://buildpacks.io/) and [Dockerfiles](https://docs.docker.com/engine/reference/builder/). When you give App Platform access to your code, it defaults to using a Dockerfile if one is present in the root of the directory or specified in the app spec. Otherwise, App Platform checks your code to determine what language or framework it uses. If it supports the language or framework, it chooses an appropriate resource type and uses the proper buildpack to build the app and deploy a container. App Platform uses the [heroku-buildpack-nodejs buildpack](https://github.com/heroku/heroku-buildpack-nodejs#readme) for detecting and building your Node.js applications and applications using Node.js frameworks such as Express.js, Next.js, and Nuxt.js. ## Node.js Applications using Buildpacks App Platform looks for any of the following files to detect a Node.js application: - `package.json` - `package-lock.json` - `yarn.lock` - `pnpm-lock.yaml` If App Platform detects more than one package manager lockfile, it selects one to use during build time. The order of preference is `yarn.lock`, `pnpm-lock.yaml`, then `package-lock.json`. If all three files are present, Yarn is preferred. ## Current Buildpack Version and Supported Runtimes App Platform uses version `325` of the Heroku Node.js buildpack. The buildpack supports running most Node.js versions runtime versions (`>= 0.10.0`) on the platform, but it is recommended to use the active LTS and Stable versions since these have higher test coverage. The buildpack supports the following Node.js runtime versions: - Ubuntu-22 - 4.x - 19.x - 20.0.0 - 20.9.0 - 20.16.0 - 20.20.0 - 21.0.0 - 21.7.3 - 22.0.0 - 22.22.0 - 23.0.0 - 23.10.0 - 24.0.0 - 24.13.0 - 25.0.0 - 25.4.0 App Platform uses `Node.js 22.x` by default if you do not specify a Node.js version in the engines section. ## Specify a Node.js Engine App Platform has updated the Node.js default version from v20 to v22. This is because v22 is the current stable LTS version and v20 is now in maintenance phase. Best practices for pinning the Node.js version in the package.json for apps should be followed in order to avoid build failures. You can specify your desired Node.js version in the `engines` section of `package.json`. `package.json` ```json { "engines": { "node": "16.x" } } ``` ## Specify Package a Manager App Platform supports [npm](https://docs.npmjs.com), [Yarn](https://yarnpkg.com/getting-started), and [pnpm](https://pnpm.io/motivation) to build the Node.js applications. We recommend using only one package manager in your application to avoid any conflicts. ### npm If you have a `package-lock.json` or `package.json` at the root of your application, App Platform uses the `npm` package manager. App Platform defaults to installing the current version of `npm` as designated by the [Node.js release](https://nodejs.org/en/about/previous-releases#looking-for-latest-release-of-a-version-branch). You can customize the `npm` version used by specifying the version in the `engines` section of your `package.json`: `package.json` ```json { "engines": { "npm": "~1.0.20" } } ``` ### yarn If you have `yarn.lock` at the root of your application along with `package.json`, App Platform uses `yarn` to build your application. You can specify the `yarn` version in `packageManager` section of your `package.json`, like this: `package.json` ```json { "packageManager": "yarn@4.1.1" } ``` This method uses [Corepack](https://github.com/nodejs/corepack) which is preferred for [Yarn](https://yarnpkg.com/) tooling. The version defined in `package.json` must be exact, but can be configured from a version range with [Corepack’s use command](https://github.com/nodejs/corepack?tab=readme-ov-file#corepack-use-nameversion), for example, `corepack use yarn@4.x`. You can also specify a `yarn` version in the `engines` section of your `package.json`: `package.json` ```json { "engines": { "yarn": "^0.14.0" } } ``` ### pnpm If you have `pnpm-lock.yaml` at the root of your application along with `package.json`, App Platform uses `pnpm` to build your application. You can specify which `pnpm` version in the `packageManager` section of your `package.json`, like this: `package.json` ```json { "packageManager": "pnpm@9.0.5" } ``` This method uses [Corepack](https://github.com/nodejs/corepack), which is preferred for [pnpm](https://pnpm.io/) tooling. The version defined in `package.json` must be exact, but you can configure a version range with [Corepack’s use command](https://github.com/nodejs/corepack?tab=readme-ov-file#corepack-use-nameversion), for example, `corepack use pnpm@9.x`. You can also specify a `pnpm` version in the `engines` section of your `package.json`, like this: `package.json` ```json { "engines": { "pnpm": "9.0.5" } } ``` ## Build Behaviour App Platform uses the same build process regardless of the package manager used. All the dependencies listed in `package.json` under `dependencies` and `devDependencies` are installed by default. However, after the build steps, the packages declared under `devDependencies` are stripped before application deployment. **Note**: Make sure to push your lockfiles (`package-lock.json`, `pnpm-lock.yaml`, or `yarn.lock`) to your repository and keep them updated. This ensures that the dependencies are installed correctly. ### Use npm install If you use `npm`, it uses `npm ci` to set up the build environment. If you prefer to use `npm install` instead of `npm ci`, set the `USE_NPM_INSTALL` environment variable with a `BUILD_TIME` scope in your app’s spec, like this: `app.yaml` ```yaml services: - name: web git: repo: "https://github.com/example/repo" branch: master envs: - key: USE_NPM_INSTALL scope: BUILD_TIME value: "true" ``` ### Disable NODE\_MODULES cache If you don’t use `npm` or you don’t want to cache `Node_modules`, declare a `NODE_MODULES_CACHE` environment variable in your app spec and set it to `false`, like this: `app.yaml` ```yaml services: - name: web git: repo: "https://github.com/example/repo" branch: master envs: - key: NODE_MODULES_CACHE scope: BUILD_TIME value: "false" ``` ### Skip devDependencies To disable the installation of `devDependencies`, set these environment set `NPM_CONFIG_PRODUCTION` to `true` if you are using npm, or `YARN_PRODUCTION` to `true` if you are using yarn, like this: `app.yaml` ```yaml services: - name: web git: repo: "https://github.com/example/repo" branch: master envs: - key: NPM_CONFIG_PRODUCTION scope: BUILD_TIME value: "true" ``` ### Skip Pruning The build process prunes the `devDependencies` before application deployment. If you want to keep these `devDependencies`, skip the pruning step by: - Setting environment variable `NODE_ENV` to anything other than `production`. This works for all the package managers. - Setting environment variable `NPM_CONFIG_PRODUCTION=false` if you’re using **npm**. - Setting environment variable `PNPM_SKIP_PRUNING=true` if you’re using **pnpm**. - Setting environment variable `YARN_PRODUCTION=false` if you’re using **Yarn v1**. - Setting environment variable `YARN2_SKIP_PRUNING=true` if you’re using **Yarn v2 and above**. ### Build Scripts By default, the `build` script in `package.json` is used to build the application. While each package manager supports standard `preinstall` and `postinstall` scripts, you can run scripts only before or after other build steps. To run specific actions before or after installing dependencies, use the `heroku-prebuild`, `heroku-postbuild`, and `heroku-cleanup` scripts. `package.json` ```json "scripts": { "heroku-prebuild": "echo This runs before installing dependencies.", "heroku-postbuild": "echo This runs after installing dependencies, but before pruning and caching dependencies.", "heroku-cleanup": "echo This runs after pruning and caching dependencies." } ``` ### Build Flags You can set build flags to your `build` script by setting `NODE_BUILD_FLAGS` environment variable. ### Configure NPM You can configure `npm` by: - Adding a `.npmrc` file in the root directory. - Setting `NPM_CONFIG` environment variable. `npm` reads configuration from any environment variables beginning with `NPM_CONFIG`. When `NPM_CONFIG_PRODUCTION` is set to `true`, npm automatically runs all scripts in a subshell where `NODE_ENV` is `production`. ### Using Private Packages You can use private packages with `npm` by configuring the private registry and access token. If the app uses a private dependency source, such a [Gemfury](https://gemfury.com), the project must configure an alternate registry with access tokens. You can specify registry URL and authorization token in `.npmrc`, like this: `.npmrc` ```json @scope:registry=https://registry.npmjs.org //registry.npmjs.org/:_authToken=${NPM_TOKEN} ``` In this example, `NPM_TOKEN` is provided as environment variable. ### Listening on PORT Your application must listen on the port specified by the `PORT` environment variable. App Platform sets this variable at runtime. Here’s an example with Node and Express that uses the `PORT` variable or `3000` for developing locally. ```javascript const express = require('express'); const app = express(); // get our port const port = process.env.PORT || 3000; // application code goes here // have node listen on our port app.listen(port, () => console.log(`App listening on port ${port}!`)); ``` ### Using Cache It maintains a build cache that stores caches for `npm`, `yarn`, and `bower` that persists between builds. You can disable all caching by setting `NODE_MODULES_CACHE=false` environment variable. ### Custom Caching The `node_modules` and `bower_components` are cached by default. You can override these defaults by setting `cacheDirectories` array in `package.json`. custom-caching ```json "cacheDirectories": ["client/node_modules", "server/node_modules", "data"] ``` ### Clearing the Cache If your app is failing to build and you suspect that the issue is related to `node_modules` caching, you can force clear the cache and start a new build. To force clear the cache and rebuild using the Control Panel, go to the [**Apps** page](https://cloud.digitalocean.com/apps) and select your app. Click the **Actions** menu, then select **Force rebuild and deploy**. In the **Restart or deploy** window, select the **Clear build cache** option, then click **Force rebuild and deploy**. This clears the build cache and starts a new deployment. ![Force Build and Deploy screen with Clear Build Cache checked](https://docs.digitalocean.com/screenshots/app-platform/app-force-build-deploy.f0e96a8ec41d6739b2afc615c6b48f4f9595bc95a1da45a26bacdd51ed76469b.png)