尤雨溪在Vite Conf 2024
上宣布成立公司Void Zero[1],目前已经完成$460万种子轮融资,由Accel
领头,并且有Amplify
以及在dev tools领域有丰富经验的创始人参与。主要目标是搭建下一代JavaScript
工具链,实现一套工具覆盖从源码到最终产物的中间过程,例如semantic analysis、transformer、linter、formatter、minifier、boundler等。
好的工具链不外乎快
、好用
, 本文将结合尤雨溪在Vite Conf 2024
上分享的内容来介绍什么是下一代JavaScript工具链
, 以及快
、好用
体现在哪些方面, 最后再上手试验下相关工具看是否真的快
。
Vite工具现状
相信现在大多数前端开发人员的构建工具首选一定是Vite
,Vite确实易上手并且快,涵盖了Vue、React、Preact等主流前端框架,也支持TypeScript、Nuxt等。Vite仅需简单的几个指令即可运行起项目:
// 运行create指令,选择前端框架和语言,例如Vue、TypeScript
npm create vite@latest
// Done. Now run:
cd vite-project
npm install
npm run dev
Vite为什么快?
有对比才能体现快,几年前构建前端项目还是使用webpack、Rollup、Parcel等工具,当项目代码指数级增长,这些工具的性能瓶颈愈发明显,动不动需要几分钟才能启动dev server,即使是模块热更新(HMR),文件修改后也需要几秒钟才能反馈到浏览器,这严重影响开发者工作幸福指数
。
浏览器的快速发展造就了Vite
,Vite的优势在两个方面:首先是支持了Native ES Modules,其次是build过程接入了编译型语言(如go、rust)开发的工具。这些优势体现在服务器启动和热更新两个阶段:
服务器启动:Vite将应用中的模块区分为依赖、源码两种,改进了开发服务器启动时间。
依赖:开发时不会变动的纯JavaScript,或者是较大的依赖(上百个模块的组件库),这些代码的处理代价比较高,Vite会使用
esbuild预构建
这些依赖,由于esbuild使用Go编写,因此比以JavaScript编写的打包器预构建快10-100倍。源码:对于Vue、JSX等频繁变动的代码文件,Vite以原生ESM方式提供源码,让浏览器接管了打包程序的部分工作,Vite只需要在浏览器请求源码时进行转换并安需提供,也就是需安需导入、安需加载。
热更新(HMR)
在Vite中,HMR是在原生ESM上执行的。当编辑一个文件时,Vite只需要精确地使已编辑Module与其最近的HMR边界之间的链失活,使得无论应用大小如何,HMR能保持快速更新。
Vite同时利用HTTP头来加速整个页面的重新加载:源码模块请求根据
304 Not Modified
协商缓存,而预构建的依赖模块请求则通过Cache-Control:max-age=31536000,immutable
进行强缓存,因此一旦被缓存将不需要再次请求。
Vite也有缺陷
Vite当前架构底层依赖于esbuild
、Rollup
、SWC
,三者的作用如下:
esbuild: Vite使用esbuild执行依赖项预构建,转化TypeScript、JSX,并且作为生成环境构建的默认minifier。
Rollup: Rollup直接基于ES6模块格式,因此能够实现除屑优化(Tree Shaking),然后基于插件生态来支持打包过程的扩展。Vite基于Rollup的插件模板实现插件生态,构建生产环境的bundling chunk和静态资源。
SWC: SWC使用Rust语言实现,号称
super-fast
JavaScript编译器,能够将TypeScript、JSX编译为浏览器支持的JavaScript,编译速度比babel快20倍。Vite主要使用SWC来打包React代码以及实现React代码的HMR。
Vite充分利用esbuild、Rollup、SWC各自的优势来组合成一套打包工具链,虽然对使用者来说是无感的,但对于Vite内部,三套打包框架组合在一起本身就显得比较臃肿。
接下来我们就分析下这一套组合拳会有哪些缺陷:
两套bundling
虽然esbuild构建非常快,但它的tree shaking以及代码切分不像rollup的配置化那样灵活,插件系统设计的也不尽如人意,因此Vite仅在DEV环境使用esbuild预构建依赖项。rollup正好拟补了ebuild的缺点,比较好的chunck control,以及易配置的tree shaking,因此适合在生成环境打包代码。
生产环境构建速度慢
由于Rollup基于JavaScript实现,虽然比Webpack快很多,但相比于native工具链,速度就相形见绌了。
比较大的二进制包
SWC的二进制包有多大?在Mac系统下,达到37MB,比Vite和其依赖项文件总和大了2倍。
SWC虽然快,但缺少bundler能力
SWC有比较完善的transform和minifier,但没有提供可用的bundler,这也就说明了SWC不能直接作为打包工具。
不一致的bundler行为
DEV环境使用esbuild预构建依赖项,而PROD环境使用rollup构建包,在包含ESM、CJS多模块形式场景下,esbuild和rullup的构建行为存在差异,导致一些仅在线上出现的问题。
低效率的构建管道
由于混合了JavaScript、Go、Rust三种程序,同一代码片段可能会在不同进程重复执行AST、transform、serialize,并将结果在不同进程间传递。另一方面,在进程间传递大量的代码块本身也会有比较大的开销,特别是传递source map此类文件时开销更大。
总结这些问题,就三点:碎片化、不兼容、低效率。 为了解决这些种种问题,统一的打包工具迫在眉睫,这也是尤雨溪提出Rolldown
的主要原因。
基于Rust的下一代工具链
VoidZero
提出的下一代工具链是什么?下图为 VoieZero
规划蓝图,不管是Vue、React、Nuxt还是其他前端框架,一个Vite
统统给你搞定,测试框架仅需Vitest
即可。Vite
底层依赖Rolldown
打包器,而打包过程完全交由工具链Oxc
负责。实际干活的Rolldown
和Oxc
都基于Rust实现,因此够快。
Oxc
、Rolldown
离正式使用还有一段距离,预计是2025年初投入使用,但这也不妨碍我们先了解下这两个工具让人惊掉下巴的牛,毕竟值460万美金。
Oxc
Oxc
作为统一的语言工具链,将提供包含代码检查Linter
、代码格式化Formatter
、代码打包的组合式NPM包或者Rust包。代码打包过程分为Transformer
、Minifier
、Resolver
、Parser
、Semantic Analysis
。
Oxc
官网地址: oxc.rs/[2] , 目前已经发布了oxlint v0.9.9
、oxc-transform alpha 版本
。
oxlint v0.9.9
:检查速度比eslint快50-100倍。oxlint已经在Shopify
投入使用,之前使用eslint检查代码需要75分钟/CI,而使用oxlint
仅需要10秒钟,你就说快吧!oxc-transform alpha
:转换速度是SWC的3到5倍, 并且内存占用减少20%, 更小的包体积(2MB vs SWC的37MB). 已实现的主要3个功能:转换TypeScript至ESNext; 转换React JSX至ESNext,并支持React Refresh; TypeScript DTS 声明;
Oxc
目前已完成Parser
Linter
Resolver
,正在快马加鞭地完善Transformer
。
Rolldown
Rolldown
是基于Rust实现的JavaScript快速打包器,与Rollup API兼容。作为打包器应包含的功能有:
Bundling:
阶段1:使用Rolldown替换esbuild,执行依赖项预生成,主要包括多entry的代码切分、cjs/esm混合打包、基础插件支持; 阶段2:Rolldown能够支持生成环境构建,包括命令行和配置文件支持、Treeshaking、Source map、Rollup插件兼容等; Transform: 使用
oxc
代替esbuild的Transform,尽可能使用同一套AST
。核心功能模块Typescript/JSX转换、代码缩减(minification)以及语法降级;与Vite深度集成: 替换esbuild和rollup,Vite内部核心插件使用Rust实现,提升构建效率。
Rolldown
在性能方面表现如何?官方给出了两个测试。
测试一:打包数量为19k的模块文件,其中10k为React JSX组件,9k为图标js文件。不同打包框架的耗时如下:
rolldown: 0.63s rolldown-vite: 1.49s esbuild: 1.23s fram: 2.08s rsbuild: 3.14s
rolldown打包速度比esbuild快了近2倍。
测试二:打包Vue Core代码,基于TypeScript的多包仓库,包含11个包/62个dist bundles,耗时如下:
Vue版本 | 构建框架 | 构建耗时 |
---|---|---|
Vue3.2 | Rollup + rullup-plugin-typescript2+ terser tsx | 114s |
Vue3.5(main branch) | Rollup + rollup-plugin-esbuild + swc minify tsc | 8.5s |
Vue3.5(rolldown branch) | Rolldown(tranform+minify) + oxc-transform | 1.11s |
基于
rolldown
的Vue3.5源代码比Rollup
构建快了近8倍。
单从测试数据来看,基于Rust开发的rolldown
,打包速度确实带来惊人的提升。以下为下一代Vite的架构概览,预计2025年初发布。
总结
VoidZero
宣称的下一代JavaScript工具链,价值460万美金,其商业价值可见一斑,对于研发个体来说没有明显的感受,但对于大型企业来说,VoidZero
能实打实的为企业节省每年几百万的CI构建成本。
VoidZero
将清一色的使用Rust来搭建底层构建逻辑,如果能够成型,也证明了Rust在前端构建领域的地位。这也让我们反思,借助于Rust独特的性能和安全性优势,它还能够为前端带来哪些价值?例如WASM支持,基于Tauri、Electon.rs框架的桌面应用,支持Flutter和Dart语言的移动端应用。
究竟VoidZero
会为前端领域带来怎样的变革,Vite能不能一统JavaScript工具链,让我们拭目以待吧。
参考资料
https://voidzero.dev
[2]https://oxc.rs