认识Vite
vite本身是个前端编译工具的聚合器。内部使用了rollup、babel等工具,来达到特定场景下提高构建速度的效果。
构建工具
根据不同的环境,vite会使用不同的底层构建工具:
- 开发环境:
- ES Build:基于golang 的 javascript 打包工具,速度更快,可以实现rollup、webpack的大部分功能。
- 生产环境:
- Rollup:成熟和稳定是关键,而不是编译速度
代码类型
根据代码变动的频繁程度,vite将代码分为2类:
- 依赖:第三方库,不变动,代码多,数量大。
- 源码:项目代码,变动频繁,经常修改。
预构建
对于「依赖」代码,vite采用了 pre-bundle(预编译)的做法:
- 在“冷启动”时,使用esbuild对依赖进行编译,并且将其放入到 .vite 目录下
- 在没有新的依赖更新的情况下,再次启动时,会直接使用前一步构建好的依赖
ESM
vite基于现代浏览器原生的ESM能力,来避免了像webpack那样(对整个源码进行遍历,转换成AST,然后再打包成多份javascript),大大提高了开发模式下的编译速度。
上面的2张图中,左侧是源码,右侧是访问构建好的网站。
注意看右图的绿色框部分,里面的代码基本没变化,几乎就是左侧源码直出。
并且使用了 import
语法,这里也没进行任何转换,完全依赖浏览器的ESM能力。
需要注意的是,不论是「源码」还是「依赖」,它们的路径都被转换了。因为ESM不能直接使用本地的路径,所以vite内部还架设了一个 koa.js
服务器,就是单纯做静态服务,将路径进行转换。
这样,不论项目多么复杂,都不会增加编译耗时,因为其速度完全取决于 koa.js
静态服务和浏览器自带的ESM。
如果是webpack,项目复杂后,代码分析、ast转换、生成目标代码,这3步的耗时就会快速增加。
HTTP缓存
对于不同类型的代码,在开发模式采用了不同的http缓存策略:
依赖:强制缓存
源码:协商缓存
这算是优化的小tips,但不是提速的核心,核心还是「预构建」+「ESM」