相信大部分兄弟都体验过 Vite 了,知道它很快。但你知道它为什么快,相比 Webpack 有哪些不同吗?今天咱们就来全面了解一下 Vite ,尤其适合新手兄弟。一起学起来吧!
什么是构建工具
很多人对构建工具没有什么概念,只知道是用来打包的。那么到底什么是构建工具呢?
大家都知道浏览器只支持 Html、CSS、JavaScript,但一个企业级项目可能会用到各种各样的前端技术,如 Less、Sass、TS、Vue组件、语法降级、体积优化等,这时候我们就需要相应的工具去处理这些内容:
- 使用
less-loader
/sass-loader
处理 less / sass - 使用
tsc
将 typescript 转换为 javascript - 使用
vue-complier
将 vue 组件模板转换为 render 函数 - 使用
babel
将 es 的新语法转换为旧版浏览器认识的语法 - 使用
uglifyjs
将我们的代码压缩成体积更小的文件
我们可以手动把代码挨个处理一遍,但这样效率非常低,当我们稍微修改一点代码,这个流程又要重新走一遍,非常麻烦。有个神奇的东西,可以把以上工具集成到一起,整个流程交给它自动处理。而且当代码发生变化时,自动帮我们重新走一遍,这个东西就叫做构建工具。当然构建工具做的事情远不止于此,比如:
- 模块化开发支持:支持直接从 node_modules 里引入代码
- 提高项目性能:压缩文件、代码分割
- 优化开发体验:热更新、跨域问题
- …
构建工具减轻了我们的心智负担,让我们不用关心我们写的代码如何在浏览器运行,只需要关心代码怎么写就可以了。市面上主流的构建工具有 Webpack、Vite、esbuild、Rollup、Parcel,以及最近刚出的 turbopack ,但目前最流行的依然是 Webpack
和 Vite
。
Vite 相较于 Webpack 的优势
当项目体积越来越庞大时,构建工具需要处理的代码量呈指数级增长,包含数千个模块的项目也是相当普遍。类似 Webpack 的构建工具就会遇到性能瓶颈:通常需要很长时间,甚至几分钟项目才能启动起来。热更新(HMR)也可能需几秒,甚至十几秒。不知道大家目前的项目怎么样,反正我们公司稍微大一点的 Vue2 项目是真的慢,等的捉急。这种情况已经很大程度影响到了我们的开发效率和幸福感。
Webpack 有没有办法进行优化呢?很难。Webpack 先递归分析各模块依赖关系-构建依赖图谱,然后进行打包,再启动本地服务器。而且 Webpack 支持多种模块化规范,比如 CommonJS
、ES-Module
,一开始就要统一模块化代码,将所有的依赖全部处理一遍。整个流程如下图:
即使使用按需加载,也有一系列工作需要做,所以 Webpack 基本没有优化空间。
那么 Vite 为什么能解决这个问题呢?
- 底层语言。Vite 使用
esbuild
预构建依赖。esbuild
使用 Go 编写,比用 JS 编写的打包器预构建依赖快 10-100 倍。 - 先启动服务器,再按需请求模块并编译。Vite 利用的是现代浏览器本身支持
ES-Module
这个特性,直接向依赖的模块发出请求。Vite 启动时不需要分析模块之间的依赖关系,也不用打包,项目越大,优势越明显。
这个是 Vite 的启动过程:
这样大家应该看得出来 Vite 为什么快了吧!
依赖预构建
上面提到了依赖预构建,可能很多兄弟对这个不太理解,这里我也来讲一下。现代浏览器已经支持 ES-Module
,但导入模块只能用相对路径或绝对路径,直接使用模块名称的方式是行不通的:
// main.js
// 假设我们已经安装了 lodash 模块
import a from './a.js' // 支持
import b from '/b.js' // 支持
import _ from 'lodash' // 报错
依赖预构建就可以很好的解决这个问题。Vite 首先会找到依赖的模块,然后调用 esbuild
,将 CommonJS
等其他规范的代码转换成 ES-Module
规范,然后把它放在 node_modules/.vite/deps
目录下,接着再修改相应的引入路径。
由于浏览器是通过 HTTP 来请求模块文件的,一旦模块的依赖关系比较多的话,就会发起很多个网络请求。例如,lodash-es
内置模块超过 600 个,它们之前相互导入。当我们执行以下代码时,浏览器会同时发出 600 多个 HTTP 请求!大量的请求造成网络堵塞,导致页面的加载非常的慢。
import {
debounce } from 'lodash-es'
这时候还得靠依赖预构建,预构建将 lodash-es
整体转换为一个模块,这样我们就只需要发起一个 HTTP 请求了!
总结一下,依赖预构建为我们解决了以下三个头痛的问题:
- 兼容其他规范。不同的第三方依赖包会有不同的导出格式(如
CommonJS
规范)。 - 重写导入路径。例如
lodash
或重写为/node_modules/.vite/deps/lodash.js?v=fef37e66
,以便浏览器能够正确导入。 - 网络性能优化。Vite 会将内部有众多依赖关系的
ES-Module
模块转换为一个模块,提高页面的加载性能。
对不同内容的处理
学习一项技术,最好的方式是单独使用它。抛开脚手架工具,Vite 使用起来也非常的简单,直接在项目中安装 vite
,给个配置就可以了。当然不给也可以,Vite 会使用内置的默认配置:
npm install vite -D
// vite.config.js
import {
defineConfig } from 'vite'
export default defineConfig({
// ...
})
为了方便使用,可以在 package.json 添加启动和打包命令。
"scripts": {
"dev": "vite"