前端构建工具vite
模块化打包工具的由来
ES-Mdule 的浏览器兼容性问题
在浏览器支持 ES 模块之前,JavaScript 并没有提供的原生机制让开发者以模块化的方式进行开发。这也正是我们对 “打包” 这个概念熟悉的原因:使用工具抓取、处理并将我们的源码模块串联成可以在浏览器中运行的文件。
模块文件过多导致频繁发送网络请求的问题
其次就是通过模块化的方式,划分出的模块文件会比较多,而我们前端应用又是运行在浏览器当中的。那每一个我们在应用中所需要的文件,都需要从服务器当中请求回来,这些零散的模块文件就必将会导致浏览器频繁发出请求,从而影响我们应用的工作效率。
资源文件模块化问题
就是我们在前端应用开发过程当中,不仅仅只有 JavaScript 代码需要模块化。因为随着我们应用的日益复杂,我们的 html,css 这些资源文件同样也会面临相同的问题。
vite 的由来
当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。我们开始遇到性能瓶颈 —— 使用 JavaScript 开发的工具通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用 HMR,文件修改后的效果也需要几秒钟才能在浏览器中反映出来。如此循环往复,迟钝的反馈会极大地影响开发者的开发效率和幸福感。
Vite 旨在利用生态系统中的新进展解决上述问题:浏览器开始原生支持 ES 模块,且越来越多 JavaScript 工具使用编译型语言编写。
vite 是什么
Vite,一个基于浏览器原生 ES 模块的开发服务器。利用浏览器去解析模块,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。同时另有有 Vue 文件支持,还搞定定了热更新,而且热更新的速度不会随着模块增加而变慢。在开发环境下基于浏览器原生 ES 导入开发,在生产环境下进行汇总打包。
开发环境 省去打包过程,将 ESM 发送给浏览器(浏览器开始原生支持 ES 模块),实现无论项目多大都能快速的 HMR
生产环境,为了有最优的加载性能,需要打包(将代码进行 tree-shaking、懒加载和 chunk 分割(以获得更好的缓存))
vite 的特点
- 极速的服务启动
- 轻量快速的热重载
- 真正的按需编译
vite 的原理
我们平时写代码引用一个 node_modules 模块时,我们都是以如下的格式进行引用。
1 | import vue from 'vue' |
浏览器检测到内部含有 import 引入的包,就会发起 HTTP 请求获取模块的内容文件,其 Vite 的主要功能就是通过劫持浏览器的这些请求,并在后端进行相应的处理将项目中使用的文件通过简单的分解与整合,然后再返回给浏览器渲染页面,vite 整个过程中没有对文件进行打包编译(省去 webpack 冗长的打包时间),所以其运行速度比原始的 webpack 开发编译速度快出许多!
热更新(HMR)的原理
vite 通过使用 websocket 连接实现 HMR(热更新):在客户端与服务端建立了一个 websocket 链接,当代码被修改时,服务端发送消息通知客户端去请求修改模块的代码,充分利用浏览器 HTTP 头的缓存机制-协商缓存(资源加载状态码 304)和 强缓存(node_modules 下的.vite_opt_cache 文件夹存放被缓存的依赖包),完成热更新。
vite 与 webpack 对比
webpack:使用 webpack 的打包工具时,webpack 需要将所有模块打包成一个一个或多个模块,并且修改其中任何一个小模块都会导致整个模块重新打包,不管代码多少都会经历打包的过程,且随着项目规模的扩大,重新打包(热更新)的时间越来越长。
vite: 一个由原生 ES 模块驱动的 Web 开发的工具,完全做到按需加载,一劳永逸的解决了热更新慢的问题!
Webpack | Vite | |
---|---|---|
打包原理 | 把代码打包为立即执行函数,这个转换封装逻辑,代码量越大,打包时间越长 | 把模块区分为 依赖和源码,用 go 写的 esbuild 去预构建 这些依赖,源码部分利用浏览器原生 ESM 的方式去提供出去。(浏览器请求源码时,vite 进行 按需部分编译 ) |
预构建依赖 | webpack 基于Node.js | vite 使用 esbuild(Go 编写) 预构建依赖,并且比以 Node.js 编写的打包器预构建依赖快 10-100 倍。 |
打包构建 | 先打包生成 bundle,再启动开发服务器 | 先启动开发服务器,利用新一代浏览器的 ESM 能力,无需打包,直接请求所需模块并实时编译 |
服务器启动时间 | 冷启动开发服务器慢。webpack 基于打包器的方式,在提供服务前急切地抓取和构建整个应用。 | 缩短数倍的冷启动时间,启动开发服务器更快。 1. 一开始将应用中的模块区分为 依赖 和 源码 两类,改进了开发服务器启动时间; 2. Vite 将会使用 esbuild 预构建依赖和依赖缓存; 3. 利用浏览器对 ESM 的支持,按需加载,减少不必要的时间开支. |
热更新速度 | 1. 当基于打包器启动时,编辑文件后将重新构建文件本身,热更新较慢; 2. HMR 更新速度也会随着应用规模的增长而显著下降。 | 1. Vite 同时利用 HTTP 头来加速整个页面的重新加载,依赖模块通过与构建进行缓存,减少再次请求,热更新较快。 2. 在 Vite 中,HMR 是在原生 ESM 上执行的,HMR 不会随着规模的增长而改变速度。 |
生产环境 | 仍然需要打包,因为模块嵌套导入会导致网络开销。 打包之后可以进行 tree-shaking / 懒加载 / chunk 分割 打包到生产环境时,vite 使用传统的 rollup 进行打包,生产环境 esbuild 构建对于 css 和代码分割不够友好。所以,vite 的优势是体现在开发阶段 | |
生态 | 已经主宰多年,版本稳定;生态丰富,它的 loader 和 plugin 非常多;使用者较多;项目使用相对来说风险较低 | Vite 初出茅庐,锋芒毕露,还在迭代优化升级中;在生态上不如 webpack,社区插件较少;目前较多的是观望者,没有大规模使用,很多问题还没有暴露出来,因此项目使用风险相对于 webpack 而言更高。 |