vercel/next.js
Build pipeline
next build is orchestrated by packages/next/src/build/index.ts — at 4,401 lines, the second-largest file in the framework. It coordinates discovery, compilation, analysis, static generation, manifest writing, and trace collection.
Stages
graph TD
Start[next build] --> Config[Load + validate config<br/>server/config.ts]
Config --> Discovery[Discover routes<br/>route-discovery.ts]
Discovery --> Validate[validate-app-paths.ts]
Validate --> Compile{Bundler}
Compile -- default --> Turbopack[turbopack-build/]
Compile -- --webpack --> Webpack[webpack-build/]
Compile -- NEXT_RSPACK=1 --> Rspack[rspack via webpack-build]
Turbopack --> Analyze[Static analysis<br/>analysis/, swc/]
Webpack --> Analyze
Rspack --> Analyze
Analyze --> Static[Static generation<br/>static-paths/]
Static --> Manifests[Write manifests<br/>manifests/, generate-routes-manifest.ts]
Manifests --> Traces[Collect file traces<br/>collect-build-traces.ts]
Traces --> Adapter[Adapter post-processing<br/>adapter/build-complete.ts]
Adapter --> Done[Done]Each stage is a function call from index.ts into a module under packages/next/src/build/. The stages run sequentially — the build is single-process by design (the bundler itself runs workers).
Discovery
packages/next/src/build/route-discovery.ts (15 KB) walks app/ and pages/ and produces:
- A list of pages, layouts, error boundaries, loading boundaries, route handlers.
- The page extensions (
.ts,.tsx,.js,.mdxpernext.config.js). - Conflict detection across the two routers.
validate-app-paths.ts (10 KB) catches structural errors: a route handler colocated with a page, a layout without children, missing default exports.
Compilation
Three bundler paths share most of their config but plug in different builders:
| Path | Driver |
|---|---|
packages/next/src/build/turbopack-build/ |
crates/next-build via napi |
packages/next/src/build/webpack-build/ |
webpack 5 (packages/next/src/compiled/webpack/) |
packages/next/src/build/webpack-build/ + rspack |
rspack with packages/next-rspack/ |
The webpack config generator at packages/next/src/build/webpack-config.ts (2,936 lines) is shared between webpack and rspack. It produces three configurations per build:
- Server — Node-runtime server bundle
- Edge — Edge-runtime server bundle
- Client — Browser bundle
Each is generated for both production and (in dev) development. The webpack plugin set under packages/next/src/build/webpack/plugins/ provides Next.js-specific build behavior: route discovery into webpack entries, define-env injection, manifest generation, server reference manifests for server actions, and CSS chunking.
Build entries
packages/next/src/build/entries.ts (24 KB) decides which JavaScript entry points the bundler creates per route. Each App Router page produces three entries (server, edge, client) and each Pages Router page typically produces two (server, client). The entries reference templates under packages/next/src/build/templates/ like app-page.ts, app-route.ts, and pages.ts.
Templates
packages/next/src/build/templates/ is special: every file in it is compiled by the user's bundler at build time, not by the framework's own taskr build. That means relative require() calls in these files are resolved against the user's project, not the framework's own paths. New helpers must be exported from packages/next/src/server/app-render/entry-base.ts and accessed via entryBase.*.
Static analysis
After bundling, packages/next/src/build/analysis/ and packages/next/src/build/swc/ run additional passes:
- Read each page's exported config (
runtime,dynamic,revalidate,fetchCache, etc.). - Read segment configs from the loader tree (
packages/next/src/build/segment-config/). - Decide each page's rendering mode: static, ISR, dynamic, or PPR.
The output is a per-route rendering plan that drives the next stage.
Static generation
packages/next/src/build/static-paths/ pre-renders pages whose paths are known at build time. For getStaticPaths (Pages Router) and generateStaticParams (App Router), the build runs the data-fetching function, then the renderer for each path.
A worker pool runs many static renders in parallel — see packages/next/src/server/dev/static-paths-worker.ts (also used at build time).
Manifests
After compilation and static generation, the build writes JSON manifests to .next/:
| Manifest | Purpose |
|---|---|
routes-manifest.json |
All static + dynamic routes with their regexes |
build-manifest.json |
Per-route asset list (Pages Router) |
app-build-manifest.json |
Per-route asset list (App Router) |
prerender-manifest.json |
Pre-rendered routes and their revalidation config |
react-loadable-manifest.json |
Dynamically loaded modules |
next-font-manifest.json |
Font preload data |
server-reference-manifest.json |
Server actions inventory |
client-reference-manifest.json |
Client component inventory |
images-manifest.json |
Image optimization config |
middleware-manifest.json |
Middleware bindings |
The runtime reads these via packages/next/src/server/load-manifest.external.ts and packages/next/src/server/app-render/manifests-singleton.ts.
Build trace
Two unrelated traces are emitted:
- Build trace at
.next/trace— OpenTelemetry-format trace of the build itself, useful for performance analysis. Convert withscripts/trace-to-tree.mjs. - nft.json files — produced by
packages/next/src/build/collect-build-traces.ts(22 KB). Per-route file lists used by hosting platforms to know which dependencies each route needs.
Adapter
After all of the above, hosting-platform-specific post-processing runs:
packages/next/src/build/adapter/build-complete.ts (2,215 lines) is the API surface platforms target. It receives the route inventory, manifests, and traces, and produces a platform deployment shape (function bundles, edge bundles, image config, headers, redirects, rewrites).
Vercel implements this externally; other hosting platforms can target the same surface.
define-env
packages/next/src/build/define-env.ts (16 KB) builds the process.env constants injected into user bundles via webpack's DefinePlugin. Critical rules:
- For edge builds, force feature flags that gate Node-only imports to
falseso dead-code branches get eliminated. Otherwise edge bundles would fail to resolvenode:streamand friends. - New flags in user-bundled code go here.
- Flags consumed by pre-compiled runtime internals are independent of
define-env.ts— they need separate plumbing throughnext-server.tsorexport/worker.ts.
Compiler aliases
packages/next/src/build/create-compiler-aliases.ts (27 KB) builds the webpack/rspack/Turbopack aliases that point user code at the right vendored copy of React, the right react-server-dom-* package per layer, and the right module.compiled.js per runtime.
Polyfills
packages/next/src/build/polyfills/ injects Web Fetch, AbortController, structuredClone, and other modern-browser features for older targets. The packages/next-polyfill-module/ and packages/next-polyfill-nomodule/ packages are the actual bundles.
Integration points
- The build is invoked by
packages/next/src/cli/next-build.ts. - Manifest output is consumed by the server runtime at request time.
- Static output is served by the caching layer.
- Turbopack-driven builds delegate to the Rust crates (see crates).
Entry points for modification
- To add a new build stage: edit
packages/next/src/build/index.tsand add the corresponding module. - To add a new manifest: write the producer under
packages/next/src/build/manifests/and add a reader underpackages/next/src/server/. - To change webpack config:
packages/next/src/build/webpack-config.ts. - To add a new flag injected at build time: see feature-flag plumbing.
Key source files
| File | Purpose |
|---|---|
packages/next/src/build/index.ts |
Build orchestrator |
packages/next/src/build/route-discovery.ts |
Walk app/ and pages/ for routes |
packages/next/src/build/validate-app-paths.ts |
Validate routing structure |
packages/next/src/build/entries.ts |
Build webpack entries per route |
packages/next/src/build/webpack-config.ts |
webpack config generator |
packages/next/src/build/define-env.ts |
Build-time env injection |
packages/next/src/build/create-compiler-aliases.ts |
Module aliases per layer/runtime |
packages/next/src/build/handle-externals.ts |
Externalize Node modules from server bundle |
packages/next/src/build/static-paths/ |
Static generation |
packages/next/src/build/manifests/ |
Manifest writers |
packages/next/src/build/generate-routes-manifest.ts |
routes-manifest.json writer |
packages/next/src/build/collect-build-traces.ts |
nft.json producer |
packages/next/src/build/adapter/build-complete.ts |
Platform adapter API |
packages/next/src/build/templates/app-page.ts |
App page entry template (compiled by user bundler) |
packages/next/src/build/templates/app-route.ts |
App route handler template |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.