浅析vite打包速度快的原因

238 阅读8分钟

前言

vite刚出来时候,主流对vite并不看好,那时都觉得这是一种重复造轮子行为。

随着时间推移,如今vite也成了主流的打包工具之一,逐渐被社区认可。

于是,我们现在来分析一下vite为什么能成为社区认可的新秀。

正文

关于为什么选用vite,官方在开局的文档中就写明白了,文档写的很清楚,并不谜语人。

核心就一点,快。

这里默认大家都对Vite有个最基础的认识,如果不清楚vite是什么,可以参考Vite 文档

在正式开始之前,我们先简单整理下,如何简单的应对面试官的八股文答案。

vitewepack

webpack作为项目打包的老大哥级别的工具,vite从一出现就在和webpack对比。

比起webpack的全,vite的核心就是快。

而且,随着时间的推移,vite的生态和完善程度逐渐不逊色于webpack,未来如果没有新的打包工具顶替的话,vite可能就是未来的主流打包工具了。

这里如果面试官问你为什么选用vite而非webpack,你可以从以下角度来回答面试官。

  1. vite使用了ES Module的构建方式,更符合现代浏览器规范,而webpack因为历史遗留问题,依然是将所有的JS文件打包成一个bundle,两者构建方式不同,而vite的启动方式更快。
  2. vite是基于路由实现的按需加载模式,所以在开发状态下,某个页面的报错并不影响整个项目的开发,这可以节省处理很多意料之外问题的时间。
  3. Vite 将会使用 esbuild 预构建依赖。esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。
  4. Vite 将在下版本使用 Rolldown (rust版本的Rollup),因为Rust的性能优秀,所以未来生产环境打包速度也会更快。
  5. vite在优化这些开发状态的体验下,依然支持react和vue等现代JS开发框架,同时对TS等也有较好的支持,并且也有相对良好的插件生态库。

总的来说,vite更多优化了开发时候的体验,使得开发者在开发时不必再像以往那样等待那么长的启动时间。

开发优化

上边都是针对面试官的简略回答,下边是个人这两天根据整合的资料和官网的经验,汇总出来的。

从目前的整理的资料来看,vite相对于webpack,更多优化的是开发体验,通过各种手段大幅缩减了项目启动和热更新的时间。

如果您在以往项目开发中,对项目启动时感到等待枯燥,我十分建议您在新项目体验一下vite,对于开发来说,vite的构建确实很快。

构建方式

Webpack 通过构建整个项目的依赖图,将所有资源打包成一个或多个 bundle 文件,每次重启都需要打包。

Vite 采用了即时编译的方式,在开发模式下通过浏览器原生支持的 ES Module 特性进行加载,不需要打包。

这两种不同的构建方式,在开发时候有截然不同的体验。

  1. vite开发时启动速度极快,因为构建模式的独特性,vite利用了现代浏览器对ES Module的支持,所以vite不需要像webpack那样开局打包所有的文件来跑热更新,所以在开发模式下,速度远比webpack快的多。
  2. vite是按需编译,有些页面如果有报错,你不打开对应的页面,就不会影响到整个项目。相对的,如果是webpack某个页面的JS文件报错,那么整个项目会更新失败,进而影响整个项目的打开。
  3. 在HRM热更新⽅⾯,当某个模块内容改变时,让浏览器去重新请求该模块即可,⽽不是像webpack重新将该模块的所有依赖重新编译;

热更新

Webpack 的热更新通常需要借助 webpack-dev-server 等插件,在一些情况下配置起来比较复杂。

Vite 内置了基于浏览器原生模块热更新的开发服务器,无需额外配置即可实现快速的热更新。

浏览器缓存

vite利用304浏览器缓存协议,减少了前端请求不必要的数据传输。

针对预构建的依赖会通过使用 HTTP 头的 max-age=31536000, immutable,来进行强缓存。

后续如果文件没有发生变更则会直接命中缓存,通过从而提升开发期间的性能,减少了开发过程的无效文件请求。

这里为了防止有人忘了304协议的具体内容,我下边顺手贴一下。

304协议

在HTTP协议中,状态码304 Not Modified表示客户端发送了一个带有缓存的请求,并且服务器告诉客户端缓存的版本是最新的,因此不需要下载新的资源。

具体来说,当客户端向服务器请求某个资源时,如果该资源自从上次请求后没有发生改变,服务器就会返回一个304 Not Modified的状态码,而不是实际的数据。这意味着客户端可以继续使用其缓存中的版本。

这种行为对于提高网站性能和减少网络流量非常有用,因为它避免了不必要的数据传输。

通常,当客户端发送GET请求时会包含条件请求头(例如If-Modified-SinceIf-None-Match),服务器会检查这些头信息来判断是否需要发送完整的响应体还是仅仅返回304 Not Modified状态码。

依赖项合并

在对依赖进行预构建时,vite 还会针对那些文件内又包含了许多其它导入语句的模块进行合并,这是为了减少页面请求文件的数量,节约性能的消耗。

前面我们说过,vite 是通过浏览器对模块化的识别能力在请求文件的。

比如,我们在项目中使用 import { debounce } from 'lodash-es' 导入了 debounce 这个模块,而在 debounce 模块中又导入了其它的模块。

这样周而复始,这些 import 语句都会被浏览器识别,浏览器为了请求文件就会发出大量的 htttp 请求最终导致网络拥堵;

为了解决这个问题,vite 会分析这些文件将它们转换合并为单个模块。

这样一来,当执行 import { debounce } from 'lodash-es' 时,只需要发送一个 htttp 请求来获取整个 lodash-es 的代码就可以了

底层语言

webpack是用JS编写的,在源码层级上本身就落后于vite。

Vite 将会使用 esbuild预构建依赖,esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。

不过,这里需要注意,这里所说的快,是指开发环境下,esbuild是支持开发环境,不是正式打包环境。

在正式打包环境下,vite依然用的是rollup实现打包构建的,底层语言仍然是JS,所以在生产环境状态下,二者的底层原理依然是相似的。

开发配置

Webpack 需要较多的配置,对复杂的项目来说,需要花费时间和精力来配置各种 loader 和 plugin。

Vite 开箱即用,不需要复杂的配置即可快速启动项目,支持各种插件以满足特定需求。

当然,这也是得益于站在前人的肩膀上,也可能是因为vite目前也只是一个新工具,新生的,总是简单的。

随着后续的生态逐渐扩大,很难说vite的配置项是否会像现在这般简洁易用。

结语

vite的核心就是快,随着未来前端项目铺开,vite的推广必然成为主流。

在日新月异的时代里,连学技术都有一种赌运气的感觉,不知为何,心里也是颇为无奈,或许这就是开荒期吧,一将功成万骨枯。

不过,不论如何,还是顺应时代吧,随着vite的逐步完善,也许未来5年左右,vite可能就会取代webapck在前端开发中的地位。

参考

开始 | Vite 官方中文文档 (vitejs.cn)

Vite 详解

面试常问:为什么 Vite 速度比 Webpack 快?

浅析Vite本地构建原理

【Vite为什么快【我是哈默 | Vue小知识】】

人人都说 vite 快,但它究竟为啥快?