Webpack一直是主流的前端构建工具,但是在近年来Vite越来越备受关注。它们的出现使得前端开发变得更加高效和便捷。在性能方面,Vite相比于Webpack表现出了明显的优势,尤其是在本地开发时冷启动速度、HMR(Hot Module Replacement,热更新)性能和构建速度等方面。本文将说说Vite比Webpack更快的原因。
一、构建方式区别
当我们使用Webpack打包项目时候,会把相关的资源(代码、样式等)生成多个bundle文件,再在HTML中通过<script>标签引入这些budle文件进行程序接下来的运行。如上图黄色框所示,当代码越来越多的时候,需要打包的模块也越来越多,Webpack得找所有相关的依赖图,这个过程意味着消耗更多的时间。
如图所示,在本地启动一个Vite项目时候,Server在一开始的时候就启动,而不是找到所有依赖打完包再启动。
Vite启动后再去加载对应的文件,主要有一下的特点:
1、基于浏览器原生ES模块的支持:
Vite 利用了现代浏览器对 ES 模块(ESM)的原生支持,采用的是一种no bundle的策略,当使用 Vite 启动项目时,它会将每个模块都作为一个独立的文件提供给浏览器,而不需要像传统的打包工具(如 Webpack)那样先将模块打包成一个或多个 bundle。这样一来,浏览器可以更快地加载和解析这些模块,从而实现了快速的冷启动速度。
2、即时编译(Instant Compilation):
Vite 采用了即时编译策略。当浏览器请求一个模块时,Vite 会即时地将该模块编译成浏览器可执行的代码,并将编译结果缓存起来(我们在node_modules下可以找到一个.vite文件)。下次再次请求同一模块时,Vite 可以直接返回缓存的编译结果,而不必重新编译,从而避免了冗余的编译过程,大大提高了启动速度。
3、esbuild预构建依赖:
Go 语言编写的快速、轻量级的 JavaScript/TypeScript 构建工具,比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。
二、热更新
Webpack 的热更新机制是通过 webpack-dev-server 提供的功能来实现的。webpack-dev-server 是一个开发服务器,用于在开发过程中提供快速的开发体验,包括热更新、自动刷新等功能。
Webpack-dev-server 的热更新机制是基于 WebSocket 技术实现的。当你启动 webpack-dev-server 时,它会创建一个 WebSocket 服务器,与浏览器端建立连接。然后,webpack-dev-server 会监视项目文件的变化,并将这些变化推送给浏览器端,浏览器端收到变化后会执行相应的更新操作,从而实现了热更新的效果。
具体来说,webpack-dev-server 的热更新机制包括以下几个步骤:
1、创建 WebSocket 服务器:webpack-dev-server 在启动时会创建一个 WebSocket 服务器,并与浏览器端建立连接。
2、监听文件变化:webpack-dev-server 会监听项目文件的变化,包括入口文件、模块文件、样式文件等。
3、构建更新模块:当文件发生变化时,webpack-dev-server 会重新构建变化的模块,并生成更新的代码。
4、推送更新信息:webpack-dev-server 将更新的模块信息通过 WebSocket 推送给浏览器端。
5、浏览器端处理更新:浏览器端接收到更新信息后,会根据更新的模块信息执行相应的更新操作,例如重新加载模块、更新页面内容等。
而Vite 也使用了 WebSocket 技术来实现与浏览器的通信。当有模块变化时,Vite 会通过 WebSocket 将更新信息推送给浏览器端,从而触发浏览器端的模块重载。这样看起来,它和Webpack似乎没有什么不同,但是根据Vite官网的说法,在 Vite 中,HMR 是在原生 ESM 上执行的。当编辑一个文件时,Vite 只需要精确地使已编辑的模块与其最近的 HMR 边界之间的链失活(大多数时候只是模块本身),使得无论应用大小如何,HMR 始终能保持快速更新。从官网的解释中我们可以理解为,Vite因为支持ESM的能力,使得它比Webpack拥有更小粒度的热更新能力。
三、生产环境
在生产环境下,二者的打包,构建时间就没有这么大的区别了,因为在生产环境下Vite仍需要通过Rollup将代码打包。主要是基于以下几点考虑。
1、兼容性:尽管现代浏览器对 ESM 模块有很好的支持,但在生产环境中仍然需要考虑到旧版浏览器的兼容性。为了确保应用在所有浏览器中都能正常运行,需要将 ESM 模块转换成兼容性更好的 JavaScript 代码,通常是通过打包工具进行转换和优化。
2、性能优化:在生产环境中,需要对代码进行一些性能优化,如代码压缩、合并、分割等,以减小代码体积、加快页面加载速度。通过打包工具,可以将多个模块合并成一个或多个 bundle,并对代码进行压缩和混淆,以减小文件体积。
3、资源管理:除了 JavaScript 代码外,现代的前端应用还包含许多其他类型的资源,如样式表、图片、字体等。打包工具可以帮助管理这些资源,将它们进行优化、压缩,并生成适当的 URL 地址,以便在生产环境中有效地加载和使用这些资源。
4、部署和发布:在生产环境中,需要将应用部署到服务器上,并且通常会对代码进行一些配置和优化。通过打包工具,可以方便地生成部署所需的静态文件,并进行一些配置,如路径设置、缓存控制等,以便于部署和发布应用。
四、总结
Vite在本地能更快的根本原因,是借用了浏览器原生ESM能力,从而跳过了生成bundle的时间,再加上能够不依赖第三方插件将编译结果缓存,而且esbuild自身的也有着更快的运行速度,从而实现了Vite快速的冷启动。