vite
此章节是本人对 掘金小册-vite深入浅出 的总结笔记
学习问题
- esbuild的插件执行顺序
创建项目
安装 pnpm 后,执行下面的命令,选择相对应的框架即可自动生产
pnpm create vite
vite 的大概实现
预构建
- Vite 1.x 版本中使用 Rollup 来做这件事
- Vite 2.x 果断采用 Esbuild 来完成第三方依赖的预构建
Esbuild 存在的几个缺陷
- 不支持降级到 es5 的代码,这意味着在低端浏览器跑不起来
- 不提供操作打包产物的接口,Esbuild 的打包极简化,并不像 rollup 一样灵活
- 不支持自定义代码分割
所以 vite 的思路是:在开发环境用 Esbuild 编译打包,在生产环境用 rollup 打包
Esbuild 在 vite 中的作用
- 对于第三方依赖,会将非 ESM 格式转换为 ESM 格式 (开发阶段用这个,生产环境用 rollup稳定)
- 作为 TS 和 JSX 的编译工具 (生产环境)
在对这些文件的编译时 vite 会使用 Esbuild 进行语法转译,也就是将 Esbuild 作为 Transformer 来用,但是并不支持 TS 的类型检查,也就是 Esbuild 并没有实现 ts 的类型检查,所以在编译时仅仅抹掉了类型相关的代码,暂时没有能力实现类型检查,因此 vite build
之前会先执行tsc命令,也就是借助 TS 官方的编译器进行类型检查
- 代码压缩 (生产环境)
Vite 从 2.6 版本开始,默认使用 Esbuild 来进行生产环境的代码压缩 (包括 JS 代码和 CSS 代码)
传统压缩方式(webpack,rollup)都是使用 Terser 这种 JS 开发的压缩库进行压缩,但是其有两个大缺陷
- 压缩涉及大量的 AST 操作,但是 AST 无法在各个工具之间共享,比如 Terser 无法与 babel 共享同一个 AST,造成了很多重复解析过程
- JS 性能比不上 Golang 这种原生语言
针对以上情况进行实际测试会发现 Esbuild 的压缩速度是传统方式的 20 倍
Rollup 在 vite 中的作用
生产环境打包
- css 代码分割(提高缓存复用率)
- 自动为入口 chunk 添加预加载
html
<!-- 自动预加载入口 chunk 所依赖的 chunk-->
<link rel="modulepreload" href="/assets/vendor.293dca09.js">
- 异步 chunk 加载优化 一般情况下,Rollup 打包之后,会先请求 A,然后浏览器在加载 A 的过程中才决定请求和加载 C,但 Vite 进行优化之后,请求 A 的同时会自动预加载 C,通过优化 Rollup 产物依赖加载方式节省了不必要的网络开销
兼容插件机制
在开发阶段,Vite 借鉴了 WMR 的思路,自己实现了一个 Plugin Container,用来模拟 Rollup 调度各个 Vite 插件的执行逻辑,而 Vite 的插件写法完全兼容 Rollup,因此在生产环境中将所有的 Vite 插件传入 Rollup 也没有问题
反过来说,Rollup 插件却不一定能完全兼容 Vite