跳至内容

为什么选择 Vite

问题

在浏览器中可以使用 ES 模块之前,开发人员没有原生机制以模块化方式编写 JavaScript。这就是我们都熟悉“打包”概念的原因:使用能够爬取、处理和连接我们的源模块的工具,将其打包成可以在浏览器中运行的文件。

随着时间的推移,我们看到了像 webpackRollupParcel 这样的工具,它们极大地改善了前端开发人员的开发体验。

但是,随着我们构建越来越复杂的应用程序,我们处理的 JavaScript 代码量也在急剧增加。大型项目包含数千个模块并不罕见。我们开始遇到基于 JavaScript 的工具的性能瓶颈:启动开发服务器通常需要很长时间(有时长达几分钟!),即使使用热模块替换 (HMR),文件编辑也可能需要几秒钟才能反映在浏览器中。缓慢的反馈循环会极大地影响开发人员的生产力和幸福感。

Vite 旨在通过利用生态系统中的新进展来解决这些问题:浏览器中原生 ES 模块的可用性,以及用编译为原生语言编写的 JavaScript 工具的兴起。

缓慢的服务器启动

在冷启动开发服务器时,基于打包器的构建设置必须急切地爬取并构建整个应用程序,然后才能提供服务。

Vite 通过首先将应用程序中的模块分为两类来改进开发服务器启动时间:依赖项源代码

  • 依赖项主要是纯 JavaScript,在开发过程中很少更改。一些大型依赖项(例如包含数百个模块的组件库)也很昂贵。依赖项也可以使用各种模块格式(例如 ESM 或 CommonJS)提供。

    Vite 使用 esbuild 预打包依赖项。esbuild 是用 Go 编写的,预打包依赖项的速度比基于 JavaScript 的打包器快 10-100 倍。

  • 源代码通常包含需要转换的非纯 JavaScript(例如 JSX、CSS 或 Vue/Svelte 组件),并且会经常编辑。此外,并非所有源代码都需要同时加载(例如,使用基于路由的代码拆分)。

    Vite 通过 原生 ESM 提供源代码。这实际上是让浏览器接管打包器的一部分工作:Vite 只需要按需转换和提供源代码,因为浏览器会请求它。条件动态导入后面的代码只有在当前屏幕上实际使用时才会被处理。

Bundle based dev server entry ··· route route module module module module ··· Bundle Server ready
Native ESM based dev server entry ··· route route module module module module ··· Server ready Dynamic import (code split point) HTTP request

缓慢的更新

在基于打包器的构建设置中,当编辑文件时,重新构建整个包效率低下,原因很明显:更新速度会随着应用程序大小线性下降。

在一些打包器中,开发服务器在内存中运行打包,因此当文件发生更改时,它只需要使模块图的一部分失效,但它仍然需要重新构建整个包并重新加载网页。重新构建包可能很昂贵,重新加载网页会清除应用程序的当前状态。这就是一些打包器支持热模块替换 (HMR) 的原因:允许模块“热替换”自身,而不会影响页面上的其他部分。这极大地改善了 DX - 然而,在实践中,我们发现即使 HMR 更新速度也会随着应用程序大小的增长而显著下降。

在 Vite 中,HMR 是通过原生 ESM 执行的。当编辑文件时,Vite 只需要精确地使编辑的模块与其最近的 HMR 边界之间的链失效(大多数情况下只有模块本身),从而使 HMR 更新始终快速,无论应用程序的大小如何。

Vite 还利用 HTTP 标头来加速完整页面重新加载(再次,让浏览器为我们做更多工作):源代码模块请求通过 304 Not Modified 条件地发出,依赖项模块请求通过 Cache-Control: max-age=31536000,immutable 强制缓存,因此它们在缓存后不会再次命中服务器。

一旦您体验到 Vite 的速度有多快,我们非常怀疑您是否愿意再次忍受打包的开发。

为什么在生产环境中打包

即使原生 ESM 现在得到了广泛支持,在生产环境中发布未打包的 ESM 仍然效率低下(即使使用 HTTP/2),因为嵌套导入会导致额外的网络往返。为了在生产环境中获得最佳的加载性能,最好还是将代码打包,并进行树摇、延迟加载和公共块拆分(以实现更好的缓存)。

确保开发服务器和生产构建之间的最佳输出和行为一致性并不容易。这就是 Vite 附带预配置的 构建命令 的原因,该命令开箱即用地包含许多 性能优化

为什么不使用 esbuild 打包?

Vite 当前的插件 API 与使用 esbuild 作为打包器不兼容。尽管 esbuild 更快,但 Vite 对 Rollup 的灵活插件 API 和基础设施的采用极大地促成了其在生态系统中的成功。目前,我们认为 Rollup 提供了更好的性能与灵活性的权衡。

Rollup 也一直在努力改进性能,在 v4 中将其解析器切换到 SWC。并且正在努力构建一个名为 Rolldown 的 Rust 移植版本。一旦 Rolldown 准备就绪,它就可以在 Vite 中取代 Rollup 和 esbuild,从而显著提高构建性能,并消除开发和构建之间的不一致。您可以观看 Evan You 在 ViteConf 2023 上的主题演讲以了解更多详细信息

Vite 与 X 有什么不同?

您可以查看 比较 部分,以详细了解 Vite 与其他类似工具的不同之处。