Introduction to Turbopack
Turbopack is a high-performance incremental bundler and build system for JavaScript and TypeScript applications, developed by Vercel. Created by the same team that built Webpack, Turbopack is designed to be the spiritual successor to Webpack, offering dramatically faster build times through Rust-based architecture and incremental computation. Whether you are building a small React application or a massive monorepo, Turbopack promises to transform your development experience.
What Is Turbopack?
At its core, Turbopack is an incremental bundler written in Rust. It leverages the Turbo engine, a low-level incremental computation framework, to cache and reuse work across builds. This means that when you change a single file, Turbopack only recomputes what is necessary, resulting in near-instant feedback during development.
Turbopack is not just a faster Webpack. It is a complete reimagining of how bundlers should work in a modern JavaScript ecosystem. It supports TypeScript out of the box, handles JSX and TSX files natively, and integrates seamlessly with Next.js.
Why Turbopack Matters
- Speed: Turbopack is up to 700x faster than Webpack for large applications and up to 10x faster than Vite for cold starts.
- Incremental computation: The Turbo engine caches function results, so repeated work is eliminated.
- Rust-based: Built in Rust for memory safety and performance without garbage collection pauses.
- Next.js integration: First-class support in Next.js 13+ for both development and production builds.
- Monorepo friendly: Designed to handle large codebases with thousands of modules efficiently.
Getting Started with Turbopack
Prerequisites
Before diving into Turbopack, ensure you have the following installed:
- Node.js 18.17 or later
- A package manager such as npm, yarn, or pnpm
- Basic familiarity with JavaScript or TypeScript
Using Turbopack with Next.js
The easiest way to start using Turbopack is through Next.js, where it is integrated as an opt-in feature. To enable Turbopack for local development, add the --turbo flag to your dev script.
{
"name": "my-turbopack-app",
"version": "1.0.0",
"scripts": {
"dev": "next dev --turbo",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "^14.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
Once you run npm run dev, Next.js will use Turbopack as the bundler. You should notice significantly faster startup times and near-instant hot module replacement (HMR).
Creating a Standalone Turbopack Project
If you want to use Turbopack outside of Next.js, you can install the @turbo/ packages directly. While the standalone API is still evolving, here is a basic setup that demonstrates how to configure Turbopack for a React application.
npm install @turbo/gen @turbo/webpack --save-dev
Create a turbo.config.js file in your project root:
// turbo.config.js
module.exports = {
pipeline: {
build: {
dependsOn: ["^build"],
outputs: ["dist/**"],
},
dev: {
cache: false,
persistent: true,
},
},
};
This configuration defines a task pipeline. The build task depends on upstream packages being built first, while dev runs persistently without caching.
Understanding the Turbo Engine
Incremental Computation Explained
The heart of Turbopack is the Turbo engine, which implements incremental computation through function-level caching. Every function in the build process is treated as a node in a graph. When inputs change, only the affected nodes are recomputed, and their results are cached for future use.
This approach is fundamentally different from traditional bundlers that reprocess entire dependency trees on every change. With Turbopack, if you modify a single CSS file, only the CSS processing and the final bundle assembly are rerun.
How Caching Works
Turbopack uses content-addressable caching. Each function's output is stored based on a hash of its inputs, including file contents, configuration, and environment variables. This means:
- Identical inputs always produce identical outputs.
- Cache hits are instant, even across different machines.
- Remote caching enables team-wide build acceleration.
Working with Turbopack in Next.js
Development Mode
In development mode, Turbopack handles compilation, bundling, and HMR. Here is a typical Next.js project structure that works with Turbopack:
my-app/
├── app/
│ ├── layout.tsx
│ ├── page.tsx
│ └── components/
│ └── Button.tsx
├── public/
├── next.config.js
├── package.json
└── tsconfig.json
Your next.config.js can include Turbopack-specific options:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
turbo: {
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
},
},
},
};
module.exports = nextConfig;
This configuration tells Turbopack to process SVG files using the SVGR loader, converting them into React components. The rules object is similar to Webpack's module rules but uses a simplified syntax.
Production Builds
As of Next.js 14, Turbopack is primarily recommended for development. However, you can experiment with Turbopack for production builds using the --turbo flag with the build command:
{
"scripts": {
"build": "next build --turbo"
}
}
Be aware that production support is still being stabilized. Always test your production builds thoroughly before deploying to production environments.
Advanced Configuration
Custom Loaders and Transpilers
Turbopack supports custom loaders for processing non-JavaScript assets. Here is an example that configures loaders for CSS modules, images, and Markdown files:
// next.config.js
const nextConfig = {
experimental: {
turbo: {
rules: {
'*.css': {
loaders: ['css-loader'],
},
'*.png': {
loaders: ['file-loader'],
as: '*.png',
},
'*.md': {
loaders: ['raw-loader'],
as: '*.js',
},
},
},
},
};
module.exports = nextConfig;
Environment Variables
Turbopack respects the same environment variable conventions as Next.js. Variables prefixed with NEXT_PUBLIC_ are exposed to the browser, while others remain server-side only.
// .env.local
DATABASE_URL=postgresql://localhost:5432/mydb
NEXT_PUBLIC_API_URL=https://api.example.com
Access these variables in your application as follows:
// app/page.tsx
export default function Page() {
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
return (
<main>
<h1>API Endpoint</h1>
<p>{apiUrl}</p>
</main>
);
}
Turbopack in Monorepos
Setting Up a Monorepo with Turborepo
Turbopack pairs naturally with Turborepo, Vercel's monorepo build system. Together, they provide end-to-end acceleration for large projects. Here is a sample monorepo structure:
my-monorepo/
├── apps/
│ ├── web/
│ │ ├── app/
│ │ ├── next.config.js
│ │ └── package.json
│ └── admin/
│ ├── app/
│ ├── next.config.js
│ └── package.json
├── packages/
│ ├── ui/
│ │ ├── components/
│ │ └── package.json
│ └── utils/
│ ├── lib/
│ └── package.json
├── turbo.json
├── package.json
└── pnpm-workspace.yaml
Configure turbo.json to define your task pipeline:
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", "dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"outputs": []
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
}
}
}
The ^build notation tells Turborepo to build dependencies before building the current package. This ensures that your shared UI components are compiled before your web app bundles them.
Remote Caching
One of the most powerful features of the Turbopack ecosystem is remote caching. By connecting your monorepo to Vercel's remote cache, builds can share cached results across team members and CI environments.
# Enable remote caching
npx turbo login
npx turbo link
Once linked, every task output is stored remotely. When a teammate runs the same task with the same inputs, the cached result is downloaded instead of recomputed.
Best Practices
1. Start with Development Mode
Begin by adopting Turbopack for development only. This gives you the immediate benefit of faster HMR and startup times without risking production stability. Once you are confident, gradually explore production builds.
2. Keep Dependencies Lean
Turbopack performs best when your dependency tree is manageable. Regularly audit your dependencies and remove unused packages. Fewer dependencies mean faster cold starts and smaller cache footprints.
3. Leverage Caching Strategically
Configure your turbo.json outputs carefully. Over-caching can bloat your cache storage, while under-caching forces unnecessary recomputation. Only cache directories that contain build artifacts, such as .next or dist.
4. Use Path Aliases
Path aliases improve both developer experience and Turbopack's module resolution performance. Define them in your tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"],
"@components/*": ["./components/*"],
"@lib/*": ["./lib/*"]
}
}
}
5. Monitor Bundle Size
Even with a fast bundler, large bundles hurt performance. Use the following Next.js configuration to enable bundle analysis:
// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
// your config here
});
Run ANALYZE=true npm run build to generate a visual report of your bundle composition.
6. Stay Updated
Turbopack is under active development. New features, performance improvements, and bug fixes ship regularly. Keep your dependencies updated to benefit from the latest optimizations:
npm update next @turbo/gen
Common Pitfalls and Troubleshooting
Unsupported Webpack Plugins
Some Webpack plugins are not yet supported in Turbopack. If you rely on custom Webpack plugins, check the Turbopack compatibility list before migrating. Common alternatives include using Turbopack's built-in rules or finding Turbopack-compatible equivalents.
Cache Invalidation Issues
If you notice stale builds, clear the Turbopack cache:
rm -rf .next
rm -rf node_modules/.cache
For Turborepo, you can also force a clean build:
npx turbo run build --force
Memory Usage in Large Projects
For very large monorepos, Turbopack may consume significant memory. Increase the Node.js memory limit:
NODE_OPTIONS="--max-old-space-size=8192" npm run dev
Migration from Webpack to Turbopack
Step-by-Step Migration
If you have an existing Next.js project using Webpack, migration to Turbopack is straightforward for development:
Step 1: Update Next.js to version 13.5 or later.
npm install next@latest
Step 2: Add the --turbo flag to your dev script.
"scripts": {
"dev": "next dev --turbo"
}
Step 3: Move any custom Webpack configuration to Turbopack rules.
// Before (Webpack)
module.exports = {
webpack: (config) => {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'],
});
return config;
},
};
// After (Turbopack)
module.exports = {
experimental: {
turbo: {
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
},
},
},
};
Step 4: Test your application thoroughly. Most standard Next.js features work out of the box, but custom configurations may require adjustments.
Conclusion
Turbopack represents a significant leap forward in the JavaScript tooling ecosystem. By combining Rust-based performance with incremental computation and intelligent caching, it addresses the pain points that developers have faced with traditional bundlers for years. Whether you are starting a new project or migrating an existing one, adopting Turbopack for development can dramatically improve your developer experience with faster builds, instant HMR, and scalable monorepo support. As the project matures and production support stabilizes, Turbopack is poised to become the default bundler for modern web applications. Start experimenting today, follow best practices, and stay engaged with the community to get the most out of this powerful tool.