本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!
前言
关注前端社区的同学可能知道Vue.js
他爹尤雨溪这两年推出Vite
这个构建工具,初衷就是大佬觉得基于webpack
,在开发时候,每保存一次代码就要等webpack
重新去构建打包代码,这个过程太漫长了。相信在座同学只要手头项目偏大的,都能感受到与大佬一样的痛苦。
当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。我们开始遇到性能瓶颈 —— 使用 JavaScript 开发的工具通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用 HMR,文件修改后的效果也需要几秒钟才能在浏览器中反映出来。如此循环往复,迟钝的反馈会极大地影响开发者的开发效率和幸福感。
我们忍忍就算了,但是大佬不能忍,必须要自己实现一个比webpack
更快的工具出来,Vite
就诞生了。自从发布以来,在社区讨论的声音很多,总体看下来,大家更多都是赶紧完善它,赶紧替代Webpack
。
大人时代变了
在这里我可以下结论:未来(即将到来)哪怕不是在前端构建工具领域,哪怕Vite
不是第一or社区主流,但是它今天所提供的解决问题思路必将盛行。
ES Modules已成主流
module sciprt
允许在浏览器中直接运行原生支持模块,当遇见import依赖时,会直接发起http请求对应的模块文件。
<script type="module">
// a.js可以通过export导出模块,也可以在其中继续使用import加载其他依赖
import A from ./a.js
</script>
从图中可以看到除了IE系列,主流浏览器基本支持ES Modules
。IE微软自己都放弃了,win10基本已经将Edge完全替代掉了IE。
再者,当下HTTP/2 的盛行,HTTP/3 也即将发行,再加上 5G 网络的商用,减少 HTTP 请求数量起到的作用已经微乎其微。
构建工具只有顺应历史发展,成为时代需要。
Vite和webpack区别
工作流程
webpack 原理图
webpack的简单流程:
- 识别入口文件
- 逐级递归识别依赖,构建依赖图谱
- 将代码转化成AST抽象语法树,在AST阶段中去处理代码
- 把AST抽象语法树变成浏览器可以识别的代码, 然后进行输出
宏观流程上来说,webpack会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。
这个流程在每一次保存代码的时候,都会重新走一遍。当项目越复杂、模块越多的时候,打包的时间等待的时间就越长。
Vite 原理图
由于现代浏览器本身就支持ES Module,会自动向依赖的Module发出请求。Vite
充分利用这一点,将开发环境下的模块文件,就作为浏览器要执行的文件,直接启动开发服务器,请求哪个模块再对该模块进行实时编译。这种按需动态编译的方式,极大的缩减了编译时间。
HMR方面
在HMR方面,当改动了一个模块后,仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高。
Vite的HMR是在EMS的基础上实现的,还会使用,缓存所以很快。
- 在 Vite 中,HMR 是在原生 ESM 上执行的。当编辑一个文件时,Vite 只需要精确地让已编辑的模块与其最近的 HMR 边界之间的链失效(大多数时候只需要模块本身),使 HMR 更新始终快速,无论应用的大小。
- Vite 同时利用HTTP头来加速整个页面的重新加载(再次让浏览器为我们做更多事情):源码模块的请求会根据 304 Not Modified 进行协商缓存,而依赖模块请求则会通过 Cache-Control: max-age=31536000,immutable 进行强缓存,因此一旦被缓存它们将不需要再次请求。
vite 1.x版本的内部使用的是KOA来实现静态服务器,2.x改用http模块了。
这种优势主要表现在开发阶段,当需要打包到生产环境时,Vite
还是使用传统的Rollup
进行打包,所以在代码中不可以使用CommonJS。
但是打包到生产环境,并不是日常高频操作,我们可以等待,但是在写代码到浏览器验证,这个过程产生卡顿感,就会让人产生不愉悦感。
Vite值得一提的优势
-
预编译:npm 包这类基本不会变化的模块,使用 Esbuild 在 预构建 阶段先打包整理好,减少 http 请求数
-
按需编译:用户代码这一类频繁变动的模块,直到被使用时才会执行编译操作
-
客户端强缓存:请求过的模块会被以 http 头
max-age=31536000,immutable
设置为强缓存,如果模块发生变化则用附加的版本 query 使其失效 -
产物优化:相比于 Webpack ,Vite 直接锚定高版本浏览器,不需要在 build 产物中插入过多运行时与模板代码
-
内置更好的分包实现:不需要用户干预,默认启用一系列智能分包规则,尽可能减少模块的重复打包
-
更好的静态资源处理:Vite 尽量避免直接处理静态资源,而是选择遵循 ESM 方式提供服务,例如引入图片
import img from 'xxx.png'
语句,执行后img
变量只是一个路径字符串。