Build Tools — Turbopack
Turbopack is an incremental bundler developed by the Vercel team, designed specifically for Next.js. Announced in October 2022 at Next.js Conf, Turbopack represents a ground-up rethinking of how a bundler should work in the modern era. Written in Rust, it leverages incremental computation — the same paradigm that powers build systems like Bazel and Nx.
The key insight behind Turbopack is that most bundlers throw away intermediate computation results after each build. Turbopack caches and reuses these results, meaning subsequent builds (and even cold starts) are dramatically faster. Early benchmarks show 10x faster HMR updates compared to Webpack and 4x faster cold starts compared to Vite.
Turbopack is not a Webpack replacement in the traditional sense. It is a purpose-built bundler for Next.js that focuses on two things: speed and correctness. Unlike Webpack, which evolved over a decade and carries significant architectural debt, Turbopack was designed from scratch to handle the specific patterns that Next.js applications use.
- Rust core — Written in Rust for performance and memory safety.
- Incremental by design — Every computation is cached and reused.
- Next.js native — Built specifically for the Next.js framework.
- Function-level caching — Caches at the function level, not the file level.
- Lazy compilation — Only compiles modules that are actually requested.
info
Turbopack's architecture is fundamentally different from JavaScript-based bundlers. It uses a multi-threaded Rust core with a plugin system that allows extending behavior without sacrificing performance.
| 1 | // Turbopack's architecture in a Next.js project |
| 2 | // next.config.js — opt in to Turbopack |
| 3 | const nextConfig = { |
| 4 | // Enable Turbopack for development |
| 5 | // (experimental in Next.js 14, stable in 15+) |
| 6 | experimental: { |
| 7 | turbo: { |
| 8 | // Custom loaders (analogous to Webpack loaders) |
| 9 | loaders: { |
| 10 | ".svg": ["@svgr/webpack"], |
| 11 | }, |
| 12 | // Resolve aliases |
| 13 | resolveAlias: { |
| 14 | "@": "./src", |
| 15 | }, |
| 16 | // Custom rules for module graph |
| 17 | rules: { |
| 18 | "*.mdx": ["@mdx-js/loader"], |
| 19 | }, |
| 20 | // Tree-shaking options |
| 21 | treeShaking: true, |
| 22 | }, |
| 23 | }, |
| 24 | }; |
| 25 | |
| 26 | export default nextConfig; |
warning
The core innovation in Turbopack is incremental computation. Instead of re-executing the entire build pipeline on every change, Turbopack tracks function inputs and only re-executes the minimal subset of computations whose inputs have changed.
| 1 | // Conceptual model of incremental computation |
| 2 | // Traditional bundler flow (every change = full rebuild): |
| 3 | function build() { |
| 4 | const source = readFiles(); // Always reads all files |
| 5 | const parsed = parse(source); // Always parses all files |
| 6 | const transformed = transform(parsed); // Always transforms |
| 7 | const bundled = bundle(transformed); // Always bundles |
| 8 | const optimized = optimize(bundled); // Always optimizes |
| 9 | return optimized; |
| 10 | } |
| 11 | |
| 12 | // Incremental computation flow: |
| 13 | function build(query) { |
| 14 | // Only re-executes functions whose cache key changed |
| 15 | const source = memo(readFiles, [query.files]); |
| 16 | const parsed = memo(parse, [source]); // Cache hit: skip |
| 17 | const transformed = memo(transform, [parsed]); // Cache hit: skip |
| 18 | const bundled = memo(bundle, [transformed]); // Only re-bundle |
| 19 | const optimized = memo(optimize, [bundled]); // Changed? Re-run |
| 20 | return optimized; |
| 21 | } |
| 22 | |
| 23 | // When one file changes: |
| 24 | // - readFiles: re-reads the changed file |
| 25 | // - parse: re-parses only the changed file |
| 26 | // - transform: re-transforms only the changed file |
| 27 | // - bundle: partially re-bundles affected modules |
| 28 | // - optimize: may skip entirely if nothing changed |
info
Enabling Turbopack in Next.js is a simple flag change. The --turbo flag switches the dev server's bundler from Webpack to Turbopack.
| 1 | # Enable Turbopack in Next.js dev server |
| 2 | next dev --turbo |
| 3 | |
| 4 | # With npm scripts in package.json |
| 5 | { |
| 6 | "scripts": { |
| 7 | "dev": "next dev --turbo", |
| 8 | "build": "next build", |
| 9 | "start": "next start" |
| 10 | } |
| 11 | } |
| 12 | |
| 13 | # Verify Turbopack is active — look for this in dev output: |
| 14 | # ▲ Next.js 14.x (Turbopack) — notice "(Turbopack)" indicator |
| 15 | # ready - started server on 0.0.0.0:3000, url: http://localhost:3000 |
| 16 | |
| 17 | # The dev server should feel noticeably faster: |
| 18 | # - Cold start: ~50ms vs ~300ms with Webpack |
| 19 | # - HMR updates: ~10ms vs ~100ms with Webpack |
| 20 | # - Page reload: ~100ms vs ~500ms with Webpack |
warning
Understanding the tradeoffs between bundlers helps you choose the right tool for your project. Here is how Turbopack compares.
| Aspect | Turbopack | Webpack | Vite |
|---|---|---|---|
| Language | Rust | JavaScript | JavaScript + Go (esbuild) |
| Cold start | Very fast | Slow | Fast |
| HMR | Function-level | Module-level | ESM native |
| Plugin ecosystem | Limited (new) | Largest | Growing |
| Production build | Beta | Mature | Rollup-based |
| Framework support | Next.js only | Any (generic) | Any (framework agnostic) |
| Maturity | Early (2023+) | Very mature (2012+) | Mature (2020+) |
info
Turbopack is under active development and has several limitations compared to Webpack. Understanding these helps you decide whether to adopt it now or wait for maturity.
- Limited plugin support — Many Webpack loaders are not yet supported. Migration requires a loader compatibility check.
- Next.js only — Turbopack cannot be used outside Next.js. It is not a general-purpose bundler.
- Production builds in beta — The production build pipeline using Turbopack (experimental.turbopack.build) is still experimental.
- Windows performance — Early reports indicate slower performance on Windows compared to macOS and Linux.
- Memory usage — Incremental caching can consume significant memory for large projects.
warning
Turbopack configuration lives inside next.config.js under the experimental.turbo key. While the API is more limited than Webpack's, it covers the most common customization needs.
| 1 | // next.config.js — Turbopack configuration options |
| 2 | const nextConfig = { |
| 3 | experimental: { |
| 4 | turbo: { |
| 5 | // Custom loaders — use instead of webpack.rules |
| 6 | loaders: { |
| 7 | ".mdx": ["@mdx-js/loader"], |
| 8 | ".yaml": ["yaml-loader"], |
| 9 | ".graphql": ["graphql-tag/loader"], |
| 10 | }, |
| 11 | |
| 12 | // Resolve aliases — use instead of webpack.alias |
| 13 | resolveAlias: { |
| 14 | "@": "./src", |
| 15 | "@components": "./src/components", |
| 16 | "@lib": "./src/lib", |
| 17 | "@styles": "./src/styles", |
| 18 | }, |
| 19 | |
| 20 | // Module rules — for custom transformation |
| 21 | rules: { |
| 22 | // Match by glob pattern |
| 23 | "*.svg": { |
| 24 | loaders: ["@svgr/webpack"], |
| 25 | as: "*.js", |
| 26 | }, |
| 27 | // Match node_modules pattern |
| 28 | "node_modules/**/*.css": { |
| 29 | loaders: ["style-loader", "css-loader"], |
| 30 | }, |
| 31 | }, |
| 32 | |
| 33 | // Tree-shaking config |
| 34 | treeShaking: true, |
| 35 | |
| 36 | // Module resolution |
| 37 | resolve: { |
| 38 | extensions: [".tsx", ".ts", ".jsx", ".js", ".json"], |
| 39 | }, |
| 40 | }, |
| 41 | }, |
| 42 | }; |
| 43 | |
| 44 | export default nextConfig; |
- Use --turbo early — Enable Turbopack at the start of development to identify compatibility issues before your codebase grows large.
- Test loaders individually — When migrating custom loaders, add them one at a time and verify build correctness after each addition.
- Monitor memory — If you encounter high memory usage, consider disabling specific loaders or reducing the scope of incremental caching.
- Stay on supported Next.js versions — Only use Turbopack with the Next.js versions that officially support it (14.1+ for basic, 15+ for extended).
- Keep Webpack config as fallback — Maintain a working Webpack configuration in case you need to disable Turbopack temporarily.
info