---
title: "Bundler Integration"
description: "Next.js bundler integration coordinates compilation across multiple underlying bundler backends—specifically supporting Turbopack, Webpack, and Rspack. It manages CLI argument parsing, configuratio..."
last_updated: "2026-09-23T10:52:03.186406+00:00"
canonical_url: "https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/development-and-diagnostics/bundler-integration"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/next/taskfile.js](https://github.com/blade47/next.js/blob/main/packages/next/taskfile.js)
- [packages/next/src/server/dev/hot-reloader-webpack.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-webpack.ts)
- [packages/next/src/lib/bundler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/bundler.ts)
- [packages/next/src/server/dev/hot-reloader-turbopack.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-turbopack.ts)
- [packages/next/src/server/dev/on-demand-entry-handler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/on-demand-entry-handler.ts)
- [packages/next/next-runtime.webpack-config.js](https://github.com/blade47/next.js/blob/main/packages/next/next-runtime.webpack-config.js)
- [packages/next/src/server/lib/router-utils/setup-dev-bundler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts)
- [packages/next/src/server/config-shared.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/config-shared.ts)
- [packages/next/src/shared/lib/get-webpack-bundler.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/get-webpack-bundler.ts)
- [packages/next-bundle-analyzer/index.js](https://github.com/blade47/next.js/blob/main/packages/next-bundle-analyzer/index.js)
- [packages/next/src/cli/next-build.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-build.ts)
- [turbopack/packages/turbo-tracing-next-plugin/src/index.ts](https://github.com/blade47/next.js/blob/main/turbopack/packages/turbo-tracing-next-plugin/src/index.ts)
- [packages/next/src/bundles/webpack/packages/webpack.js](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/webpack.js)
- [packages/next/src/server/config.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/config.ts)
- [packages/next-rspack/index.js](https://github.com/blade47/next.js/blob/main/packages/next-rspack/index.js)
- [packages/next/src/server/next.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/next.ts)
- [packages/next/src/server/config-utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/config-utils.ts)
- [packages/next/next-devtools.webpack-config.js](https://github.com/blade47/next.js/blob/main/packages/next/next-devtools.webpack-config.js)
- [packages/next/src/server/lib/dev-bundler-service.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dev-bundler-service.ts)
- [packages/next/src/lib/turbopack-warning.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/turbopack-warning.ts)
- [packages/next/src/bin/next.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/bin/next.ts)
- [packages/next/src/telemetry/events/build.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/telemetry/events/build.ts)
- [packages/next/src/bundles/webpack/bundle5.js](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/bundle5.js)
- [packages/next/src/server/dev/turbopack-utils.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/turbopack-utils.ts)
- [packages/next/src/shared/lib/turbopack/manifest-loader.ts](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts)
</details>

## Overview

Next.js bundler integration coordinates compilation across multiple underlying bundler backends—specifically supporting Turbopack, Webpack, and Rspack. It manages CLI argument parsing, configuration validation, compiler lifecycle orchestration, and incremental manifest persistence for both development and production targets.

Sources: [packages/next/src/lib/bundler.ts:2-87](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/bundler.ts#L2-L87), [packages/next/src/server/dev/hot-reloader-webpack.ts:687-787](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-webpack.ts#L687-L787), [packages/next/src/shared/lib/turbopack/manifest-loader.ts:177-225](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L177-L225)

## Bundler Selection and Configuration Engine

### Overview

The bundler selection and configuration engine is responsible for parsing command-line options, enumerating supported compilation backends, validating user configurations, and ensuring Turbopack compatibility against unsupported Next.js configuration options. It bridges CLI invocations and the core build system by determining which bundler engine (`Turbopack`, `Webpack`, or `Rspack`) executes for a given command.

Sources: [packages/next/src/lib/bundler.ts:1-102](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/bundler.ts#L1-L102), [packages/next/src/cli/next-build.ts:13-74](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-build.ts#L13-L74), [packages/next/src/lib/turbopack-warning.ts:41-190](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/turbopack-warning.ts#L41-L190)

### Bundler Enumeration and CLI Argument Parsing

The selection mechanism revolves around the `Bundler` enumeration and the `parseBundlerArgs` function located in `packages/next/src/lib/bundler.ts`. This engine evaluates explicit CLI flags, environment variables, and test overrides to select the active bundler backend.

| Bundler Enum Member | Associated CLI Flags / Env Vars | Default Behavior / Side Effects | Sources |
| :--- | :--- | :--- | :--- |
| `Bundler.Turbopack` | `--turbopack`, `--turbo`, `TURBOPACK`, `IS_TURBOPACK_TEST` | Default when no flags are configured (`process.env.TURBOPACK = 'auto'`) | [packages/next/src/lib/bundler.ts:2-84](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/bundler.ts#L2-L41,L73-L84) |
| `Bundler.Webpack` | `--webpack`, `IS_WEBPACK_TEST` | Sets webpack compilation pipeline when explicitly invoked | [packages/next/src/lib/bundler.ts:42-51](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/bundler.ts#L4-L4,L42-L51) |
| `Bundler.Rspack` | `NEXT_RSPACK`, `NEXT_TEST_USE_RSPACK` | Configured via environment variable side-effects and Next.js config | [packages/next/src/lib/bundler.ts:53-101](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/bundler.ts#L5-L5,L53-L63,L95-L101) |

Sources: [packages/next/src/lib/bundler.ts:2-87](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/bundler.ts#L2-L87)

> [!CAUTION]
> Setting conflicting flags across different bundlers (e.g., passing both `--turbopack` and `--webpack`) causes `parseBundlerArgs` to record multiple entries in `bundlerFlags`, print an error listing all active flags to `console.error`, and force an immediate termination via `process.exit(1)`.
> Sources: [packages/next/src/lib/bundler.ts:65-72](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/bundler.ts#L65-L72)

### Configuration Validation and Turbopack Compatibility Checks

Once the initial bundler is chosen, `validateTurboNextConfig` parses the user's `next.config.js` via `loadConfig` in raw configuration mode and checks for options that are incompatible with Turbopack. It recursively flattens custom configuration keys and compares them against `unsupportedTurbopackNextConfigOptions`.

> [!WARNING]
> If a build defaults to Turbopack (`process.env.TURBOPACK === 'auto'`) while a `webpack` configuration property is defined without a corresponding `turbopack` configuration, Next.js logs an error and terminates execution with `process.exit(1)`. Users can silence this check by supplying an explicit `--turbopack` or `--webpack` flag or by declaring an empty `turbopack: {}` block in their configuration file.
> Sources: [packages/next/src/lib/turbopack-warning.ts:143-166](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/turbopack-warning.ts#L143-L166)

The engine tracks a specific set of unsupported Next.js configuration keys when running under Turbopack:

- `experimental.fetchCacheKeyPrefix`
- `experimental.clientRouterFilterAllowedRate`
- `experimental.allowedRevalidateHeaderKeys`
- `experimental.extensionAlias`
- `experimental.fallbackNodePolyfills`
- `experimental.swcTraceProfiling`
- `experimental.craCompat`
- `experimental.disablePostcssPresetEnv`
- `experimental.esmExternals`
- `experimental.forceSwcTransforms`
- `experimental.fullySpecified`
- `experimental.urlImports`
- `experimental.slowModuleDetection`

Sources: [packages/next/src/lib/turbopack-warning.ts:5-38](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/turbopack-warning.ts#L5-L38)

### Execution Walkthrough

The bundler selection and validation sequence flows through several stages:

1. **CLI Parsing**: `parseBundlerArgs(options)` evaluates `options.turbopack`, `options.turbo`, `options.webpack`, and associated environment variables (`TURBOPACK`, `NEXT_RSPACK`, etc.), populating `bundlerFlags`.
2. **Cardinality Check**: If `bundlerFlags.size > 1`, `parseBundlerArgs` rejects the command, logs the conflict, and exits with status `1`. If `bundlerFlags.size === 0`, it defaults to `Bundler.Turbopack` and sets `process.env.TURBOPACK = 'auto'`.
3. **Build Execution Entry**: `nextBuild()` invokes `parseBundlerArgs(options)` and performs secondary validations, such as asserting that `--experimental-analyze` matches exclusively with `Bundler.Turbopack`.
4. **Config Interrogation**: `validateTurboNextConfig` loads the raw configuration object via `loadConfig(configPhase, dir, { rawConfig: true })`, flattens its keys, and checks against the unsupported option manifest.

Sources: [packages/next/src/lib/bundler.ts:15-87](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/bundler.ts#L15-L87), [packages/next/src/cli/next-build.ts:68-74](https://github.com/blade47/next.js/blob/main/packages/next/src/cli/next-build.ts#L68-L74), [packages/next/src/lib/turbopack-warning.ts:41-76](https://github.com/blade47/next.js/blob/main/packages/next/src/lib/turbopack-warning.ts#L41-L76)

## Development Bundler Orchestration Architecture

### Overview

Development bundler orchestration bridges Next.js server initialization, dynamic route watching, and the underlying compiler lifecycle. The development server instantiates the bundler through `setupDevBundler`, recording telemetry events and returning a `DevBundler` interface that exposes request handlers, manifest checkers, and hot-reloading hooks.
Sources: [packages/next/src/server/lib/router-utils/setup-dev-bundler.ts:1302-1341](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts#L1302-L1341), [packages/next/src/server/lib/router-utils/setup-dev-bundler.ts:1343-1343](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts#L1343)

### DevBundler Interface and Service Lifecycle

The `DevBundlerService` wraps the `DevBundler` instance to perform development-time tasks, manage Incremental Static Regeneration (ISR) manifests via an internal `LRUCache`, and route HMR communication.
Sources: [packages/next/src/server/lib/dev-bundler-service.ts:17-43](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dev-bundler-service.ts#L17-L43)

| Property / Method | Source Interface / Target | Purpose |
| :--- | :--- | :--- |
| `appIsrManifestInner` | `LRUCache<boolean>` | Stores ISR status flags for active routes with a maximum capacity of 8,000 entries. |
| `close` | `NextJsHotReloaderInterface['close']` | Binds to hot reloader closure logic to tear down compilation watchers. |
| `setCacheStatus` | `NextJsHotReloaderInterface['setCacheStatus']` | Updates cache status channels during compilation. |
| `setReactDebugChannel` | `NextJsHotReloaderInterface['setReactDebugChannel']` | Configures React debugging message transmission. |
| `sendErrorsToBrowser` | `NextJsHotReloaderInterface['sendErrorsToBrowser']` | Forwards compilation and build errors to connected clients. |
| `ensurePage` | `DevBundler['hotReloader']['ensurePage']` | Triggers compilation of specific page definitions on demand. |

Sources: [packages/next/src/server/lib/dev-bundler-service.ts:18-50](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dev-bundler-service.ts#L18-L50)

> [!NOTE]
> The ISR status manifest is selectively transmitted to legacy Pages Router clients or App Router clients with Cache Components disabled. When Cache Components are active, the binary nature of partial static rendering prevents the static indicator manifest from providing granular telemetry.
> Sources: [packages/next/src/server/lib/dev-bundler-service.ts:113-130](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dev-bundler-service.ts#L113-L130)

### Service Mocking and Revalidation Pipeline

`DevBundlerService` enables programmatic revalidation by mocking Node.js request and response objects, dispatching them through the worker handler, and asserting HTTP cache headers.
Sources: [packages/next/src/server/lib/dev-bundler-service.ts:75-101](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dev-bundler-service.ts#L75-L101)

```typescript
  public async revalidate({
    urlPath,
    headers,
    opts: revalidateOpts,
  }: {
    urlPath: string
    headers: IncomingMessage['headers']
    opts: any
  }) {
    const mocked = createRequestResponseMocks({
      url: urlPath,
      headers,
    })

    await this.handler(mocked.req, mocked.res)
    await mocked.res.hasStreamed

    if (
      mocked.res.getHeader('x-nextjs-cache') !== 'REVALIDATED' &&
      mocked.res.statusCode !== 200 &&
      !(mocked.res.statusCode === 404 && revalidateOpts.unstable_onlyGenerated)
    ) {
      throw new Error(`Invalid response ${mocked.res.statusCode}`)
    }

    return {}
  }
```
Sources: [packages/next/src/server/lib/dev-bundler-service.ts:75-101](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/dev-bundler-service.ts#L75-L101)

### Router Server Bridge and Virtual Manifests

The setup routine registers virtual file system items (`devVirtualFsItems`) for client pages manifests and middleware matchers, intercepting incoming HTTP requests inside `requestHandler` before they reach downstream routing logic.
Sources: [packages/next/src/server/lib/router-utils/setup-dev-bundler.ts:1221-1258](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts#L1221-L1258)

The request handling sequence processes incoming HTTP messages through distinct stages:

1. **URL Parsing**: `requestHandler` invokes `parseUrl(req.url || '/')` to extract the request pathname.
2. **Manifest Interception**: If `pathname` includes `clientPagesManifestPath`, the server responds with status `200`, sets `Content-Type: application/json`, and serializes non-App Router routes filtered via `opts.fsChecker.appFiles`.
3. **Middleware Matcher Interception**: If `pathname` matches `devMiddlewareManifestPath` or `devTurbopackMiddlewareManifestPath`, it responds with `serverFields.middleware?.matchers` and returns `{ finished: true }`.
4. **Fallback Propagation**: If no virtual manifests match, it returns `{ finished: false }` to let standard routing handle the request.

Sources: [packages/next/src/server/lib/router-utils/setup-dev-bundler.ts:1230-1258](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts#L1230-L1258)

> [!WARNING]
> When `logErrorWithOriginalStack` processes runtime errors, it deobfuscates error messages and checks instance types: `ModuleBuildError` logs standard error output via `Log.error(err.message)`, whereas `TurbopackInternalError` suppresses raw console output since rust-side handlers already write simplified messages to disk.
> Sources: [packages/next/src/server/lib/router-utils/setup-dev-bundler.ts:1260-1282](https://github.com/blade47/next.js/blob/main/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts#L1260-L1282)

## Webpack and Rspack Compilation Lifecycle

### Overview

The Webpack and Rspack compilation lifecycle handles bundler resolution, runtime configuration generation for multi-compiler setups, hot reloader initialization, and Node.js require-hook patching. Next.js isolates its internal bundling dependencies by re-routing module requests through custom resolution layers and runtime configuration generators.

Sources: [packages/next/src/server/dev/hot-reloader-webpack.ts:687-787](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-webpack.ts#L687-L787), [packages/next/src/shared/lib/get-webpack-bundler.ts:1-12](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/get-webpack-bundler.ts#L1-L12), [packages/next/src/server/config-utils.ts:1-144](https://github.com/blade47/next.js/blob/main/packages/next/src/server/config-utils.ts#L1-L144)

### Bundler Resolution and Hook Patching

Next.js provides a unified access layer for selecting between standard Webpack and Rspack via `getWebpackBundler()`. When `process.env.NEXT_RSPACK` is active, it loads Rspack core via `getRspackCore()`; otherwise, it returns standard Webpack.

```typescript
export default function getWebpackBundler(): typeof webpack {
  return process.env.NEXT_RSPACK ? getRspackCore() : webpack
}
```
Sources: [packages/next/src/shared/lib/get-webpack-bundler.ts:1-12](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/get-webpack-bundler.ts#L1-L12), [packages/next/src/bundles/webpack/packages/webpack.js:5-11](https://github.com/blade47/next.js/blob/main/packages/next/src/bundles/webpack/packages/webpack.js#L5-L11)

To prevent version mismatch issues with user-installed packages, `loadWebpackHook()` patches the Node.js `require` function to route `webpack` and internal loader requests directly to Next.js's bundled webpack versions and plugins.

```typescript
export function loadWebpackHook() {
  if (installed) {
    return
  }
  installed = true

  ;(
    require('../server/require-hook') as typeof import('../server/require-hook')
  ).addHookAliases(
    [
      ['webpack', 'next/dist/compiled/webpack/webpack-lib'],
      ['webpack/package', 'next/dist/compiled/webpack/package'],
      ['webpack/package.json', 'next/dist/compiled/webpack/package'],
      ['webpack/lib/webpack', 'next/dist/compiled/webpack/webpack-lib'],
      ['webpack/lib/webpack.js', 'next/dist/compiled/webpack/webpack-lib'],
      [
        'webpack/lib/node/NodeEnvironmentPlugin',
        'next/dist/compiled/webpack/NodeEnvironmentPlugin',
      ],
    ].map(
      ([request, replacement]) => [request, require.resolve(replacement)]
    )
  )
}
```
Sources: [packages/next/src/server/config-utils.ts:1-144](https://github.com/blade47/next.js/blob/main/packages/next/src/server/config-utils.ts#L1-L144)

> [!NOTE]
> `loadWebpackHook()` uses dynamic `require.resolve` lookups mapped over array pairs to ensure replacement targets resolve to valid built artifacts within `next/dist/compiled/webpack/`.
> Sources: [packages/next/src/server/config-utils.ts:1-144](https://github.com/blade47/next.js/blob/main/packages/next/src/server/config-utils.ts#L1-L144)

### Runtime Webpack Configuration Generation

The `getWebpackConfig` method orchestrates the creation of multi-compiler configurations for client, server, and edge-server runtimes. 

The configuration generation sequence proceeds through distinct phases:

1. **Page Discovery**: `getWebpackConfig` executes `findPageFile` concurrently for `/_app` and `/_document` files if a pages directory exists.
2. **Mapping Creation**: It invokes `createPagesMapping` to build page definitions using `PAGE_TYPES.PAGES`.
3. **Entrypoint Generation**: It calls `createEntrypoints` passing the collected pages, app directory state, and preview configuration properties.
4. **Project Info Loading**: It retrieves project details via `loadProjectInfo`.
5. **Compiler Generation**: It resolves base configurations concurrently for client, server, and edge-server compilers using `getBaseWebpackConfig`.

Sources: [packages/next/src/server/dev/hot-reloader-webpack.ts:687-787](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-webpack.ts#L687-L787)

```typescript
  private async getWebpackConfig(span: Span) {
    const webpackConfigSpan = span.traceChild('get-webpack-config')
    const pageExtensions = this.config.pageExtensions

    return webpackConfigSpan.traceAsyncFn(async () => {
      const pagePaths = !this.pagesDir
        ? ([] as (string | null)[])
        : await webpackConfigSpan
            .traceChild('get-page-paths')
            .traceAsyncFn(() =>
              Promise.all([
                findPageFile(this.pagesDir!, '/_app', pageExtensions, false),
                findPageFile(this.pagesDir!, '/_document', pageExtensions, false),
              ])
            )

      this.pagesMapping = await webpackConfigSpan
        .traceChild('create-pages-mapping')
        .traceAsyncFn(() =>
          createPagesMapping({
            isDev: true,
            pageExtensions: this.config.pageExtensions,
            pagesType: PAGE_TYPES.PAGES,
            pagePaths: pagePaths.filter(
              (i: string | null): i is string => typeof i === 'string'
            ),
            pagesDir: this.pagesDir,
            appDir: this.appDir,
            appDirOnly: Boolean(this.appDir && !this.pagesDir),
          })
        )

      const entrypoints = await webpackConfigSpan
        .traceChild('create-entrypoints')
        .traceAsyncFn(() =>
          createEntrypoints({
            appDir: this.appDir,
            buildId: this.buildId,
            config: this.config,
            envFiles: [],
            isDev: true,
            pages: this.pagesMapping,
            pagesDir: this.pagesDir,
            previewMode: this.previewProps,
            rootDir: this.dir,
            pageExtensions: this.config.pageExtensions,
          })
        )

      const commonWebpackOptions = {
        dev: true,
        buildId: this.buildId,
        encryptionKey: this.encryptionKey,
        config: this.config,
        pagesDir: this.pagesDir,
        rewrites: this.rewrites,
        originalRewrites: this.config._originalRewrites,
        originalRedirects: this.config._originalRedirects,
        runWebpackSpan: this.hotReloaderSpan,
        appDir: this.appDir,
        previewProps: this.previewProps,
      }

      return webpackConfigSpan
        .traceChild('generate-webpack-config')
        .traceAsyncFn(async () => {
          const info = await loadProjectInfo({
            dir: this.dir,
            config: commonWebpackOptions.config,
            dev: true,
          })
          return Promise.all([
            getBaseWebpackConfig(this.dir, {
              ...commonWebpackOptions,
              compilerType: COMPILER_NAMES.client,
              entrypoints: entrypoints.client,
              ...info,
            }),
            getBaseWebpackConfig(this.dir, {
              ...commonWebpackOptions,
              compilerType: COMPILER_NAMES.server,
              entrypoints: entrypoints.server,
              ...info,
            }),
            getBaseWebpackConfig(this.dir, {
              ...commonWebpackOptions,
              compilerType: COMPILER_NAMES.edgeServer,
              entrypoints: entrypoints.edgeServer,
              ...info,
            }),
          ])
        })
    })
  }
```
Sources: [packages/next/src/server/dev/hot-reloader-webpack.ts:687-787](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-webpack.ts#L687-L787)

### Design Trade-Offs and Constants

| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| **Node require-hook patching** | Prevents conflicting user-land dependencies and ensures exact Webpack version alignment. | Mutates global Node.js require behavior, which can interfere with advanced custom module loaders. |
| **Multi-compiler generation (`client`, `server`, `edgeServer`)** | Isolates environment-specific transformations (such as SSR vs. browser code). | Increases initial configuration generation time and memory footprint during startup. |
| **Virtual CommonJS package output (`{"type": "commonjs"}`)** | Forces deterministic CommonJS parsing rules inside the `.next` output directory. | Restricts native ESM feature usage inside internal build outputs. |

Sources: [packages/next/src/server/dev/hot-reloader-webpack.ts:886-897](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/hot-reloader-webpack.ts#L886-L897), [packages/next/src/server/config-utils.ts:1-144](https://github.com/blade47/next.js/blob/main/packages/next/src/server/config-utils.ts#L1-L144)

## On-Demand Entrypoint Resolution Pipeline

### Overview

The on-demand entrypoint resolution pipeline governs lazy page compilation scheduling, inactive entry disposal, and batch invalidation control during development. The `Invalidator` class coordinates compiler triggering to ensure that concurrent invalidation requests are batched without forcing unintended client-side hard reloads due to unstable Webpack hashes.

Sources: [packages/next/src/server/dev/on-demand-entry-handler.ts:270-326](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/on-demand-entry-handler.ts#L270-L326)

### Invalidation Batching and Execution Flow

The `Invalidator` class manages compilation states using `building` and `rebuildAgain` trackers (`BuildingTracker` and `RebuildTracker`, mapped to `CompilerNameValues`). When an invalidation is requested via `invalidate(compilerKeys)`, the execution pipeline follows a precise conditional sequence:

```
invalidate(compilerKeys) 
  → checks if compilerKey is in building Set 
  → [If building] adds key to rebuildAgain Set and continues 
  → [If idle] adds key to building Set 
  → calls multiCompiler.compilers[COMPILER_INDEXES[key]].watching?.invalidate()
```

When compilation completes, `doneBuilding(compilerKeys)` clears the keys from `building` and checks `rebuildAgain`, automatically re-triggering `invalidate(rebuild)` if queued updates exist.

Sources: [packages/next/src/server/dev/on-demand-entry-handler.ts:272-326](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/on-demand-entry-handler.ts#L272-L326)

> [!NOTE]
> If a build is actively processing a compiler key when an invalidation arrives, `Invalidator` never aborts the active build. Aborting an active build would trigger a client-side hard reload; instead, the key is registered in `rebuildAgain` and flushed immediately upon completion.
> Sources: [packages/next/src/server/dev/on-demand-entry-handler.ts:286-296](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/on-demand-entry-handler.ts#L286-L296)

### Entrypoint Lifecycle and Path Resolution

Active entries are tracked through `entriesMap`, which indexes entry objects by output directory and entry name. The `findPagePathData` function normalizes page routes and resolves them to absolute paths using project extensions and directory configurations.

```typescript
export async function findPagePathData(
  rootDir: string,
  page: string,
  extensions: string[],
  pagesDir: string | undefined,
  appDir: string | undefined,
  isGlobalNotFoundEnabled: boolean
): Promise<PagePathData>
```

Sources: [packages/next/src/server/dev/on-demand-entry-handler.ts:233-254](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/on-demand-entry-handler.ts#L233-L254), [packages/next/src/server/dev/on-demand-entry-handler.ts:400-408](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/on-demand-entry-handler.ts#L400-L408)

Inactive entries are periodically evaluated by `disposeInactiveEntries`, which flags entries for removal if their `lastActiveTime` exceeds `maxInactiveAge`. Root middleware, instrumentation hooks, and currently active client or server access pages are explicitly excluded from periodic disposal.

Sources: [packages/next/src/server/dev/on-demand-entry-handler.ts:328-371](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/on-demand-entry-handler.ts#L328-L371)

> [!WARNING]
> Middleware and instrumentation hook files identified by `isMiddlewareFilename(bundlePath)` or `isInstrumentationHookFilename(bundlePath)` are permanently exempt from periodic inactive disposal. Disposing them would break request handling for subsequent requests requiring these handlers.
> Sources: [packages/next/src/server/dev/on-demand-entry-handler.ts:342-348](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/on-demand-entry-handler.ts#L342-L348)

## Turbopack Runtime and Manifest Operations

### Overview

The Turbopack runtime and manifest subsystem manages route dispatching, HMR event streaming, issue tracking, and incremental persistence of build artifacts. The `TurbopackManifestLoader` class coordinates write operations across build, page, client build, app paths, action, font, middleware, and subresource integrity manifests using an internal change-tracking cache layer (`ManifestsMap`).

Sources: [packages/next/src/server/dev/turbopack-utils.ts:146-150](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/turbopack-utils.ts#L146-L150), [packages/next/src/shared/lib/turbopack/manifest-loader.ts:134-175](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L134-L175)

### Route Type Handling and Call Chain

Route compilation and dispatching are executed via `handleRouteType`, which processes different route variants such as `'page'`, `'page-api'`, `'app-page'`, and `'app-route'`. When loading middleware or server references for these routes, path resolution relies on precise manifest lookup sequences.

```mermaid
sequenceDiagram
    participant H as handleRouteType
    participant M as loadMiddlewareManifest
    participant P as getManifestPath
    participant A as addMetadataIdToRoute
    participant S as addRouteSuffix
    participant L as loadPagesManifest
    participant SM as ManifestsMap.set
    participant GT as ManifestsMap.get

    H->>M: loadMiddlewareManifest(pageName, type)
    M->>P: getManifestPath(page, distDir, name, type, true)
    P->>A: addMetadataIdToRoute(basePage)
    P->>S: addRouteSuffix(...)
    H->>L: loadPagesManifest(pageName)
    L->>SM: set(key, value)
    SM->>GT: get(key)
```

Sources: [packages/next/src/server/dev/turbopack-utils.ts:178-434](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/turbopack-utils.ts#L178-L434), [packages/next/src/shared/lib/turbopack/manifest-loader.ts:71-118](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L71-L118)

1. `handleRouteType` invokes `loadMiddlewareManifest` to resolve edge runtimes and associated entry points.
Sources: [packages/next/src/server/dev/turbopack-utils.ts:237-238](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/turbopack-utils.ts#L237-L238), [packages/next/src/shared/lib/turbopack/manifest-loader.ts:657-667](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L657-L667)
2. `loadMiddlewareManifest` calls `getManifestPath` to locate the target artifact on disk.
Sources: [packages/next/src/shared/lib/turbopack/manifest-loader.ts:661-667](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L661-L667)
3. `getManifestPath` invokes `addMetadataIdToRoute` to format metadata route file paths.
Sources: [packages/next/src/shared/lib/turbopack/manifest-loader.ts:113-113](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L113)
4. `getManifestPath` invokes `addRouteSuffix` to append the required route file boundary suffix.
Sources: [packages/next/src/shared/lib/turbopack/manifest-loader.ts:113-113](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L113)
5. `handleRouteType` invokes `loadPagesManifest` to record server page mappings.
Sources: [packages/next/src/server/dev/turbopack-utils.ts:204-204](https://github.com/blade47/next.js/blob/main/packages/next/src/server/dev/turbopack-utils.ts#L204), [packages/next/src/shared/lib/turbopack/manifest-loader.ts:817-822](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L817-L822)
6. `loadPagesManifest` delegates to `ManifestsMap.set` to update raw and parsed json objects.
Sources: [packages/next/src/shared/lib/turbopack/manifest-loader.ts:818-818](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L818), [packages/next/src/shared/lib/turbopack/manifest-loader.ts:141-145](https://github.com/blade47/next.js/blob/main/packages/next/src/shared/lib/turbopack/manifest-loader.ts#L141-L145)
7. `ManifestsMap.set` uses `ManifestsMap.get` to evaluate existing map state during updates.
Sources:

## Related

- [Dev Server and HMR](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/development-and-diagnostics/dev-server-and-hmr)
- [React Refresh Support](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/technical/development-and-diagnostics/react-refresh-support)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/8f4009b0-65bd-4480-9b00-e201f0914bb3/llms.txt) for all pages in this wiki.
