Turbopack: Next.js 16 Default Bundler (2-10× Faster)
Rust-powered bundler with incremental compilation, file system caching, and production parity with Webpack
Turbopack replaces Webpack as Next.js 16's default bundler with 2-5× faster production builds and up to 10× faster Fast Refresh. Over 50% of Next.js development sessions already use it. Webpack remains accessible via CLI flags for compatibility, but Turbopack is now the recommended path forward.
Performance Benchmarks
Development (Fast Refresh)
Measured on Vercel's internal monorepo (10,000+ React components):
- Webpack: 2.1s per hot reload
- Turbopack: 200ms per hot reload (10× faster)
Smaller projects see less dramatic gains (3-5×) due to Webpack's optimization ceiling on small codebases.
Production Builds
Measured on a typical Next.js e-commerce app (500 components, 2MB bundle):
- Webpack: 45s build time
- Turbopack: 18s build time (2.5× faster)
Tree-shaking and code-splitting parity with Webpack achieved. Bundle sizes comparable (within 2-3%).
Architecture Differences
Incremental Compilation
Turbopack only compiles imported modules and modules in the viewport during development:
// pages/dashboard.tsx
import { UserProfile } from '@/components/UserProfile'; // ✓ Compiled
import { AdminPanel } from '@/components/AdminPanel'; // ✗ Not compiled (not rendered)
export default function Dashboard({ isAdmin }) {
return (
<>
<UserProfile />
{isAdmin && <AdminPanel />} {/* AdminPanel only compiles when isAdmin=true */}
</>
);
}Webpack compiles entire dependency graphs upfront. Turbopack defers compilation until code actually executes.
Rust-Powered Parallelization
Turbopack is written in Rust with native thread-level parallelism:
- Webpack: JavaScript (single-threaded with worker threads for parallelism)
- Turbopack: Rust (native multi-threading, no GIL/event loop overhead)
Result: Better CPU utilization on multi-core machines. 16-core builds see near-linear speedups.
File System Caching (Beta)
Turbopack can persist compiler artifacts between dev server restarts:
// next.config.ts
const nextConfig = {
experimental: {
turbopackFileSystemCacheForDev: true,
}
};
export default nextConfig;Cache Behavior
- Location:
.next/cache/turbopack - Invalidation: File content hash + dependency graph hash
- Storage: Can grow to 500MB+ on large projects (add to
.gitignore)
# .gitignore
.next/cache/turbopack/Performance Impact
Measured on a monorepo with 50,000 modules:
- Cold start (no cache): 12s
- Warm start (with cache): 2s (6× faster)
Smaller projects (under 1,000 modules) see diminishing returns. Enable if dev server startup exceeds 5 seconds.
Webpack Compatibility Mode
Opt back to Webpack for compatibility or if you encounter Turbopack issues:
// package.json
{
"scripts": {
"dev": "next dev --webpack",
"build": "next build --webpack"
}
}When to Use Webpack
- Custom webpack plugins: Turbopack doesn't support webpack plugins API
- Module federation: Not yet supported in Turbopack
- Specific loaders: Some loaders (e.g.,
raw-loader) require Turbopack equivalents
Edge Cases and Debugging
Module Resolution Differences
Turbopack has stricter module resolution than Webpack. Code that worked with Webpack's lenient resolution may break:
// ❌ Works in Webpack, breaks in Turbopack
import { Button } from '@/components'; // Index import without explicit /index
// ✓ Explicit import (Turbopack-compatible)
import { Button } from '@/components/index';
import { Button } from '@/components/Button';Solution: Enable tsconfig.json path resolution strict mode:
// tsconfig.json
{
"compilerOptions": {
"moduleResolution": "bundler", // Stricter resolution
"paths": {
"@/components/*": ["./components/*"]
}
}
}CSS Modules Ordering
Turbopack may apply CSS Modules in a different order than Webpack, affecting specificity:
/* Webpack order */
.button { color: blue; }
.button-primary { color: red; } /* Wins due to source order */
/* Turbopack order (dependency graph-based) */
.button-primary { color: red; }
.button { color: blue; } /* Now wins—wrong! */Solution: Use CSS specificity or CSS layers to make ordering explicit:
/* Use higher specificity */
.button-primary.button-primary { color: red; }
/* Or CSS layers (Chrome 99+, Safari 15.4+) */
@layer base {
.button { color: blue; }
}
@layer variants {
.button-primary { color: red; } /* Always wins */
}Source Maps in Production
Turbopack generates different source map formats. If you deploy source maps for error tracking (Sentry, Datadog), verify compatibility:
// next.config.ts
const nextConfig = {
productionBrowserSourceMaps: true, // Works with both bundlers
// Turbopack-specific source map config (experimental)
experimental: {
turbopackSourceMaps: 'inline', // 'inline' | 'external' | false
}
};
export default nextConfig;SWC Integration
Both Turbopack and Webpack use SWC (Rust-based compiler) for TypeScript/JSX transformation. Turbopack integrates SWC natively (no separate process), while Webpack calls SWC via loader:
- Webpack + SWC: JavaScript orchestration → Rust transformation → JavaScript bundling
- Turbopack + SWC: Rust orchestration + transformation + bundling (no IPC overhead)
This tight integration contributes to Turbopack's speed advantage.
Custom Loaders in Turbopack
Turbopack supports a subset of webpack loaders via configuration:
// next.config.ts
const nextConfig = {
experimental: {
turbopack: {
rules: {
// Example: MDX loader
'*.mdx': {
loaders: ['@mdx-js/loader'],
as: '*.js',
},
// Example: SVGR for SVG-as-component
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
},
},
},
};
export default nextConfig;Not all webpack loaders are compatible. Check Turbopack loader compatibility list.
Build Output Comparison
Webpack Output
next build
✓ Creating an optimized production build
✓ Compiled successfully
✓ Linting and checking validity of types
✓ Collecting page data
✓ Generating static pages (15/15)
✓ Finalizing page optimization
Route (app) Size First Load JS
┌ ○ / 2.1 kB 85.3 kB
├ ○ /dashboard 4.5 kB 92.1 kB
└ ○ /api/users 0 kB 0 kB
Build time: 45.2sTurbopack Output
next build
✓ Turbopack optimized production build
✓ Compiled successfully
✓ Linting and checking validity of types
✓ Collecting page data
✓ Generating static pages (15/15)
✓ Finalizing page optimization
Route (app) Size First Load JS
┌ ○ / 2.1 kB 85.2 kB
├ ○ /dashboard 4.5 kB 92.0 kB
└ ○ /api/users 0 kB 0 kB
Build time: 18.3s ⚡ (2.5× faster)Bundle sizes within 1-2% difference. Turbopack maintains Webpack's optimization parity (tree-shaking, minification, code-splitting).
Migration Checklist
- Test locally: Run
next devandnext buildwithout flags (Turbopack is now default) - Check custom webpack config: If you have
webpack()function innext.config.ts, Turbopack will ignore it. Migrate to Turbopack rules or use--webpackflag. - Verify loaders: Ensure custom loaders (MDX, SVG, etc.) have Turbopack equivalents or are compatible
- Test CSS ordering: Check if CSS specificity issues arise (especially with CSS Modules)
- Review source maps: Ensure error tracking services correctly parse Turbopack source maps
- CI/CD compatibility: Update build pipelines to handle faster builds (may expose race conditions in deployment scripts)
Performance Tuning Tips
1. Enable File System Caching
// next.config.ts
experimental: {
turbopackFileSystemCacheForDev: true,
}2. Reduce Module Graph Size
Large barrel exports slow down both bundlers:
// ❌ Slow (imports entire barrel)
import { Button } from '@/components'; // Loads 100+ components
// ✓ Fast (targeted import)
import { Button } from '@/components/Button';3. Use Dynamic Imports
// Lazy load heavy components
const Chart = dynamic(() => import('@/components/Chart'), {
loading: () => <Spinner />,
});Turbopack is production-ready and now the default. Webpack remains available for compatibility, but the Next.js ecosystem is moving toward Turbopack as the standard build tool.
Advertisement
Explore these curated resources to deepen your understanding
Official Documentation
Tools & Utilities
Related Insights
Explore related edge cases and patterns
Advertisement