Vite5基础进阶和原理剖析

Vite5 的核心和基础使用

核心设计

  1. 木块化规范演进:commonjs -> amd -> cmd -> umd -> esmodule
  2. bundleless 模式,取决于浏览器原生 ESModule 的支持
  3. 本地开发 esbuild,线上构建 rollup

基本使用

  1. 脚手架初始化项目
  2. 工程化、规范、自动化
  3. 配置 Vite 体系。哪些内容需要打包,需要编译什么内容
    1. react 项目:@vitejs/plugin-react
    2. vue 项目:@vitejs/plugin-vue
    3. 官方文档,@vitejs/plugin-xxx
    4. unbundle
    5. vite-awesome

初始化项目

pnpm create vite 项目名 --template [react-ts/vue-ts]

vite.config.ts 配置

  1. plugins

  2. resolve

  3. server

  4. build

  5. manualChunks 静态拆包

  6. 模块懒加载

    1
    2
    3
    import("./src/utils").then((res) => {
    console.log(res);
    });

    上面代码会被单独打包成一个文件

  7. define 配置项用于在编译时定义全局常量,它会在代码被打包构建的过程中,将你指定的标识符替换为对应的值。简单来说,就是让你可以在源代码中直接使用一些
    “全局变量”,而这些变量会在构建阶段被静态替换为具体内容。

    核心作用

    • 注入全局常量:在代码中直接使用预定义的常量(如环境标识、API 地址等),无需手动导入。
    • 编译时替换:替换发生在构建阶段,而非运行时,不会增加运行时开销。
    • 条件编译:可以根据不同环境定义不同的值,实现代码的条件执行(如开发环境打印日志,生产环境移除日志)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
