Vite
概览
基于 ES Module,因为浏览器原生支持 ES Module
生产环境使用 Rollup
打包,开发环境使用 ESBuild
打包。
还有一个正在进行中的工作,即构建一个名为 Rolldown
的 Rust 版本的 Rollup。一旦 Rolldown 准备就绪,它就可以在 Vite 中取代 Rollup 和 ESBuild,显著提高构建性能,并消除开发和构建之间的不一致性。
创建项目:
npm create vite@latest
# 或者
pnpm create vite
在搭建 Vite 项目时,执行npm create vite@latest
命令,这里的 create vite
只是内置了 Vite 的脚手架,并不是 Vite 本身,通过脚手架可以快速创建一个 Vite 项目。
vite 为什么比 webpack 快?
痛点:随着项目越来越大,webpack 需要很长时间才能启动开发服务器,即使使用 HMR,文件修改后的效果也需要几秒钟才能在浏览器中反映出来。迟钝的反馈会影响开发效率。
webpack 支持多种模块化规范,一开始就必须要统一模块化代码,这意味着需要将所有的依赖全部读一遍。处理后得到一个 Bundle,然后启动开发服务器。而 Vite 是一开始就启动开发服务器,在浏览器请求源码时进行转换(如转换 jsx、ts、less、vue 组件等)并按需提供源码,根据情景动态导入代码。
Vite 利用了浏览器原生支持的 ES 模块。只要在 script 标签上添加 type="module"
标记, main.js 就可以直接使用 import 语法去动态导入 js 文件。
路径补全
vite 在处理的过程中如果遇到了不是绝对路径、也不是相对路径的引用,则会尝试开启路径补全。
// main.ts 中使用的代码
import { createApp } from 'vue';
// 打开控制台 Network,发现会自动补全路径
import { createApp } from '/node_modules/.vite/deps/vue.js?v=19b29bc2';
会自动去 node_modules 中寻找依赖
依赖预构建
在首次启动 vite 时,Vite 会在本地加载站点之前预构建项目依赖。依赖预构建仅适用于开发模式。
首先 vite 会找到对应的依赖,然后调用 esbuild 将其他规范的代码转换成 ES Module 规范,然后放到当前目录下的 node_modules/.vite/deps
,同时对 ES Module 规范的各个模块进行统一集成。
- CommonJS 和 UMD 兼容性
- 解决网络多包传输的性能问题
在开发阶段中,Vite 的开发服务器将所有代码视为原生 ES 模块。在项目中使用的第三方依赖包可能是 CommonJS 或者 UMD 规范的。因此,Vite 需要先将它们转换为 ES Module。
例如在使用 lodash 时,lodash 可能也 import 了其他的第三方依赖包,浏览器会加载很多模块,造成性能问题。而 Vite 会将它们全部预构建,然后通过一个入口文件将这些模块合并成一个文件,减少网络传输。
假设项目中使用了 lodash-es
:
import lodashES from 'lodash-es';
console.log(lodashES);
查看 node_modules/lodash-es/lodash.js
会发现有一大堆的 export
。但是查看控制台的 Network,找到 http://localhost:5173/node_modules/.vite/deps/lodash-es.js?v=1bf1d6d1
这个请求,查看发现内容被 vite 重写了。而且浏览器没有同时发出大量的 HTTP 请求,vite 将其集成到一个模块,只发出了一次 HTTP 请求。
接下来验证一下,在 vite.config.js 中配置 optimizeDeps.exclude
来排除依赖预构建。
export default defineConfig({
optimizeDeps: {
exclude: ['lodash-es']
}
});