vite插件
wǎng luò shí huāng 2025-05-11
vite
命令行
学习vite插件
参考文章:https://juejin.cn/post/7103165205483356168
- 插件执行顺序
- 插件生命周期
vite插件的执行顺序:
开发阶段/构建阶段 共同: 1. 别名解析阶段 2. 前置处理阶段 (enforce: 'pre') (自注:第三方插件先执行,然后才是vite插件执行。也就是说每个阶段都是第三方插件先执行,然后才是vite核心组件执行) 3. 核心处理阶段 (Vite 内置插件) 4. 正常处理阶段 (用户插件无 enforce) 5. 后置处理阶段 (enforce: 'post') 6. 最终处理阶段 (Vite 后置插件post) 构建阶段特有: 7. 构建输出阶段 (manifest, minify, reporting)
每个阶段的具体作用
# 阶段1:别名处理 Alias
作用:把
@/components/Button转成真实路径JavaScript// vite.config.js resolve: { alias: { '@': path.resolve(__dirname, 'src') } }1
2
3
4
5
6插件示例:Vite 内置的
vite:alias插件# 阶段2:用户插件 enforce: 'pre'
作用:在核心处理之前做一些预处理
JavaScript// 用户插件配置 export default function myPlugin() { return { name: 'my-plugin', enforce: 'pre', // ← 关键! transform(code, id) { // 在Vite处理前修改代码 if (id.endsWith('.vue')) { return code.replace('旧代码', '新代码'); } } } }1
2
3
4
5
6
7
8
9
10
11
12
13典型场景:
- 源代码预处理(如自定义模板语法)
- 自定义文件扩展名支持
- 修改源码后再给Vite处理
# 阶段3:Vite 核心插件
作用:Vite 的"大脑",处理各种文件
JavaScript// Vite内置的核心插件(部分) [ 'vite:modulePreload', // 模块预加载 'vite:resolve', // 模块解析 'vite:html-inline-proxy', // HTML代理 'vite:css', // CSS处理 'vite:esbuild', // JS/TS编译 'vite:json', // JSON处理 'vite:wasm', // WebAssembly 'vite:worker', // Worker处理 'vite:asset', // 静态资源 ]1
2
3
4
5
6
7
8
9
10
11
12# 阶段4:用户插件(无 enforce)
作用:最常用的插件位置,处理Vite编译后的内容
JavaScriptexport default function myPlugin() { return { name: 'my-plugin', // 不写 enforce,默认就是这个阶段 transform(code, id) { // 处理Vite编译后的代码 } } }1
2
3
4
5
6
7
8
9常见插件:
@vitejs/plugin-vue(处理 .vue 文件)@vitejs/plugin-react(处理 React)unplugin-auto-import(自动导入)
# 阶段5:用户插件 enforce: 'post'
作用:在所有处理之后,做最终调整
JavaScriptexport default function myPlugin() { return { name: 'my-plugin', enforce: 'post', // ← 后置处理 transform(code, id) { // 所有插件处理完后,最后修改代码 if (id.includes('node_modules')) { return code + '\n// 已处理完毕'; } } } }1
2
3
4
5
6
7
8
9
10
11
12典型场景:
- 最终代码优化
- 添加全局代码
- 第三方库的最终修改
# 阶段6:Vite 构建后置插件
作用:构建产物的最后处理
JavaScript// Vite构建阶段的最后插件 [ 'vite:build-html', // 构建HTML 'vite:css-post', // CSS后处理 'vite:terser', // 代码压缩 'vite:manifest', // 生成manifest.json 'vite:reporter', // 构建报告 ]1
2
3
4
5
6
7
8# 三、实战示例:理解执行顺序
# 场景:处理
.vue文件假设你有这样的配置:
JavaScript// vite.config.js import vue from '@vitejs/plugin-vue'; import myPrePlugin from './myPrePlugin'; import myPostPlugin from './myPostPlugin'; export default { plugins: [ myPrePlugin(), // enforce: 'pre' vue(), // 无enforce myPostPlugin(), // enforce: 'post' ] }1
2
3
4
5
6
7
8
9
10
11
12处理
App.vue文件的流程:1. Alias阶段:解析 @/components → src/components ↓ 2. myPrePlugin(enforce: 'pre'): - 可以预处理 .vue 文件的原始内容 ↓ 3. Vite核心插件: - 还没处理 .vue,因为不认识这种扩展名 ↓ 4. @vitejs/plugin-vue(无enforce): - 将 .vue 文件拆成 template/script/style - 交给Vite核心插件分别处理 ↓ 5. myPostPlugin(enforce: 'post'): - 对编译后的最终代码做最后调整 ↓ 6. Vite构建插件: - 压缩、生成manifest等1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 四、如何验证执行顺序?
# 方法1:添加日志插件
JavaScript// debug-plugin.js export default function debugPlugin(phase) { return { name: 'debug-plugin', enforce: phase, // 'pre' | undefined | 'post' transform(code, id) { console.log(`[${phase || 'normal'}] 处理文件: ${id}`); return code; } } } // vite.config.js import debugPlugin from './debug-plugin'; export default { plugins: [ debugPlugin('pre'), debugPlugin(), // 无enforce debugPlugin('post'), ] }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# 方法2:查看Vite实际插件顺序
Vite内部通过
sortUserPlugins排序:JavaScript// Vite源码简化版 function sortUserPlugins(plugins) { const prePlugins = []; const normalPlugins = []; const postPlugins = []; for (const plugin of plugins) { if (plugin.enforce === 'pre') prePlugins.push(plugin); else if (plugin.enforce === 'post') postPlugins.push(plugin); else normalPlugins.push(plugin); } return [...prePlugins, ...normalPlugins, ...postPlugins]; }1
2
3
4
5
6
7
8
9
10
11
12
13
14# 五、选择正确的 enforce 时机
# 什么时候用
enforce: 'pre'?JavaScript// 场景:需要修改原始代码,再交给Vite处理 { enforce: 'pre', transform(code, id) { // 自定义模板语法转换 if (code.includes('{{ myVar }}')) { return code.replace(/\{\{(\w+)\}\}/g, '<span>$1</span>'); } } }1
2
3
4
5
6
7
8
9
10# 什么时候用默认(无 enforce)?
JavaScript// 场景:处理Vite能识别的标准文件 { // 不写 enforce transform(code, id) { // 给所有JS文件添加水印 if (id.endsWith('.js')) { return `/* 来自我的插件 */\n${code}`; } } }1
2
3
4
5
6
7
8
9
10# 什么时候用
enforce: 'post'?JavaScript// 场景:在所有插件处理后做最终修改 { enforce: 'post', transform(code, id) { // 最终压缩前,移除console.log if (process.env.NODE_ENV === 'production') { return code.replace(/console\.log$$.*?$$;/g, ''); } } }1
2
3
4
5
6
7
8
9
10# 六、实际项目中的常见配置模式
JavaScript// vite.config.js export default { plugins: [ // 1. 前置插件:自定义处理 myCustomPrePlugin(), // 2. 框架插件:Vue/React等 vue(), // 3. 功能插件:自动导入、组件等 autoImport(), components(), // 4. 后置插件:优化、分析 visualizer({ enforce: 'post' }), // 5. 开发工具插件 ...(isDev ? [devPlugin()] : []), ] }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 记住这个核心原则:
enforce: 'pre'→ 你改代码给Vite处理 默认无 enforce → Vite处理完你再改enforce: 'post'→ 大家都改完你最后改就像流水线生产:
- 预处理原材料(pre)
- 核心生产线(Vite核心)
- 常规加工(用户插件默认)
- 最终包装(post)
- 出厂质检(Vite后置插件)
- 02
- Git 和 Husky 添加提交钩子并实现代码任务自动化01-30
- 03
- 其他工程化杂项08-29