Skip to main content

Next.js 构建工具:Turbopack vs Webpack

面试题:Next.js 15 为什么默认用 Turbopack?它比 Webpack 快在哪里?

一、构建工具演进史

Next.js 构建工具时间线
─────────────────────────────────────────
2016 Next.js 1.x 纯 Webpack 时代
2018 Next.js 7+ 引入 SSR 优化
2020 Next.js 9.4 引入 Fast Refresh
2022 Next.js 12 尝试 SWC 替代 Babel(编译器)
2023 Next.js 13.4 App Router 稳定 + Turbopack dev(alpha)
2024 Next.js 15 Turbopack dev 稳定,build 仍是 Webpack
2026 Next.js 15.x Turbopack build 仍在迭代(beta)

当前状态(2026):dev 用 Turbopack 已稳定;build 仍推荐用默认 Webpack(生产打包能力更成熟)。

二、Webpack:曾经的王者

2.1 工作模式

启动时 ──→ 抓取所有入口 ──→ 解析依赖图 ──→ 全量打包 ──→ dev server 启动

监听文件变化

重新打包

2.2 痛点

  1. 冷启动慢:必须先解析全量模块构建依赖图
  2. HMR 退化:项目越大 HMR 越慢(与项目规模 O(n) 关系)
  3. JS 实现:解释型语言,单线程瓶颈明显
  4. 配置复杂:loader / plugin 体系庞大

三、Turbopack:Rust 编写的下一代打包器

3.1 核心定位

Turbopack 是 Vercel 出品、Rust 编写的增量打包器。Next.js 团队负责人 Tobias 曾在 Vite vs Turbopack 的争议中明确:Turbopack 定位是大型项目/全栈,Vite 定位是库/中小项目

3.2 三个关键设计

① 增量计算(Incremental Computation)

核心创新:只重新计算真正改变的部分,任务粒度细到函数级别

// 概念示意(不是真实代码)
struct Task {
function: fn() -> Output,
inputs: HashSet<TaskId>,
}

// 当文件 A 改变时
// 1. 标记所有依赖 A 的 Task 为 dirty
// 2. 只重跑这些 Task
// 3. 没依赖 A 的 Task 结果直接复用

类比:webpack 像每次都重新画整张画;Turbopack 像图层,只重画被修改的图层

② 请求级编译(Request-driven)

// Vite 的策略:浏览器请求 /src/App.tsx → 编译 App.tsx
// Turbopack 的策略:浏览器请求 /src/App.tsx → 编译 App.tsx 及其所有依赖

与 Vite 看起来像,但区别在于:

  • Vite 是 dev 阶段用 esbuild,build 用 Rollup
  • Turbopack 是 dev/build 同一套引擎,状态可复用

③ 函数级缓存

Webpack 是文件级缓存;Turbopack 是函数级缓存

// 假设有这样一个模块
export const getUser = (id) => /* 从 DB 查用户 */;
export const getPosts = () => /* 从 DB 查帖子 */;

// 改 getPosts 函数体(不影响 getUser)
// Webpack: 整个文件 re-compile
// Turbopack: 只 re-compile getPosts,getUser 结果直接用

3.3 性能数据(官方)

场景WebpackTurbopack提升
大型项目 dev 启动30s1.5s20x
HMR 速度500ms30ms16x
内存占用1.2 GB400 MB3x

数据来自 Vercel 2024 官方博客,基于 vercel.com 自身代码库测试。

四、Turbopack vs Vite:容易被问的对比

面试题:Turbopack 和 Vite 有什么本质区别?

维度ViteTurbopack
底层语言esbuild (Go) + RollupRust
dev 模式原生 ESM + 按需编译增量计算 + 请求级编译
build 模式Rollup(成熟)Rust 自研(2026 仍在 beta)
缓存粒度文件级(HTTP 缓存)函数级(细到函数)
大项目表现中等(ESM 瀑布请求)(Rust 内存模型 + 并行)
HMR 边界ESM 模块边界函数/模块边界
框架绑定框架无关(Vue/React/Svelte 都行)深度绑定 Next.js
生态插件体系成熟(rollup 兼容)插件体系还在补

核心差异一句话

Vite 解决「dev 体验」,Turbopack 解决「大型项目能 scale」。小项目 Vite 更顺手;大型 Next.js 项目 Turbopack 优势明显。

五、Turbopack 在 Next.js 中的使用

5.1 dev 模式

# 15+ 默认就是 Turbopack
next dev
# 或显式声明
next dev --turbopack

5.2 build 模式(2026 现状)

# 默认(Webpack)
next build

# 试用 Turbopack build(beta,可能有兼容问题)
next build --turbopack

生产环境 build 仍建议用 Webpack:Turbopack build 在生态兼容性上还不成熟,部分 loader/plugin 未适配。

六、SWC:被忽略的功臣

无论用 Webpack 还是 Turbopack,底层都依赖 SWC 编译 TS/JSX

工具语言编译速度
BabelJS慢(解释型)
SWCRust快 20x
esbuildGo快 10x
TSCGo最慢(重在类型检查)

面试题:Babel 慢在哪? Babel 是 AST 转换的鼻祖,但纯 JS 实现,冷启动 + 大项目都慢。SWC 用 Rust 重写了一套等价编译器,API 兼容 Babel 插件,所以能直接平替。

七、面试高频追问

Q1:为什么不用 Vite 的 esbuild 替代 Turbopack?

A:esbuild 速度快但不适合做大型项目的全量打包(HMR 边界处理、CSS 处理、SSR 构建等能力不够)。Turbopack 是为 Next.js 量身定做的,能处理 App Router 的 RSC 边界、Server Components 序列化等 Next.js 特有场景。

Q2:Turbopack 完全替代 Webpack 了吗?

A:dev 已替代;build 还在迭代。Webpack 仍是 2026 年的生产构建主力,但 1~2 年内 Turbopack build 会稳定。

Q3:HMR 的原理是什么?

A:

  • Webpack:监听文件变化 → 重新编译 → WebSocket 推送 → 浏览器替换
  • Turbopack:监听文件 → 标记函数级 dirty → 只重编译 dirty 函数 → 增量推送

Q4:如何排查 Next.js 构建慢?

A:

  1. next build --profile 生成 profile
  2. 看哪个 chunk / loader 耗时
  3. 拆分大依赖(manualChunks / 动态 import)
  4. 升级到最新 SWC

八、相关文档