面向未来的前端构建工具 - Vite(分享文档总结)

1,144 阅读5分钟

本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,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>

截屏2021-07-24 16.28.03.png

从图中可以看到除了IE系列,主流浏览器基本支持ES Modules。IE微软自己都放弃了,win10基本已经将Edge完全替代掉了IE。

再者,当下HTTP/2 的盛行,HTTP/3 也即将发行,再加上 5G 网络的商用,减少 HTTP 请求数量起到的作用已经微乎其微。

构建工具只有顺应历史发展,成为时代需要。

Vite和webpack区别

工作流程

webpack 原理图 webpack 原理图

webpack的简单流程:

  1. 识别入口文件
  2. 逐级递归识别依赖,构建依赖图谱
  3. 将代码转化成AST抽象语法树,在AST阶段中去处理代码
  4. 把AST抽象语法树变成浏览器可以识别的代码, 然后进行输出

宏观流程上来说,webpack会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。

这个流程在每一次保存代码的时候,都会重新走一遍。当项目越复杂、模块越多的时候,打包的时间等待的时间就越长。

vite 原理图 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 变量只是一个路径字符串。

参考文章

Vite官网

浅谈Vite 原理与 Webpack比较