Skip to content

Turbopack - Rust 驱动的下一代打包工具

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,不需要任何配置:

Terminal window
# 创建新项目
npx create-next-app@latest my-app
cd my-app
# 启动开发服务器(自动使用 Turbopack)
npm run dev

如果你想用回 Webpack,需要显式指定:

{
"scripts": {
"dev": "next dev --webpack"
}
}

Next.js 13/14#

老版本需要手动开启:

{
"scripts": {
"dev": "next dev --turbo"
}
}

或者在 next.config.js 里配置:

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
turbo: {},
},
}
module.exports = nextConfig

生产构建#

截至 2025 年初,Turbopack 的生产构建还在 beta 阶段。如果你想尝试:

Terminal window
# 使用 Turbopack 进行生产构建(beta)
next build --turbo

不过目前生产环境还是建议用 Webpack,等 Turbopack 稳定后再切换。

配置详解#

Turbopack 的配置写在 next.config.jsturbo 字段里。

自定义 Loader#

Turbopack 不兼容 Webpack 的 loader,但提供了自己的 loader 机制:

next.config.js
module.exports = {
experimental: {
turbo: {
rules: {
// 处理 SVG 文件
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
// 处理 GraphQL 文件
'*.graphql': {
loaders: ['graphql-tag/loader'],
as: '*.js',
},
},
},
},
}

路径别名#

next.config.js
module.exports = {
experimental: {
turbo: {
resolveAlias: {
// 用 lodash-es 替换 lodash
'lodash': 'lodash-es',
// 自定义模块别名
'@components': './src/components',
'@utils': './src/utils',
},
},
},
}

扩展名解析#

next.config.js
module.exports = {
experimental: {
turbo: {
resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.mjs', '.json'],
},
},
}

环境变量#

Turbopack 对环境变量的处理和 Webpack 一致,支持 .env 文件:

.env.local
NEXT_PUBLIC_API_URL=https://api.example.com
DATABASE_URL=postgresql://localhost:5432/mydb

客户端只能访问 NEXT_PUBLIC_ 前缀的变量。

实战:从 Webpack 迁移#

假设你有一个现有的 Next.js 项目,想切换到 Turbopack。

检查兼容性#

先跑一下开发服务器,看看有没有报错:

Terminal window
npx next dev --turbo

常见的问题:

  1. Webpack loader 不兼容

Turbopack 不支持 Webpack 的 loader。如果你用了 sass-loaderless-loader 这类,需要换成 Turbopack 的配置方式。

好消息是,Next.js 内置了对 CSS/Sass/Less 的支持,大部分情况下不需要额外配置。

  1. 自定义 Webpack 配置失效

next.config.js 里的 webpack 函数在 Turbopack 模式下会被忽略。需要把配置迁移到 turbo 字段。

原来的配置:

next.config.js
module.exports = {
webpack: (config) => {
config.resolve.alias = {
...config.resolve.alias,
'@': './src',
}
return config
},
}

迁移后:

next.config.js
module.exports = {
experimental: {
turbo: {
resolveAlias: {
'@': './src',
},
},
},
}
  1. 第三方包的问题

有些包可能没有正确的 ESM 导出,Turbopack 会报错。可以用 resolveAlias 指向兼容的版本,或者等包作者修复。

性能对比测试#

切换后可以跑个对比,看看提升有多大:

Terminal window
# 测试冷启动时间
time npx next dev --webpack &
# 等服务器启动后 Ctrl+C
time npx next dev --turbo &
# 等服务器启动后 Ctrl+C

在一个 200+ 组件的项目里,我自己测试的结果:

指标WebpackTurbopack提升
冷启动28s8s71%
热更新1.2s0.15s87%
内存占用1.8GB0.9GB50%

你的项目数据肯定会有差异,但大方向是一致的。

当前限制#

Turbopack 还在快速迭代,有些功能暂时不支持:

不支持的功能#

生产构建的状态#

虽然 next build --turbo 可以用,但还是 beta 版。已知问题:

生产环境暂时还是用 Webpack 更稳妥。

与其他工具的对比#

vs Webpack#

对比项WebpackTurbopack
语言JavaScriptRust
生态非常成熟发展中
冷启动慢(大项目尤其明显)
热更新中等非常快
配置复杂但灵活简单但选项少
适用场景任何项目Next.js 项目

vs Vite#

对比项ViteTurbopack
开发服务器基于 ESM,esbuild 预构建Rust 全量打包
热更新快(但大项目会变慢)非常快(大项目优势明显)
框架支持Vue/React/Svelte 等仅 Next.js
生产构建Rollup仍在开发
上手难度简单更简单(开箱即用)

如果你用 Next.js,Turbopack 是更好的选择。如果用其他框架,Vite 仍然是开发体验的标杆。

vs esbuild#

esbuild 单纯追求构建速度,不太关心开发体验。Turbopack 在速度和功能之间做了平衡,增量计算和懒编译都是为开发体验服务的。

调试与问题排查#

查看构建详情#

Terminal window
# 开启详细日志
NEXT_TURBOPACK_TRACING=1 next dev --turbo

常见问题#

1. 模块找不到

Error: Cannot find module 'xxx'

检查 resolveAliasresolveExtensions 配置,确保路径正确。

2. 样式不生效

Turbopack 对 CSS Modules 的处理略有不同。确保文件名是 *.module.css 格式,并且用正确的导入方式:

// 正确
import styles from './Button.module.css'
// 错误
import './Button.module.css'

3. 热更新不触发

检查文件是否在 .gitignore.turboignore 里被忽略了。Turbopack 会跳过这些文件。

4. 内存不够

Turbopack 虽然比 Webpack 省内存,但大项目还是会吃不少。如果遇到 OOM,可以:

Terminal window
# 增加 Node.js 内存限制
NODE_OPTIONS="--max-old-space-size=8192" next dev --turbo

未来展望#

Vercel 的路线图很清晰:

  1. 2025 年:生产构建稳定版发布
  2. 长期目标:完全取代 Webpack,成为 Next.js 唯一的打包器

从目前的发展速度看,Turbopack 的成熟度在快速提升。如果你在用 Next.js,现在就可以在开发环境用起来了,等生产构建稳定后全面切换。

对于不用 Next.js 的项目,Turbopack 暂时还不是选项。Vercel 的精力主要放在 Next.js 生态,独立使用的支持优先级不高。这时候 Vite 仍然是更通用的选择。

参考资料#