一、vite的简介
- 定位:新一代前端构建工具
- 两大组成部分: No-bundle开发服务,源文件无需打包、生产环境基于rollup的bundler 3.核心特征:
- 高性能、简单易用
- 超快的冷服务器启动
- 即时的模块更新
- 真正的按需编译
- 更小的打包体积
二、vite使用
项目初始化
- 提前安装 pnpm:npm i -g pnpm
- 初始化命令:pnpm create vite
- 安装依赖:pnpm install
- 启动项目:npm run dev
三、 vite 整体架构
3.1 关键技术:依赖预打包
-
预打包原因:避免node_modules 过多的文件请求、将commomjs格式转换为esm格式
-
实现原理:服务启动前扫描代码中用到的依赖、用esbuild对依赖代码进行预打包、改写import语句,指定依赖为预构建产物路径
3.2 关键技术:单文件编译
用esbulid编译TS/JSX、
- 优势:编译速度提升10-100x
- 局限性:不支持类型检查、不支持语法降级到ESS
3.3 关键技术:代码压缩
esbulid 作为默认压缩工具,替换传统的Terser、Uglify.js等压缩工具
3.4 关键技术:插件机制
- 开发阶段:模拟rollup 插件机制
- 生产环境:直接使用rollup
四、vite 插件开发
- 代码分割:拆包
问题:无法进行并发请求、缓存复用率低
- js编译工具
- 语法安全降级
- 服务器渲染SSR
五、 Vite原理
5.1 ESM&esbuild
1.ESM:
在ES6没有出现之前,随着js代码日益膨胀,往往会对资源模块化来提效,这也就出现了多个模块化方案。如CommonJS常用于服务端,AMD、CMD规范常用在客户端。ES6出现后,紧接着出现了ESM。ESM是浏览器支持的一种模块化方案,允许在浏览器实现模块化。
- CommonJS:模块同步,如Browserify会对代码进行解析,整理出代码中的所有模块依赖关系,然后把nodejs的模块编译成浏览器可用的模块,相关的模块代码都打包在一起,形成一个完整的JS文件,这个文件中不会存在 require 这类的模块化语法,变成可以在浏览器中运行的普通JS,运行时加载
- AMD:模块异步,依赖前置,是requireJS在推广过程中对模块定义的规范化产出,加载完依赖后立即执行依赖模块,依赖加载成功后执行回调
- CMD:模块异步,延迟执行,是seaJS在推广过程中对模块定义的规范化产出,就近依赖,先加载所有依赖模块,运行时才执行require内容,按顺序执行
与CommonJS、AMD不同,ESM的对外接口只是一种静态定义,为编译时加载,遇到模块加载命令import,就会生成一个只读引用。等脚本真正执行时,再根据这个只读引用,到被加载的那个模块内取值。由于ESM编译时就能确定模块的依赖关系,因此能够只包含要运行的代码,可以显著减少文件体积,降低浏览器压力。
2.esbulid: Vite 对 js/ts 的处理没有使用如 glup, rollup 等传统打包工具,而是使用了 esbuild。esbuild 是一个全新的js打包工具,底层使用了go,大量使用了并行操作,可以充分利用CPU资源。esbuild支持如babel, 压缩等的功能。
对比各打包工具性能,可以看到esbuild比rollup等工具快十几倍。
5.2 请求拦截:
Vite 的基本实现原理,就是启动一个 koa 服务器拦截由浏览器请求 ESM的请求。通过请求的路径找到目录下对应的文件做一定的处理最终以 ESM的格式返回给客户端。
5.3 热更新原理:
Vite 的热加载原理,其实就是在客户端与服务端建立了一个 websocket 连接,当代码被修改时,服务端发送消息通知客户端去请求修改模块的代码,完成热更新。
- 服务端:服务端做的就是监听代码文件的改变,在合适的时机向客户端发送 websocket 信息通知客户端去请求新的模块代码。
- 客户端:Vite 中客户端的 websocket 相关代码在处理 html 中时被写入代码中。可以看到在处理 html 时,vite/client 的相关代码已经被插入。