plugins: [react()],
// 模块化解析
resolve: {
// 别名
alias: {
"@": "src",
},
},
// 服务配置
server: {
port: 3000,
open: true,
// 跨域配置
proxy: {
"/api": {
target: "https://www.baidu.com",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
// 构建配置
build: {
outDir: "dist", // 打包输出目录
assetsDir: "assets", // 静态资源输出目录
minify: "terser", // 压缩,默认是压缩的, 也可以设置为 'esbuild'
sourcemap: true, // 生成 sourcemap 文件,开发环境下使用。如果是生产环境的话,可以用@sentry/vite-plugin 插件上传 sourcemap 文件,在 sentry 平台查看源代码。
terserOptions: {
// 压缩选项
compress: {
drop_console: true, // 移除 console
drop_debugger: true, // 移除 debugger
},
},
// 构建产物优化,代码分割
rollupOptions: {
// 入口文件配置
input: {
main: resolve(__dirname, "index.html"), // 入口文件
nested: resolve(__dirname, "nested/index.html"), // 嵌套入口文件
},
output: {
// 手动代码分割
// manualChunks:{
// 'react-vendor': ['react', 'react-dom'], // 将 react 相关的都打到同一个包里
// 'antd-vendor': ['antd'], // 将 antd 相关的都打到同一个包里
// }
manualChunks(id) {
// id 是模块的路径,根据路径匹配来代码分割
// 比如:node_modules/react/index.js
if (id.includes("node_modules")) {
return id
.toString()
.split("node_modules/")[1]
.split("/")[0]
.toString();
}
},
},
},
},
css: {
modules: {
// 仅对 CSS Modules 有效:即文件名需包含 .module(如 xxx.module.css、xxx.module.scss)的样式文件才会应用此配置。
hashPrefix: "hash",
},
},
define: {
IS_PROD: process.env.NODE_ENV === "production",
/*
* 在 js 或者组件中可以直接使用这个变量:
* if (IS_PROD) {
* console.log('生产环境'); // 生产环境构建时,这里会被替换为 true
* } else {
* console.log('开发环境'); // 开发环境构建时,这里会被替换为 false
* }
*/
},
json: {
namedExports: false, // 禁用命名导出,默认是开启的
/*
* // 1. 仅支持默认导出
* import data from './data.json';
* console.log(data.name); // 正常输出:"Vite"
*
* // 2. 具名导出会报错(Uncaught SyntaxError: The requested module './data.json' does not provide an export named 'name')
* import { name } from './data.json'; // 错误!
*
* */
stringify: true,
/*
* 若设置为 true,导入的 JSON 会被转换为 export default JSON.parse("..."),
* 这样会比转译成对象字面量性能更好,尤其是当 JSON 文件较大的时候。
* 如果设置为 'auto',只有当 数据大于 10kB 时,才会对数据进行字符串化处理。
* */
},
});

vite 插件开发

前置准备:vite-plugin-inspect 插件

vite-plugin-inspect 是 Vite 生态中的一个开发辅助插件,主要作用是可视化地查看 Vite 构建过程中的模块转换、插件执行流程和依赖关系,帮助开发者调试和理解
Vite 的内部工作机制。

Vite 为了将生态的扩充交给开发者,因此采用了插件化设计思想,定义了基础插件化协议,开发者可以根据协议开发自己的插件,以此来丰富
vite 生态。

Vite 插件的本质是函数,函数有返回值。

1
2
3
4
5
6
7
8
9
10
11
export default function viteHuaLuPlugin() {
return {
name: "vite-hua-lu-plugin", // 插件名称

// 插件方法
// transform(source,id){} 用于转换文件内容,id 是文件的路径,source 是文件的内容
transform(source, id) {
return source.replace(/hualu/g, "HUALU"); // 替换所有的 hualu 为 HUALU
},
};
}
1
2
3
4
5
6
7
// 配置自定义插件
import { defineConfig } from "vite";
import viteHuaLuPlugin from "./viteHuaLuPlugin";

export default defineConfig({
plugins: [viteHuaLuPlugin()],
});

vite 实现代码分包(减少首屏加载体积)

将大型第三方库(如 React、Ant Design、Lodash)从主 bundle 中剥离,单独打包成 vendor chunk,利用浏览器缓存机制提升加载效率。

Vite 优化配置 (build.rollupOptions.output.manualChunks)

Vite 底层使用 Rollup,通过 manualChunks 手动指定分包策略:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
// 将 React 相关库打包为 react-vendor.js
"react-vendor": ["react", "react-dom", "react-router-dom"],
// 将 Ant Design 和 Lodash 打包为 ui-vendor.js
"ui-vendor": ["antd", "lodash-es"],
},
},
},
chunkSizeWarningLimit: 1000, // 调整chunk大小警告阈值(kb)
},
});

(PS)webpack 优化配置(optimization.splitChunks)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
module.exports = {
optimization: {
splitChunks: {
chunks: "all", // 对同步和异步模块都进行分割
cacheGroups: {
// 提取 React 核心库
reactVendor: {
test: /[\\/]node_modules[\\/](react|react-dom|react-router-dom)[\\/]/,
name: "react-vendor",
priority: 20,
},
// 提取 UI 组件库
uiVendor: {
test: /[\\/]node_modules[\\/](antd|element-ui)[\\/]/,
name: "ui-vendor",
priority: 15,
},
// 其他第三方库
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
name: "vendor",
priority: 10,
},
},
},
},
};

vite 开启 Tree Shaking 与按需引入(剔除无用代码)

确保构建工具能正确识别并删除未使用的代码。

vite 生产环境打包默认支持 tree shaking

1
2
3
4
5
6
7
8
9
10
11
export default defineConfig({
build: {
minify: "terser",
terserOptions: {
compress: {
drop_console: true, // 生产环境移除 console.log
drop_debugger: true, // 移除 debugger
},
},
},
});

避免默认导入整个库,使用具名导入:ß

1
2
3
4
5
// ❌ 错误:引入整个 lodash,体积巨大
import _ from "lodash";

// ✅ 正确:只引入 debounce 函数
import { debounce } from "lodash-es";

Vite5基础进阶和原理剖析
https://zouhualu.github.io/20250421/Vite5基础进阶和原理剖析/
作者
花鹿
发布于
2025年4月21日
许可协议