Turbopack 是 Vercel 团队用 Rust 从头打造的增量式打包工具,目标是成为 Webpack 的继任者。它在 Next.js 13 中首次亮相,到了 Next.js 15 已经成为开发环境的默认打包器。
官方宣称的数据相当夸张:比 Webpack 快 700 倍,比 Vite 快 10 倍。这个数字后来引发了一些争议(尤雨溪还专门写文章反驳过),实际差距没那么大,但 Turbopack 确实快,尤其在大型项目里优势明显。
为什么要造一个新轮子#
Webpack 已经十多年了,生态成熟、功能强大,但它有个根本性问题:用 JavaScript 写的打包器去处理 JavaScript 项目,性能天花板摆在那里。
你可能经历过这种场景:一个几百个组件的 React 项目,npm run dev 等个三四十秒才能看到页面,改一行代码又得等好几秒才能热更新。项目越大,这个问题越严重。
Vite 用 esbuild 解决了开发环境的冷启动问题,但热更新还是基于 ESM 的原生机制,大项目里请求瀑布流会拖慢速度。
Turbopack 的思路是:用 Rust 重写整个打包流程,同时引入函数级缓存和增量计算,把性能问题从根本上解决掉。
核心架构#
Turbopack 的设计有几个关键点:
统一依赖图#
传统打包器在处理 SSR 项目时,需要分别构建客户端和服务端的代码,维护两套依赖图。Turbopack 用一个统一的依赖图来管理所有输出目标,减少重复计算。
┌─────────────────────────────────────┐│ 统一依赖图 (Unified Graph) │├─────────────────────────────────────┤│ 源代码 → 解析 → 转换 → 分析依赖 ││ ↓ ││ ┌──────────┴──────────┐ ││ ↓ ↓ ││ 客户端产物 服务端产物 │└─────────────────────────────────────┘增量计算引擎#
这是 Turbopack 最核心的能力。它把构建过程拆分成无数个细粒度的函数调用,每个函数的输入输出都被缓存起来。下次构建时,只有输入变化的函数才会重新执行。
举个例子,你改了 Button.tsx,Turbopack 只需要重新处理这个文件以及依赖它的文件,其他几百个组件的处理结果直接从缓存里拿。
懒编译#
开发环境下,Turbopack 不会一上来就把整个项目都编译一遍。它只编译浏览器实际请求到的代码。你打开首页,它只编译首页用到的模块;你点进详情页,才去编译详情页的代码。
这个策略让大型项目的冷启动时间大幅下降。
在 Next.js 中使用#
Next.js 15+#
从 Next.js 15 开始,开发环境默认就是 Turbopack,不需要任何配置:
# 创建新项目npx create-next-app@latest my-appcd my-app
# 启动开发服务器(自动使用 Turbopack)npm run dev如果你想用回 Webpack,需要显式指定:
{ "scripts": { "dev": "next dev --webpack" }}Next.js 13/14#
老版本需要手动开启:
{ "scripts": { "dev": "next dev --turbo" }}或者在 next.config.js 里配置:
/** @type {import('next').NextConfig} */const nextConfig = { experimental: { turbo: {}, },}
module.exports = nextConfig生产构建#
截至 2025 年初,Turbopack 的生产构建还在 beta 阶段。如果你想尝试:
# 使用 Turbopack 进行生产构建(beta)next build --turbo不过目前生产环境还是建议用 Webpack,等 Turbopack 稳定后再切换。
配置详解#
Turbopack 的配置写在 next.config.js 的 turbo 字段里。
自定义 Loader#
Turbopack 不兼容 Webpack 的 loader,但提供了自己的 loader 机制:
module.exports = { experimental: { turbo: { rules: { // 处理 SVG 文件 '*.svg': { loaders: ['@svgr/webpack'], as: '*.js', }, // 处理 GraphQL 文件 '*.graphql': { loaders: ['graphql-tag/loader'], as: '*.js', }, }, }, },}路径别名#
module.exports = { experimental: { turbo: { resolveAlias: { // 用 lodash-es 替换 lodash 'lodash': 'lodash-es', // 自定义模块别名 '@components': './src/components', '@utils': './src/utils', }, }, },}扩展名解析#
module.exports = { experimental: { turbo: { resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.mjs', '.json'], }, },}环境变量#
Turbopack 对环境变量的处理和 Webpack 一致,支持 .env 文件:
NEXT_PUBLIC_API_URL=https://api.example.comDATABASE_URL=postgresql://localhost:5432/mydb客户端只能访问 NEXT_PUBLIC_ 前缀的变量。
实战:从 Webpack 迁移#
假设你有一个现有的 Next.js 项目,想切换到 Turbopack。
检查兼容性#
先跑一下开发服务器,看看有没有报错:
npx next dev --turbo常见的问题:
- Webpack loader 不兼容
Turbopack 不支持 Webpack 的 loader。如果你用了 sass-loader、less-loader 这类,需要换成 Turbopack 的配置方式。
好消息是,Next.js 内置了对 CSS/Sass/Less 的支持,大部分情况下不需要额外配置。
- 自定义 Webpack 配置失效
next.config.js 里的 webpack 函数在 Turbopack 模式下会被忽略。需要把配置迁移到 turbo 字段。
原来的配置:
module.exports = { webpack: (config) => { config.resolve.alias = { ...config.resolve.alias, '@': './src', } return config },}迁移后:
module.exports = { experimental: { turbo: { resolveAlias: { '@': './src', }, }, },}- 第三方包的问题
有些包可能没有正确的 ESM 导出,Turbopack 会报错。可以用 resolveAlias 指向兼容的版本,或者等包作者修复。
性能对比测试#
切换后可以跑个对比,看看提升有多大:
# 测试冷启动时间time npx next dev --webpack &# 等服务器启动后 Ctrl+C
time npx next dev --turbo &# 等服务器启动后 Ctrl+C在一个 200+ 组件的项目里,我自己测试的结果:
| 指标 | Webpack | Turbopack | 提升 |
|---|---|---|---|
| 冷启动 | 28s | 8s | 71% |
| 热更新 | 1.2s | 0.15s | 87% |
| 内存占用 | 1.8GB | 0.9GB | 50% |
你的项目数据肯定会有差异,但大方向是一致的。
当前限制#
Turbopack 还在快速迭代,有些功能暂时不支持:
不支持的功能#
- 部分 Webpack 插件:自定义 Webpack 插件无法使用,需要等官方提供替代方案
- Monaco Editor:这个富文本编辑器目前有兼容问题
- 某些 CSS-in-JS 方案:styled-components 和 emotion 可以用,但一些冷门库可能有问题
- 自定义 SWC 配置:
.swcrc文件会被忽略
生产构建的状态#
虽然 next build --turbo 可以用,但还是 beta 版。已知问题:
- 产物体积可能略大于 Webpack
- 某些边界情况的代码分割不够理想
- 缺少部分高级优化选项
生产环境暂时还是用 Webpack 更稳妥。
与其他工具的对比#
vs Webpack#
| 对比项 | Webpack | Turbopack |
|---|---|---|
| 语言 | JavaScript | Rust |
| 生态 | 非常成熟 | 发展中 |
| 冷启动 | 慢(大项目尤其明显) | 快 |
| 热更新 | 中等 | 非常快 |
| 配置 | 复杂但灵活 | 简单但选项少 |
| 适用场景 | 任何项目 | Next.js 项目 |
vs Vite#
| 对比项 | Vite | Turbopack |
|---|---|---|
| 开发服务器 | 基于 ESM,esbuild 预构建 | Rust 全量打包 |
| 热更新 | 快(但大项目会变慢) | 非常快(大项目优势明显) |
| 框架支持 | Vue/React/Svelte 等 | 仅 Next.js |
| 生产构建 | Rollup | 仍在开发 |
| 上手难度 | 简单 | 更简单(开箱即用) |
如果你用 Next.js,Turbopack 是更好的选择。如果用其他框架,Vite 仍然是开发体验的标杆。
vs esbuild#
esbuild 单纯追求构建速度,不太关心开发体验。Turbopack 在速度和功能之间做了平衡,增量计算和懒编译都是为开发体验服务的。
调试与问题排查#
查看构建详情#
# 开启详细日志NEXT_TURBOPACK_TRACING=1 next dev --turbo常见问题#
1. 模块找不到
Error: Cannot find module 'xxx'检查 resolveAlias 和 resolveExtensions 配置,确保路径正确。
2. 样式不生效
Turbopack 对 CSS Modules 的处理略有不同。确保文件名是 *.module.css 格式,并且用正确的导入方式:
// 正确import styles from './Button.module.css'
// 错误import './Button.module.css'3. 热更新不触发
检查文件是否在 .gitignore 或 .turboignore 里被忽略了。Turbopack 会跳过这些文件。
4. 内存不够
Turbopack 虽然比 Webpack 省内存,但大项目还是会吃不少。如果遇到 OOM,可以:
# 增加 Node.js 内存限制NODE_OPTIONS="--max-old-space-size=8192" next dev --turbo未来展望#
Vercel 的路线图很清晰:
- 2025 年:生产构建稳定版发布
- 长期目标:完全取代 Webpack,成为 Next.js 唯一的打包器
从目前的发展速度看,Turbopack 的成熟度在快速提升。如果你在用 Next.js,现在就可以在开发环境用起来了,等生产构建稳定后全面切换。
对于不用 Next.js 的项目,Turbopack 暂时还不是选项。Vercel 的精力主要放在 Next.js 生态,独立使用的支持优先级不高。这时候 Vite 仍然是更通用的选择。