前言
Turbopack 是一个为 JS 和 TS 优化的增量式打包框架,由原 Webpack 和 Next.js 作者用 Rust 编写。当 Turbopack 以比 Vite 快10倍的口号出现时,我就迫不及待地想要试一下这个号称可以支持未来几十年的架构的框架了。
安装
由于 Turbopack 还是 Alpha 阶段,所以现如今只能用于 Next.js v13 版本Turbopack ,npx create-next-app --example with-turbopack
.
Why Turbopack
Turbopack以比Vite更快的口号吸引了我,官网给出的解释如下:
Bundling(Turbopack ) VS ESM(Vite)
- 在开发模式 (development mode) 下,Vite 不会打包应用源代码,而是利用浏览器原生的 ES Module 系统。由于只需要转换一个单文件,启动速度非常快。但是,一旦项目庞大,模块间的依赖关系变得非常复杂,浏览器中大量的请求可能导致启动时间变慢。因此,如果浏览器能够在尽可能少的网络请求中获取所需的代码,就会更快。
- Turbopack 使用 Rust 编写,打包性能非常好。在生产环境 (production mode) 下,它跳过了打包过程,只打包开发环境下的代码。
Increment Computation (增量计算)
Do less work or do work in parallel.
为了使打包过程更快,Turbopack做了两件事:
- do less work (为bundle 做了缓存处理,不会重复做同样的工作)
- do work in parallel(并行) ( Turbo 引擎会像执行函数调用时的调度器一样,并行化所有可用的核心 (cores) )
为什么不用 esbuild
esbuild 对单任务打包非常快,但是:
- 没有热更新(HMR)
- 不做太多的缓存处理
Lazy bundling
Only bundling assets when absolutely necessary
以前的 Next.js 喜欢在开发模式下将整个代码一起打包,但现在由 Turbopack 构建的 Next.js 应用程序只会打包已请求页面的代码。例如,在“~/home”路由上,只会打包 home 页面下导入的代码,从而大大缩短了启动时间。
核心概念
Turbo引擎
这是一个使用Rust编写的增量计算引擎,其工作原理如下:
Function-level Cache (函数级缓存)
首先,Turbopack可以将任何一个函数标记为“to be remembered”。当这些函数被调用时,Turbo Engine会记住它们调用了哪些函数,返回了什么,并将它们存储在内存缓存中。
当在 api.ts 和 sdk.ts 两个文件中调用 readFile() 时,Turbopack 会将这两个文件的代码打包,并将结果保存在缓存中。下一次,如果我们更改了 sdk.ts 文件,Turbopack 会重新计算readFile('sdk.ts')函数。由于之前的缓存仍然存在,我们的 readFile('api.ts') 就不需要重新打包计算了,直接调用缓存结果。
当文件数量很大时,效率非常高
The Cahce (缓存)
Turbo 引擎目前将缓存存储在内存中,这意味着只要进程在运行缓存,它就会一直存在。对于 dev 服务器来说非常有效。当你使用 next dev—turbo
命令启动时,将使用 Turbo 引擎启动缓存,并且当你停止 dev 服务器时,缓存将被清除。
未来,官方计划使此缓存持久化——可以保存在文件系统中或像 Turborepo 那样的远程缓存中。这意味着 Turbopack 可以记住跨运行和跨机器完成的工作。
Compiling by Request(按请求编译)
page-level compilation (页面级编译)
we began compiling only the code on the page you requested
Turbopack 仅在你请求的页面上编译代码,未请求的页面的代码也被编译。
Request-level compilation (请求级编译)
Turbopack 足够聪明,只编译你需要的代码,这意味着:
- 如果浏览器请求 HTML,我们只编译 HTML,而不是 HTML 引用的任何东西。
- 如果浏览器需要某些 CSS,我们将只编译那些 CSS,而不编译引用的图像。
Features
JavaScript
- Turbopack 默认使用 SWC 打包 JS、TS 文件,并且支持 ESNext 语法
- Browserslist 开箱即用
- 目前还不支持 Babe,未来将通过插件支持
TypeScript
- Turbopack 支持 TS 所有的特性
- 在 tsconfig.json 里面配置 Paths 和 baseUrl 会被 Turbopack 读取到,可直接用
- 由于使用 SWC 编译 TS 文件,所以编译前的类型检查需要依靠
tsc --watch
或 IDE 的 TS的集成
Frameworks
Turbopack 计划为多个框架提供一流的支持。无论使用的是 Svelte、React、Vue.js,还是其他框架,Turbopack 希望为它们都提供良好的体验。
- React:
- 组件中不需要手动导入 React -
import React from 'React'
- React Server component 天然支持,开箱即用
- 组件中不需要手动导入 React -
- Next.js:
- 同上
- next/dynamic 暂不支持,未来支持
CSS
- 支持全局导入 CSS
import './global.css'
- 支持 CSS Modules
import cssExports from './phone.module.css'
- PostCSS nested 开箱即用
.phone {
& _title {
width: 500px;
@media(max - width: 500px) {
width: auto;
}
body.is_dark & {
color: white;
}
}
img {
display: block;
}
}
- 支持 @import 语法
@import './modal.css'
- 支持 PostCSS 和 TailwindCSS
- 暂不支持 SASS、LESS ,未来支持
Dev Server
热更新
热更新(Hot Module Replacement)可以让你的服务器向浏览器推送文件更新,而不会触发完整的刷新。由于 Turbopack 采用 Rust 编写的增量架构、增量计算和延迟打包等技术,因此 HMR 的性能得到了极大优化。
Fast Refresh
Fast Refresh 是建立在 HMR 之上的,它提供了一个框架级的整合,以在更新中保留状态。例如,对 组件的更改将在不同的更改中保留该组件的内部 count
静态资源
- 导入静态资源:如
import img from './img.png'
和import video from './video.mp4'
- 暂不支持像Next.js那样导入图片时返回metadata对象。而是直接返回该图片路径字符串。
- 可以直接访问/public文件夹下的资源,如
public/favicon.png
可以通过https://example/favicon.png
直接访问。 - 支持导入JSON文件和命名导入,如
import fixtures from './fixtures.json';
和import {users,posts} from './fixtures.json'
导入模块
开箱即用支持 CommonJS 和 ESM,并且部分支持 AMD:
- Common JS :
- 支持 require()语法
const {add} require('./math')
- 支持 require()语法
- ESM
import img from './img.png';
- Dynamic Import
- 支持 import()
const getFeatureFlags = () => { return import('/featureFlags').then(mod => { return mod.featureFlags; })}
- 支持 import()
环境变量
环境变量通常配置在.env .env.local .env.development .env.production.local
等文件中。可以通过process.env调用配置的环境变量,例如:
在.env文件中配置DATABASE_URL="postgres://"
在其他文件中引入 process.env.DATABASE_URL
即可获取。
自定义Turbopack
由于 Turbopack 内置了对 CSS、编译现代 JS 文件的支持,不需要 loaders 和 loader configuration 的内置功能。
总结
-
从开发体验来看,初始开发零散组件时可能会因为入口组件比较零散而导致开发体验劣化。但是,在开发大型项目时使用这种增量编译和缓存打包工具有利于减少编译时间并优化开发体验。
-
从生态拓展性来看,目前只能在 Next.js13 中使用 Turbopack。之后才会有 webpack 等兼容打包能力,并且类似于 webpack 的插件、loader 开放能力等都还在建设中。因此,Turbopack 仍然需要一段时间才能完善其生态系统。
-
从未来空间来看,由 webpack 作者创建的 Turbopack 吸取了大量 webpack 的软件架构打包经验,并广泛学习市面上比较优秀的构建工具,如 Google 的 Bazel。开发团队实力强大,还有Vercel 这样一个大公司在背后助力,未来可期。