Vite 概述

随着浏览器的不断发展,越来越多的浏览器原生支持 ES 6 语法,这使得 ES 6 的模块化 API 可以直接在浏览器中使用。Vite 就是借助了这一特性,从而在开发环境下对构建进行了性能的提升,这也是它快速的体现。

怎么区分开发环境和生产环境

我们知道,Vite 在开发环境下基于浏览器原生 ES 6 Modules 提供功能支持,在生产环境下基于 Rollup 打包。所谓开发环境,就是日常代码编写调试的环境,在该环境下一般以开发者本身的浏览器环境、Node.js 环境等为结果导向,所以环境相对固定,复杂性较低,约束也较少。但是在该环境中,对构建速率、开发时间成本的要求很高,即要求高效率、低成本,代码更新后立刻看到结果。Vite 借助浏览器原生 ES 6 的方式在开发环境下提供服务能够很好地满足这些要求,使用 Vite 的页面在引入 JavaScript 时会加上 type=module,代码如下:

<head>
    <script type="module" src="/@vite/client"></script>
    ...
    <title>Vite App</title>
</head>
<body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
</body>

使用了 type=moduleJavaScript 文件会成为一个 module,所以才能够被 import 或者 export,而且这些文件本身也是前端页面必需的源码文件。

实际上,Vite 让浏览器接管了打包程序的部分工作,或者说 Vite 并不会操作文件的打包,而是将文件进行基础的编译,编译出能让现代浏览器识别的文件和语法,当浏览器访问这些文件时,就可以直接解析。这和事先将源码文件利用 Node.js 相关的 API 对文件进行复杂打包和利用 Webpack 进行复杂的编译,并将打包和编译后的内容提前生成并准备好场景是有本质区别的,如图 9-1 和图 9-2 所示。

image 2024 02 23 21 35 48 823
Figure 1. 图9-1 事先准备源码文件的方式
image 2024 02 23 21 38 11 571
Figure 2. 图9-2 采用原生 ES 6 Modules 的方式

而对于生产环境来说,用户端在访问业务时的环境是错综复杂的,无法预知用户在什么环境下使用业务,例如采用低版本浏览器或者在手机上使用,所以原生的 ES 6 Modules 的支持性并不好,即使支持 ES 6 Modules,但由于嵌套导入会导致额外的网络往返,在生产环境中发布未打包和压缩的 ES 6 Modules 文件仍然会影响加载速率。为了在生产环境中获得最佳的加载性能,最好还是将源码进行 Tree Shaking、懒加载以及拆分和压缩(以获得更好的缓存),这符合原本的生产环境通用的打包构建方式。

什么是Rollup

Vite 在生产环境下基于 Rollup 打包,生成前端所需的源码文件。Rollup 是一个 JavaScript 模块打包器,如图 9-3 所示,它最先提出了 Tree Shaking 的概念,和 Webpack 或者 Browserify 有着同样的模块打包功能,它最大的特点是基于 ES Modules 进行打包,不需要通过类似 Babel 转化的方案将 ES 6 Modulesimport 转化成 CommonJSrequire 方式,极大地利用了浏览器的原生特性。

image 2024 02 23 21 41 13 166
Figure 3. 图9-3 rollup.js

基于 ES 6 Modules 本身的特性以及 Tree Shaking, Rollup 可以最大化地保证打包后的文件体积更小,这也是 Vite 在生产环境下采用 Rollup 的主要原因。