Module A-11·26 min read

Why Turbopack replaced Webpack, incremental computation model, SWC transforms, turbopack config and filesystem cache, module graph anatomy, diagnosing OOM build failures, and pageExtensions for non-standard project layouts.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

A-11 — Build Engine Internals: Turbopack, SWC, and Memory Optimisation

Who this is for: Architects who want to understand what happens between npm run build and the deployable output — how Turbopack replaced Webpack, why SWC is faster than Babel, how the module graph is constructed, and how to diagnose and fix build performance problems that appear when a codebase scales.


Why the Build Stack Changed

For four years, Next.js used Webpack 5 as its bundler and Babel as its JavaScript transformer. Both were fine at small scale. Both had known limitations at large scale:

Webpack's problem: Webpack rebuilds the module graph on every save. In a large application, the graph might have 10,000 modules. Even incremental builds re-analyse significant portions of this graph. Teams with large codebases saw 30-60 second hot reload times.

Babel's problem: Babel is written in JavaScript and processes files one-at-a-time. TypeScript type stripping, JSX transformation, decorator transforms — Babel does each file sequentially. SWC does the same transformations in Rust, parallelised across all CPU cores, 10-100x faster.

The replacement strategy: SWC for JavaScript/TypeScript transformation (already the default in Next.js 12+), Turbopack for bundling (stable in Next.js 15 for development, nearing stability for production).


SWC — The Transformation Layer

SWC (Speedy Web Compiler) is a Rust-based JavaScript/TypeScript compiler. It replaced Babel as Next.js's transform layer in version 12.

What SWC handles:

  • TypeScript → JavaScript (type stripping, not type checking)
  • JSX → React.createElement calls
  • ES2022+ → target ES version
  • Import path transforms (absolute imports, module aliases)
  • Emotion/styled-components transforms (when configured)
  • React Compiler transforms (when enabled)

What SWC does not do:

  • Type checking (that's tsc --noEmit, run separately in CI)
  • Bundling (that's Webpack or Turbopack)
  • Custom Babel plugins (Babel is no longer in the chain when SWC is active)

The custom Babel plugin problem: if your project uses a Babel plugin that SWC doesn't have a native equivalent for, you have to keep Babel in the chain — which means losing SWC's speed advantage for those transforms. This is why teams with custom Babel plugins see slower builds than teams that migrated fully.

ts

For styled-components and Emotion, SWC has built-in transforms that are faster than the Babel plugins:

ts

Turbopack — The Bundler Replacement

Turbopack (also written in Rust) is the replacement for Webpack. Its architectural difference: incremental computation with fine-grained caching.

Webpack's model: build the entire module graph, apply transforms, produce bundles. Incremental builds re-analyse changed modules and their transitive dependents.

Turbopack's model: every module and every function on every module is a cacheable unit of computation. When a file changes, only the computation units that depend on that specific file are re-evaluated. The cache is persistent across restarts — a restart after Turbopack has warmed its cache is nearly as fast as a hot reload.

The practical result: a codebase that took 30 seconds for a hot reload with Webpack might take 500ms with Turbopack, because Turbopack doesn't re-evaluate the 9,800 modules that didn't change.

Enable Turbopack for development:

bash

Turbopack is the default for next dev in Next.js 15. For next build (production), Turbopack is still in progress — production builds use Webpack by default until Turbopack production build reaches parity.


Turbopack Configuration

Turbopack configuration lives in next.config.ts under the turbopack key:

ts

The Webpack loader compatibility note: Turbopack cannot use Webpack loaders directly. If your project uses custom Webpack loaders (SVG transforms, MDX loaders, etc.), you need to find or create Turbopack-compatible versions. This is the primary migration blocker for complex projects.


pageExtensions — Customising Which Files Are Routable

Next.js decides what counts as a page, layout, or route handler partly by file extension. The default list is ['tsx', 'ts', 'jsx', 'js'] — any file with one of those extensions in the right location (app/page.tsx, pages/about.js, etc.) is treated as routable. pageExtensions in next.config.ts lets you change that list:

ts

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.