Relevant source files
The following files were used as context for generating this wiki page:
- packages/next/src/build/webpack-config.ts
- packages/next/next-runtime.webpack-config.js
- packages/next/src/server/dev/hot-reloader-webpack.ts
- packages/next/src/build/webpack-build/impl.ts
- packages/next/taskfile.js
- packages/next/src/build/webpack/config/index.ts
- packages/next/src/build/webpack/config/blocks/base.ts
- packages/next/src/build/entries.ts
- packages/next/next-devtools.webpack-config.js
- packages/next/src/build/webpack-build/index.ts
- packages/next/src/build/webpack/plugins/middleware-plugin.ts
- packages/next/src/bundles/webpack/packages/webpack.js
- packages/next/src/build/webpack/config/utils.ts
- packages/next/src/bundles/webpack/packages/package.js
- packages/next/src/server/config-utils.ts
- packages/next/src/bundles/webpack/packages/sources.js
- packages/next/src/build/create-compiler-aliases.ts
- packages/next/src/build/webpack/config/blocks/css/index.ts
- packages/next/src/build/output/log.ts
- packages/next/src/build/webpack/config/blocks/css/loaders/client.ts
- packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts
- packages/next/src/server/lib/lru-cache.ts
- packages/next/src/shared/lib/get-rspack.ts
Overview
Next.js coordinates its build pipeline and development server by dynamically constructing compiler options Build Pipeline, Hot Reloading. The Webpack configuration system assembles specialized compilation targets across the browser client, Node.js server, and Edge Runtime environments Webpack Configuration. By chaining functional configuration blocksWebpack Configuration, it integrates SWC Compiler transformations Webpack Loaders, asset handling, and module aliasing Webpack Configuration. Adjacent manifest plugins and runtime builders consume these configuration outputs to generate application bundles, route loaders, and runtime artifacts Manifest Plugins, Route Discovery.
Sources: packages/next/src/build/webpack/config/index.ts:10-50, packages/next/src/build/webpack-config.ts:985-1007
Compiler target architecture
Compiler Environment Matrix
Next.js implements a multi-target compilation model that separates builds across three distinct environments: the Node.js server, the Edge Runtime server, and the browser client. During production compilation (webpackBuild), these targets are orchestrated sequentially or via worker threads in an ordered pipeline: server, edge-server, and client. Running the server compilers before the client compiler allows Next.js to track server/client component boundaries and dynamically inject client-side entry points discovered during server compilation.
Sources: packages/next/src/build/webpack-build/index.ts:14-18, packages/next/src/build/webpack-build/impl.ts:246-298
| Compiler Name | Target Environment | Key Configuration & External Handling |
|---|---|---|
server | Node.js Server | Presets node externals, applies handleExternals resolver, strips Node built-ins and Bun identifiers. |
edge-server | Edge Runtime | Configures edge polyfilled modules, party town fallbacks, and handleWebpackExternalForEdgeRuntime. |
client | Browser Client | Bundles React and user code for browser execution, registers React Refresh and telemetry plugins. |
Sources: packages/next/src/build/webpack-config.ts:987-1063, packages/next/src/build/webpack-build/impl.ts:175-203
Note
Server compilations execute prior to the client bundle so that client component entry points discovered via pluginState.injectedClientEntries can be accurately fed into the client compiler configuration.
Sources: packages/next/src/build/webpack-build/impl.ts:232-288
Base configuration composition
Functional Pipeline Assembly
The construction of a Webpack configuration in Next.js is orchestrated by buildConfiguration, an asynchronous function that instantiates a ConfigurationContext object and pipes the initial webpack.Configuration through an array of functional blocks Webpack Configuration. The context encapsulates configuration flags such as hasAppDir, isDevelopment, isServer, isEdgeRuntime, targetWeb, rootDirectory, transpilePackages, and experimental features Webpack Configuration.
Sources: packages/next/src/build/webpack/config/index.ts:10-82
The pipeline uses a utility function pipe that reduces an array of configuration modifier functions sequentially, supporting both synchronous and asynchronous operations Webpack Configuration. By default, buildConfiguration incorporates the base block and the css block, and conditionally appends the images block unless disableStaticImages is explicitly enabled Webpack Configuration.
| Function / Utility | File Path | Purpose |
|---|---|---|
buildConfiguration | packages/next/src/build/webpack/config/index.ts | Main entry point coordinating context setup and functional block piping. |
pipe | packages/next/src/build/webpack/config/utils.ts | Asynchronous function reducer executing configuration transforms in sequence. |
base | packages/next/src/build/webpack/config/blocks/base.ts | Curried block configuring mode, target, devtool, and source map plugins. |
Sources: packages/next/src/build/webpack/config/index.ts:10-82, packages/next/src/build/webpack/config/utils.ts:40-46, packages/next/src/build/webpack/config/blocks/base.ts:19-22
Note
The assetPrefix value normalized inside ConfigurationContext automatically strips any trailing slash from the provided input string to maintain consistent asset URL resolution across compilation targets.
Sources: packages/next/src/build/webpack/config/index.ts:62-66
Base Configuration Block & Source Map Strategy
The base configuration block, curried using lodash.curry, assigns fundamental Webpack properties based on the ConfigurationContext Webpack Configuration. It sets config.mode to 'development' or 'production' and determines config.name using constants from COMPILER_NAMES (server, edgeServer, or client) Webpack Configuration. For non-web targets, it specifies node18.17, aligning with the engine version defined in packages/next/package.json Webpack Configuration.
Source map generation within the base block adapts dynamically depending on development mode, runtime environment, and experimental flags Webpack Configuration.
| Condition | config.devtool Setting | Associated Plugin / Behavior |
|---|---|---|
ctx.isDevelopment | 'eval-source-map' (Webpack) / Forked plugin (Rspack) | Full-fidelity source maps with original variable names and columns for browser debugging. |
ctx.isEdgeRuntime (Production) | 'source-map' | Standard source map generation for edge runtime bundles. |
ctx.isServer && ctx.serverSourceMaps (Production) | 'source-map' | Enabled when server source maps are explicitly requested in configuration. |
ctx.productionBrowserSourceMaps && ctx.isClient (Production) | 'source-map' | Generates browser source maps for client production builds. |
| Default Production (Fallback) | false | Disables source map generation to reduce bundle size and compile overhead. |
Sources: packages/next/src/build/webpack/config/blocks/base.ts:36-54
Warning
When eval-source-map is active under Rspack or Webpack, the block resets config.devtool to false and explicitly injects either EvalSourceMapDevToolPlugin or getRspackCore().EvalSourceMapDevToolPlugin alongside DevToolsIgnorePlugin using path-ignoring rules.
Sources: packages/next/src/build/webpack/config/blocks/base.ts:67-86
Module aliasing and resolution
Custom Module Aliases and Path Resolution
Next.js sets up comprehensive compiler aliases via createWebpackAliases to map project roots, page directories, app directories, and internal framework assets. During development, custom application and error pages (_app, _error, _document) are resolved via array aliases that fall back to internal Next.js default templates if the user files are absent.
if (dev) {
const nextDistPath = 'next/dist/' + (isEdgeServer ? 'esm/' : '')
customAppAliases[`${PAGES_DIR_ALIAS}/_app`] = [
...(pagesDir
? pageExtensions.reduce((prev, ext) => {
prev.push(path.join(pagesDir, `_app.${ext}`))
return prev
}, [] as string[])
: []),
`${nextDistPath}pages/_app.js`,
]
customAppAliases[`${PAGES_DIR_ALIAS}/_error`] = [
...(pagesDir
? pageExtensions.reduce((prev, ext) => {
prev.push(path.join(pagesDir, `_error.${ext}`))
return prev
}, [] as string[])
: []),
`${nextDistPath}pages/_error.js`,
]
customDocumentAliases[`${PAGES_DIR_ALIAS}/_document`] = [
...(pagesDir
? pageExtensions.reduce((prev, ext) => {
prev.push(path.join(pagesDir, `_document.${ext}`))
return prev
}, [] as string[])
: []),
`${nextDistPath}pages/_document.js`,
]
}Sources: packages/next/src/build/create-compiler-aliases.ts:73-102
Client compilers map the instrumentation stub (private-next-instrumentation-client) to INSTRUMENTATION_CLIENT_STUB_PATH, and resolve user instrumentation through private-next-instrumentation-client-user with a fallback to private-next-empty-module (which is configured as false to create a Webpack no-op module).
| Alias Constant / Key | Target Path / Resolution Behavior |
|---|---|
@vercel/og$ | next/dist/server/og/image-response |
next/dist/server/ReactDOMServerPages | react-dom/server.edge (React 19) or react-dom/server.browser (React 18) |
styled-jsx/style$ | defaultOverrides['styled-jsx/style'] |
PAGES_DIR_ALIAS | User-defined pages directory (if present) |
APP_DIR_ALIAS | User-defined app directory (if present) |
ROOT_DIR_ALIAS | Absolute path to project root (dir) |
DOT_NEXT_ALIAS | Build output directory (distDir) |
setimmediate | next/dist/compiled/setimmediate |
Sources: packages/next/src/build/create-compiler-aliases.ts:105-252
Note
In browser bundles, createWebpackAliases iterates over browserVariantModules (generated from the filesystem) and maps every .js file under NEXT_PROJECT_ROOT_DIST to its .browser sibling to prevent server-only logic from leaking into client bundles.
Sources: packages/next/src/build/create-compiler-aliases.ts:176-187
Vendored React Runtimes and Layer Mapping
Next.js vendors its own React channels and maps react, react-dom, and react-server-dom-webpack depending on the target environment condition (browser, edge, or nodejs) and React condition (client or server). The function createVendoredReactAliases builds these mappings based on the active bundledReactChannel ('' or '-experimental') and layer constraints.
export function createVendoredReactAliases(
bundledReactChannel: BundledReactChannel,
{
layer,
isBrowser,
isEdgeServer,
reactProductionProfiling,
}: {
layer: WebpackLayerName
isBrowser: boolean
isEdgeServer: boolean
reactProductionProfiling: boolean
}
): CompilerAliases {
const environmentCondition = isBrowser
? 'browser'
: isEdgeServer
? 'edge'
: 'nodejs'
const reactCondition = shouldUseReactServerCondition(layer)
? 'server'
: 'client'
// ✅ Correct aliasSources: packages/next/src/build/create-compiler-aliases.ts:377-400
Server-only and client-only import guards are enforced via createServerOnlyClientOnlyAliases, which substitutes restricted packages with empty modules or compilation errors depending on whether the compiler runs on the server or client.
| Module Request | Server Target Resolution | Client Target Resolution |
|---|---|---|
server-only$ | next/dist/compiled/server-only/empty | next/dist/compiled/server-only/index |
client-only$ | next/dist/compiled/client-only/error | next/dist/compiled/client-only/index |
next/dist/compiled/server-only$ | next/dist/compiled/server-only/empty | next/dist/compiled/server-only/index |
next/dist/compiled/client-only$ | next/dist/compiled/client-only/error | next/dist/compiled/client-only/index |
Sources: packages/next/src/build/create-compiler-aliases.ts:254-274
Warning
If serverExternalPackages and transpilePackages contain overlapping package names, Webpack configuration initialization throws an error to prevent conflicting externalization and transpilation rules.
Sources: packages/next/src/build/webpack-config.ts:883-894
Style processing and font loaders
CSS Loader Pipelines and PostCSS Integration
The CSS configuration block processes style sheets via modular loader pipelines, supporting global CSS, CSS modules, Sass variants (.scss, .sass), and font optimization. The core function css handles rule generation using curried configuration pipelines. Sass files are preprocessed by sass-loader, which compiles proprietary syntax and passes through CSS imports with sourceMap: true, followed by resolve-url-loader to rewrite relative paths. PostCSS transformations are initialized lazily via lazyPostCSS, attaching legacy plugin compatibility and vendor helpers (postcss.vendor.prefix and postcss.vendor.unprefixed).
export async function lazyPostCSS(
rootDirectory: string,
supportedBrowsers: string[] | undefined,
disablePostcssPresetEnv: boolean | undefined,
useLightningcss: boolean | undefined
) {
if (!postcssInstancePromise) {
postcssInstancePromise = (async () => {
const postcss = require('postcss') as typeof import('postcss').default
// @ts-ignore backwards compat
postcss.plugin = function postcssPlugin(name, initializer) {
function creator(...args: any) {
let transformer = initializer(...args)
transformer.postcssPlugin = name
// transformer.postcssVersion = new Processor().version
return transformer
}
let cache: any
Object.defineProperty(creator, 'postcss', {
get() {
if (!cache) cache = creator()
return cache
},
})
creator.process = function (
css: any,
processOpts: any,
pluginOpts: any
) {
return postcss([creator(pluginOpts)]).process(css, processOpts)
}
return creator
}
// @ts-ignore backwards compat
postcss.vendor = {
/**
* Returns the vendor prefix extracted from an input string.
*
* @example
* postcss.vendor.prefix('-moz-tab-size') //=> '-moz-'
* postcss.vendor.prefix('tab-size') //=> ''
*/
prefix: function prefix(prop: string): string {
const match = prop.match(/^(-\w+-)/)
if (match) {
return match[0]
}
return ''
},
/**
* Returns the input string stripped of its vendor prefix.
*
* @example
* postcss.vendor.unprefixed('-moz-tab-size') //=> 'tab-size'
*/
unprefixed: function unprefixed(
/**
* String with or without vendor prefix.
*/
prop: string
): string {
return prop.replace(/^-\w+-/, '')
},
}Sources: packages/next/src/build/webpack/config/blocks/css/index.ts:58-128
Client-side style loading delegates to getClientStyleLoader, which inspects environment flags to determine whether to inject development style tags or production chunk extracts.
| Environment / Target Condition | Loader Used | Loader Options / Insertion Behavior |
|---|---|---|
Development (pages/ directory) | next-style-loader | Inserts style elements directly before the DOM anchor element #__next_css__DO_NOT_USE__ inside <head> |
Production or App Directory (isDevelopment: false or shouldEnableApp: true) | MiniCssExtractPlugin.loader | Sets publicPath to ${assetPrefix}/_next/ (or / if experimentalInlineCss is active) and esModule: false |
Sources: packages/next/src/build/webpack/config/blocks/css/loaders/client.ts:4-60
Note
MiniCssExtractPlugin disables ordering warnings (ignoreOrder: true) because Next.js guarantees safe CSS code-splitting through strict module scoping and single entrypoint global CSS constraints.
Sources: packages/next/src/build/webpack/config/blocks/css/index.ts:589-617
Rspack Core Checks and Font Extraction
When executing builds with Rspack (NEXT_RSPACK), style extraction utilizes Rspack's internal CSS plugin architecture. The resolution helper getRspackCore checks availability and logs experimental notices using a deduplicated LRU warning cache.
export function getRspackCore() {
warnRspack()
try {
// eslint-disable-next-line @next/internal/typechecked-require
return require('next-rspack/rspack-core')
} catch (e) {
if (e instanceof Error && 'code' in e && e.code === 'MODULE_NOT_FOUND') {
throw new Error(
'@rspack/core is not available. Please make sure `next-rspack` is correctly installed.'
)
}
throw e
}
}Sources: packages/next/src/shared/lib/get-rspack.ts:3-17
Font extraction rules match target files against Google and local font loader definitions, running getNextFontLoader to configure css-loader in pure mode alongside next-font-loader.
export function getNextFontLoader(
ctx: ConfigurationContext,
postcss: any,
fontLoaderPath: string
): webpack.RuleSetUseItem[] {
const loaders: webpack.RuleSetUseItem[] = []
if (ctx.isClient) {
// Add appropriate development mode or production mode style
// loader
loaders.push(
getClientStyleLoader({
hasAppDir: ctx.hasAppDir,
isDevelopment: ctx.isDevelopment,
assetPrefix: ctx.assetPrefix,
})
)
}
loaders.push({
loader: require.resolve('../../../../loaders/css-loader/src'),
options: {
postcss,
importLoaders: 1,
// Use CJS mode for backwards compatibility:
esModule: false,
url: (url: string, resourcePath: string) =>
cssFileResolve(url, resourcePath, ctx.experimental.urlImports),
import: (url: string, _: any, resourcePath: string) =>
cssFileResolve(url, resourcePath, ctx.experimental.urlImports),
modules: {
// Do not transform class names (CJS mode backwards compatibility):
exportLocalsConvention: 'asIs',
// Server-side (Node.js) rendering support:
exportOnlyLocals: ctx.isServer,
// Disallow global style exports so we can code-split CSS and
// not worry about loading order.
mode: 'pure',
getLocalIdent: (
_context: any,
_localIdentName: any,
exportName: string,
_options: any,
meta: any
) => {
// hash from next-font-loader
return `__${exportName}_${meta.fontFamilyHash}`
},
},
fontLoader: true,
},
})
loaders.push({
loader: 'next-font-loader',
options: {
isDev: ctx.isDevelopment,
isServer: ctx.isServer,
assetPrefix: ctx.assetPrefix,
deploymentId: ctx.deploymentId,
fontLoaderPath,
postcss,
},
})
return loadersSources: packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts:6-71
The following call chain demonstrates how Rspack core checks emit deduplicated warnings during style and font loader initialization:
csscallsgetNextFontLoadergetNextFontLoaderinvokesgetClientStyleLoadergetClientStyleLoaderevaluatesgetRspackCoregetRspackCoreexecuteswarnRspackwarnRspackinvokeswarnOncewarnOncequerieshason the internal LRU cache- If absent,
setadds the warning key toLRUNodestructures warndelegates toprefixedLogto render console outputs
export const css: (
ctx: ConfigurationContext
) => (config: webpack.Configuration) => Promise<webpack.Configuration> = curry(
async function css(ctx: ConfigurationContext, config: webpack.Configuration) {Sources: packages/next/src/build/webpack/config/blocks/css/index.ts:147-150, packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts:6-10, packages/next/src/build/webpack/config/blocks/css/loaders/client.ts:4-19, packages/next/src/shared/lib/get-rspack.ts:3-25, packages/next/src/build/output/log.ts:77-84
Caution
calculateSize functions passed to LRUCache must always return a positive integer greater than zero; returning zero causes unbounded cache growth because zero-size items are never evicted.
Sources: packages/next/src/server/lib/lru-cache.ts:130-135
Edge Runtime module constraints
Edge externals and polyfilled modules
For edge server compilation targets, Webpack configuration externally manages built-in packages and polyfills via custom external handlers and fallback definitions. Packages such as @builder.io/partytown and next/dist/compiled/etag resolve to empty objects ({}) to satisfy runtime requirements within lightweight V8 isolates.
...(isEdgeServer
? [
{
'@builder.io/partytown': '{}',
'next/dist/compiled/etag': '{}',
},
getEdgePolyfilledModules(),
handleWebpackExternalForEdgeRuntime,
]Sources: packages/next/src/build/webpack-config.ts:997-1005
Note
Edge server configurations exclude standard Node.js built-in modules from direct bundling, routing them instead through handleWebpackExternalForEdgeRuntime and specialized polyfills.
Sources: packages/next/src/build/webpack-config.ts:987-1007
Middleware plugin and unsupported Node APIs
The MiddlewarePlugin inspects module graphs and assets for Edge functions and middleware execution contexts. It enforces module constraints by checking usage against known edge-safe packages and tracking unsupported Node.js API usage.
const KNOWN_SAFE_DYNAMIC_PACKAGES =
require('../../../lib/known-edge-safe-packages.json') as string[]
Sources: packages/next/src/build/webpack/plugins/middleware-plugin.ts:41-43
Warning
Importing restricted Node.js core modules into edge runtime files triggers build errors via static analysis and unsupported API detection routines. Sources: packages/next/src/build/webpack/plugins/middleware-plugin.ts:14-16
Internal tooling configurations
Build-time runtime and devtools bundling
Next.js maintains dedicated configuration files (next-runtime.webpack-config.js and next-devtools.webpack-config.js) processed via task runner pipelines to compile internal runtimes, workers, and developer tools using Rspack core bindings and @rspack/core.
const webpack = require('@rspack/core')
const path = require('path')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const DevToolsIgnoreListPlugin = require('./webpack-plugins/devtools-ignore-list-plugin')Sources: packages/next/next-runtime.webpack-config.js:1-4
const path = require('path')
const webpack = require('@rspack/core')
const MODERN_BROWSERSLIST_TARGET = require('./src/shared/lib/modern-browserslist-target')
const DevToolsIgnoreListPlugin = require('./webpack-plugins/devtools-ignore-list-plugin')Sources: packages/next/next-devtools.webpack-config.js:1-4
| Bundle Type | Entry Point Path | Output Directory | Target / Mode |
|---|---|---|---|
app-page | dist/esm/server/route-modules/app-page/module.js | dist/compiled/next-server | node / dev or prod |
app-route | dist/esm/server/route-modules/app-route/module.js | dist/compiled/next-server | node / dev or prod |
pages | dist/esm/server/route-modules/pages/module.js | dist/compiled/next-server | node / dev or prod |
pages-api | dist/esm/server/route-modules/pages-api/module.js | dist/compiled/next-server | node / dev or prod |
server | dist/esm/server/next-server.js | dist/compiled/next-server | node / dev or prod |
use-cache-probe-worker | dist/esm/server/dev/use-cache-probe-worker.js | dist/compiled/next-server | node / dev or prod |
dev-validation-worker | dist/esm/server/dev/dev-validation-worker.js | dist/compiled/next-server | node / dev or prod |
next-devtools | src/next-devtools/entrypoint.ts | dist/compiled/next-devtools | browserslist / dev or prod |
Sources: packages/next/next-runtime.webpack-config.js:91-124, packages/next/next-runtime.webpack-config.js:205-214, packages/next/next-devtools.webpack-config.js:27-32
Note
The app-worker bundle category groups development validation and cache probe workers, dynamically resolving native SWC binding graphs from the installed runtime tree instead of bundling them under dist/esm.
Sources: packages/next/next-runtime.webpack-config.js:114-123, packages/next/next-runtime.webpack-config.js:160-172
Webpack hook aliasing and local resolution
Build scripts load custom hook aliases via loadWebpackHook to intercept webpack, webpack/package, webpack-sources, and associated compiler components, redirecting requests to Next.js compiled versions unless custom user Webpack environments are requested via environment variables.
export function loadWebpackHook(webpackProjectDir: string) {
if (installed) {
return
}
installed = true
const requireHook =
require('../server/require-hook') as typeof import('../server/require-hook')
const customWebpack = Boolean(process.env.NEXT_PRIVATE_LOCAL_WEBPACK)
if (customWebpack) {Sources: packages/next/src/server/config-utils.ts:3-12
const webpackAliases: [string, string][] = [
['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',
],
[
'webpack/lib/node/NodeEnvironmentPlugin.js',
'next/dist/compiled/webpack/NodeEnvironmentPlugin',
],
[
'webpack/lib/BasicEvaluatedExpression',
'next/dist/compiled/webpack/BasicEvaluatedExpression',
],Sources: packages/next/src/server/config-utils.ts:24-41
Warning
Setting NEXT_PRIVATE_LOCAL_WEBPACK forces project-level module resolution for Webpack dependencies, triggering unrecoverable build errors if the target project lacks an installed webpack package in its dependencies.
Sources: packages/next/src/server/config-utils.ts:11-22
Related
On This Page
OverviewCompiler target architectureCompiler Environment MatrixBase configuration compositionFunctional Pipeline AssemblyBase Configuration Block & Source Map StrategyModule aliasing and resolutionCustom Module Aliases and Path ResolutionVendored React Runtimes and Layer MappingStyle processing and font loadersCSS Loader Pipelines and PostCSS IntegrationRspack Core Checks and Font ExtractionEdge Runtime module constraintsEdge externals and polyfilled modulesMiddleware plugin and unsupported Node APIsInternal tooling configurationsBuild-time runtime and devtools bundlingWebpack hook aliasing and local resolutionRelated