Files
next.js/contributing/core/developing.md
T
Hendrik LiebauandGitHub e9b96b4128 Build with dev runtimes when --debug-prerender is set (#89834)
When running `next build --debug-prerender`, React owner stacks are now
captured and displayed in prerender error output. This makes it much
easier to diagnose which component triggered uncached I/O or accessed
request data without Suspense. Previously, `--debug-prerender` only
enabled source maps and disabled minification. Now it also auto-enables
`allowDevelopmentBuild` and sets `NODE_ENV=development`, which loads
React development builds where `captureOwnerStack()` is available.

The main challenge is that with `NODE_ENV=development`, both server and
client bundles include dev-only code paths (HMR, WebSocket connections,
dev overlay, debug channel, etc.) that expect a running dev server. We
don't want these when using `next start`. To solve this, we introduce
`process.env.__NEXT_DEV_SERVER`, an internal env var that is truthy only
during `next dev`. In client bundles, it's inlined at build time (`'1'`
for `next dev`, `''` for `next build`). In production server runtime
bundles, it's inlined as `''` for dead-code elimination. In development
server runtime bundles, it's left as a runtime check because those
bundles are shared between `next dev` (where it's set) and `next build
--debug-prerender` (where it's not). Meanwhile, `NODE_ENV` continues to
control React's dev/prod mode and error formatting, which is exactly
what we want for `--debug-prerender`.

This also replaces the previous `renderOpts.dev` / `workStore.dev`
pattern, which was unreliable because `RouteModule.isDev` was derived
from `NODE_ENV` at compile time. When `allowDevelopmentBuild` set
`NODE_ENV=development`, `isDev` would be compiled as `true` and
incorrectly activate all dev guards during `next start`.

Key changes:

- `config.ts` auto-enables `allowDevelopmentBuild` and sets
`NODE_ENV=development` when `--debug-prerender` is active
- `define-env.ts` inlines `__NEXT_DEV_SERVER` into all bundles (truthy
for dev, falsy for build) so dev-server features are dead-code
eliminated in production and `--debug-prerender` builds
- `next-dev.ts` and `next.ts` set `__NEXT_DEV_SERVER` in the process
environment for externalized server-side code
- `renderOpts.dev` and `workStore.dev` are removed — all consumers now
use `__NEXT_DEV_SERVER` (for dev-server features) or `NODE_ENV` (for
error formatting that should work in both dev and `--debug-prerender`
builds)
- `patch-error-inspect.ts` devirtualizes React server URLs in source map
URLs so they display as readable file paths
2026-02-13 16:29:10 +01:00

4.4 KiB

Developing

  • The development branch is canary.
  • All pull requests should be opened against canary.
  • The changes on the canary branch are published to the @canary tag on npm regularly.

Dependencies

  • Install Rust and Cargo via rustup.
  • Install the GitHub CLI.
  • Enable pnpm:
    corepack enable pnpm
    
  • (Linux) Install LLD (the LLVM linker) and Clang (used by rust-rocksdb):
    sudo apt install lld clang
    

Local Development

  1. Clone the Next.js repository (download only recent commits for faster clone):
    gh repo clone vercel/next.js -- --filter=blob:none --branch canary --single-branch
    
  2. Create a new branch:
    git checkout -b MY_BRANCH_NAME origin/canary
    
  3. Install the dependencies with:
    pnpm install
    
  4. Start developing and watch for code changes:
    pnpm dev
    
  5. In a new terminal, run pnpm types to compile declaration files from TypeScript. Note: You may need to repeat this step if your types get outdated.
  6. When your changes are finished, commit them to the branch:
    git add .
    git commit -m "DESCRIBE_YOUR_CHANGES_HERE"
    
  7. To open a pull request you can use the GitHub CLI which automatically forks and sets up a remote branch. Follow the prompts when running:
    gh pr create
    

For instructions on how to build a project with your local version of the CLI, see Developing Using Your Local Version of Next.js as linking the package is not sufficient to develop locally.

Testing a local Next.js version on an application

Since Turbopack doesn't support symlinks when pointing outside of the workspace directory, it can be difficult to develop against a local Next.js version. Neither pnpm link nor file: imports quite cut it. An alternative is to pack the Next.js version you want to test into a tarball and add it to the pnpm overrides of your test application. The following script will do it for you:

pnpm pack-next --tar && pnpm unpack-next path/to/project

Or without running the build:

pnpm pack-next --no-js-build --tar && pnpm unpack-next path/to/project

Without going through a tarball (only works if you've added the overrides from pack-next):

pnpm patch-next path/to/project

Supports the same arguments:

pnpm patch-next --no-js-build path/to/project

Explanation of the scripts

# Generate a tarball of the Next.js version you want to test
$ pnpm pack-next --tar

# You can also pass any cargo argument to the script

# To skip the `pnpm i` and `pnpm build` steps in next.js (e. g. if you are running `pnpm dev`)
$ pnpm pack-next --no-js-build

Afterwards, you'll need to unpack the tarball into your test project. You can either manually edit the package.json to point to the new tarballs (see the stdout from pack-next script), or you can automatically unpack it with:

# Unpack the tarballs generated with pack-next into project's node_modules
$ pnpm unpack-next path/to/project

Developing the Dev Overlay

The dev overlay is a feature of Next.js that allows you to see the internal state of the app including the errors. To learn more about contributing to the dev overlay, see the Dev Overlay README.md.

NODE_ENV vs __NEXT_DEV_SERVER

Both next dev and next build --debug-prerender produce bundles with NODE_ENV=development. Use process.env.__NEXT_DEV_SERVER to distinguish between them:

  • process.env.NODE_ENV !== 'production' — code that should exist in dev bundles but be eliminated from prod bundles. This is a build-time check.
  • process.env.__NEXT_DEV_SERVER — code that should only run with the dev server (next dev), not during next build --debug-prerender or next start.

Recover disk space

Rust builds quickly add up to a lot of disk space, you can clean up old artifacts with this command:

pnpm sweep

It will also clean up other caches (pnpm store, cargo, etc.) and run git gc for you.

MacOS disk compression

If you want to automatically use APFS disk compression on macOS for node_modules/ and target/ you can install a launch agent with:

./scripts/LaunchAgents/install-macos-agents.sh

Or run it manually with:

./scripts/macos-compress.sh