Vite主要由两个部分组成
- 开发服务器
- 基于原生ES模块(ESM)提供开发环境支持。
- 提供了丰富的内建功能,如速度快到惊人的模块热更新(HMR)。这意味着开发者在修改代码时,可以实时地看到更新效果,而无需重新加载整个页面。
- 利用现代浏览器的原生ES模块支持,将开发过程中的构建步骤推迟到了运行时,从而大大减少了启动时间。
- 构建指令
- 使用Rollup作为打包工具,可以生成更小、更优化的代码块,确保生产环境的应用加载速度快。
- Rollup是一个基于ES6的模块打包工具,其打包的文件小且干净,执行效率更高,更专注于JS打包,并支持Tree-shaking(通过工具“摇”掉JS文件中用不到的代码,是一个性能优化的范畴)。
- 构建指令是预配置的,开箱即用,可以输出用于生产环境的高度优化过的静态资源。
Vite有哪些主要特性:
- 冷启动优化:Vite采用原生ESM作为模块系统的实现,避免了传统打包工具在启动时的长时间编译过程,从而实现了极速的冷启动。
- 热模块替换(HMR):Vite内置了热模块替换功能,可以在不刷新页面的情况下,实时更新模块代码,提高开发效率。
- 原生ESM支持:Vite直接利用浏览器对ESM的支持,无需额外转换,使得代码更加原生、高效。
- 插件化扩展:Vite支持通过插件进行扩展,开发者可以根据自己的需求,定制开发流程。
Vite的实现原理
Vite的实现原理主要基于原生ESM、Rollup以及WebSocket等技术。
- 原生ESM:Vite利用浏览器对ESM的原生支持,将项目中的模块按照ESM的规范进行组织。在开发过程中,Vite只会处理被引用的模块,而不会对整个项目进行打包,从而实现了极速的冷启动。
- Rollup:虽然Vite没有直接采用Webpack作为打包工具,但它借鉴了Rollup的思想。Rollup是一个轻量级的模块打包器,它采用基于ESM的tree shaking技术,可以去除未使用的代码,减少打包体积。Vite在构建生产环境代码时,会利用Rollup进行打包。因此Vite还附带了一套 构建优化 的 构建命令,开箱即用。
- WebSocket:为了实现热模块替换功能,Vite使用WebSocket在服务器和客户端之间建立了一个长连接。当文件发生变化时,服务器会通过WebSocket将更新后的模块发送给客户端,客户端收到更新后,会替换掉原有的模块,实现热更新。
1.基于ESM的 Dev Server
在Vite出现之前,传统的打包工具如Webpack通常会在启动开发服务器之前解析所有依赖并进行打包构建。这意味着Dev Server必须等待所有模块构建完成,即使在开发过程中只修改了一个子模块,整个bundle文件也会重新打包,导致启动时间随着项目规模增大而变长。
相比之下,Vite充分利用了浏览器对ESM的原生支持。当代码执行到模块加载时,浏览器会动态地下载导入的模块,而不需要等待整个项目的构建完成。这种动态加载的方式实现了即时编译,使得暂时未用到的路由不会参与构建过程。因此,随着项目规模的增大和路由的增加,Vite的构建速度不会受到影响。
2. 基于ESM的 HRM 热更新
- 模块标识符的处理:Vite 在处理模块时,通过识别 import 语句中的模块标识符,可以动态地构建出模块之间的依赖关系图。
- WebSocket 通信:Vite 启动一个 WebSocket 服务器,用于与客户端建立持久连接,实现双向通信。通过 WebSocket,Vite 可以向客户端发送消息,告知其发生了模块变化,并触发热更新操作。
- 模块替换:当开发者修改了某个模块的代码后,Vite 检测到变化后,会重新编译并构建该模块。然后,Vite 通过 WebSocket 向客户端发送更新消息,告知客户端有模块发生了变化。
- 客户端处理:客户端接收到更新消息后,会根据更新消息中的信息,以及之前构建好的模块依赖关系图,进行相应的模块替换操作。具体来说,它会以非阻塞的方式请求被更新的模块,然后将新的模块代码插入到当前页面中,完成热更新操作。
- 局部更新:Vite 可以实现局部更新,即仅更新发生变化的模块,而不需要重新加载整个应用程序。这样可以显著减少开发过程中的刷新时间,提高开发效率。
总的来说,Vite 利用了浏览器原生对 ES 模块的支持,通过 WebSocket 实现了与客户端的实时通信,从而实现了基于 ESM 的热模块替换功能。这种实现方式使得开发者可以更快地看到代码修改后的效果,加快了开发迭代速度。
3. Vite实现的核心流程
- 启动服务器
- Vite首先启动一个开发服务器,该服务器使用原生ESM(ECMAScript模块)规范。
- 服务器同时创建一个WebSocket连接,用于实现与浏览器的实时通信。
- 解析请求
- 当浏览器请求一个模块(例如,通过
标签引入的JavaScript文件)时,Vite服务器接收请求。 - 服务器解析请求,确定要加载的模块。
- 模块转换
- 如果请求的模块需要转换(例如,使用Vue或React等框架编写的组件),Vite会调用相应的插件或转换器进行处理。
- 转换后的模块被缓存起来,以便后续请求可以更快地提供服务。
- 发送模块到浏览器
- Vite服务器将处理后的模块作为HTTP响应发送给浏览器。
- 浏览器接收到模块后,按照ESM规范进行加载和执行。
- 文件监听与热更新
- Vite服务器使用文件系统监听器(如chokidar)来监控项目文件的变化。
- 当文件发生变化时(例如,保存了一个源代码文件),Vite会重新处理受影响的模块。
- 通过WebSocket连接,Vite将更新后的模块发送给浏览器。
- 浏览器接收到更新后,使用HMR(热模块替换)机制替换旧模块,无需重新加载整个页面。
- 构建生产环境代码
- 当需要构建生产环境的代码时,Vite会使用Rollup或其他打包工具进行打包。
- 打包过程会进行代码优化、压缩和分割等操作,以减小最终代码的体积并提高加载性能。
- 打包完成后,生成的生产环境代码可以部署到服务器上供用户访问。