导航
Vite 是由 Evan You,Vue.js 的创始人,发起开发的。随着前端项目变得越来越复杂,传统构建工具如 Webpack 在构建速度和开发体验上逐渐显现出一些瓶颈。尤其是在开发环境中,构建速度慢、冷启动时间长,热更新不够流畅,影响了开发者的工作效率。
为了解决这些问题,Evan You 创建了 Vite。Vite 在设计时,最大化地利用了现代浏览器对 ES Modules 的支持,直接通过浏览器按需加载 JavaScript 模块,这让 Vite 在开发时能避免传统构建工具中的大量打包步骤,从而大幅提升开发效率。
Vite 针对开发环境和生产环境下的打包构建模式完全不一样,他主要由以下两个部分组成:
Vite 这样做的主要目的是为了在开发环境构建项目时能获得极快的体验。
ES6 Module 也被称作 ES Module (或 ESM ), 是由 ECMAScript 官方提出的模块化规范,作为一个官方提出的规范, ES Module 已经得到了现代浏览器的内置支持。在现代浏览器中,如果在 HTML 中加入含有 type="module" 属性的 script 标签,那么浏览器会
按照 ES Module 规范来进行依赖加载和模块解析,这也是 Vite 在开发阶段实现 no-bundle 的原因,由于模块加载的任务交给了浏览器,即使不打包也可以顺利运行模块代码,具体的模块加载流程我们会在下一节进行详细的解释。
大家可能会担心 ES Module 的兼容性问题,其实 ES Module 的浏览器兼容性如今已经相当好了,覆盖了 90% 以上的浏览器份额。
不仅如此,一直以 CommonJS 作为模块标准的 Node.js 也紧跟 ES Module 的发展步伐,从 12.20 版本开始正式支持原生 ES Module。也就是说,如今 ES Module 能够同时在浏览器与 Node.js 环境中执行,拥有天然的跨平台能力。
下面是一个使用 ES Module 的简单例子:
main.js
import { methodA } from "./module-a.js";
methodA();
module-a.js
const methodA = () => {
console.log("a");
};
export { methodA };
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./main.js"></script>
</body>
</html>
如果在 Nodejs 环境中,你可以在 package.json 中声明 type: "module" 属性:
// package.json
{
"type": "module"
}
然后 Nodejs 便会默认以 ES Module 规范去解析模块:
node main.js
# 打印 a
顺便说一句,在 Node.js 中,即使是在 CommonJS 模块里面,也可以通过 impont 方法顺利加载 ES 模块,如下所示:
async function func() {
// 加载一个 ES 模块
// 文件名后缀需要是 mjs
const { a } = await import("./module-a.mjs");
console.log(a);
}
func();
module.exports = {
func,
}
创建名为vite-demo的文件夹作为当前项目的根目录
在当前目录下,执行以下命令初始化package.json文件。
npm init -y
执行以下命令,安装 Vite
npm i vite -D
根据以下目录结构,创建项目
vite-demo
├─ index.html # 项目打包入口文件
├─ main.js
├─ basic.js
├─ package-lock.json
└─ package.json
vite-demo/index.html 文件<head>
<!--ES模块化方式引入main.js-->
<script type="module" src="./main.js"></script>
</head>
Vite 默认以当前项目根目录下的
index.html文件作为打包的入口文件, 并且他是基于原生 ES 模块提供服务。所以在
index.html文件中要通过 ES 模块方式加载 JS 文件。
vite-demo/main.js文件// 导入 basic.js文件中变量
import { username, age } from "./basic.js";
const sex = "女";
const hobbies = ["唱歌", "跑步", "音乐"];
console.log(`${username}姓别${sex},今年${age}岁了,他喜欢${hobbies.join(",")}`);
vite-demo/basic.js文件export const username = "艾编程";
export const age = 23;
在当前项目根目录下执行以下命令,启动开发服务。
npx vite # 相当于开发环境下打包,不过Vite并不会对源码打包处理
命令执行后,并没有当前根目录下新建dist目录,而是在命令终端显示以下代码
➜ Local: <http://localhost:5173/>
➜ Network: use --host to expose
➜ press h to show help
在浏览器中访问上面Local字段对应的http://localhost:5173/地址,然后在当前地址下打开浏览器的Console控制面板。
看到如下输出结果,说明服务启动成功。

然后,我们切换到Network面板,如下图:

通过上图,可以看到
main.js和basic.js是通过浏览器直接发请求获取的,并没有做相关的打包工作。
源码执行打包工作,而是直接启动一个服务器加载当前根目录下的index.html文件(默认情况下,index.html文件为打包的入口文件)index.html 里面的 JS 文件,然后顺着依赖加载其它的 JS 文件。执行以下命令,来完成生成环境下打包工作
npx vite build
命令执行后,会在当前目录下生成dist文件夹,dist目录结构如下:
dist
├─ assets // 打包后的资源放在assets目录下
│ └─ index-B2m--zVl.js // main.js打包后生成的js文件
└─ index.html // 项目入口文件
可以看到,打包后,
main.js及相关的依赖全部被打包生成了一个 JS 文件。
查看打包后的index.html文件,内容如下:
<script type="module" crossorigin src="/assets/index-bdbbf184.js"></script>
可以看到,打包后依然采用的是 ES 模块化来加载打包后生成的 JS 文件。
如果我们直接在 VSCode 中打开dist目录下的index.html页面,在浏览器控制台会抛出以下错误