前言
一个vite插件其实就是一个具有指定属性的普通js对象
export default {
name:"plugin-name",// 插件名称,会出现在异常或打印信息中
transform(){},// 钩子函数,在指定的时机执行,通过 入参和return 对 加载或打包 结果进行修改
...其他的属性
}
1.执行场景
可以通过一些属性指定插件在下面任何场景执行
- 只在开发(构建)阶段:
server - 打包阶段:
build - 都执行
实现上面效果值需要增加一个特定apply属性即可
export default {
apply:"build"|"server",// 不指定apply则在开发和打包阶段都执行
}
2.执行顺序
vite有很多内置的插件和一些核心底层功能的插件,它们有可能会对源码进行了一些处理。在默认情况下,自定义编写的插件会在核心插件之后执行,自定义插件得到代码或数据就是处理后的数据,如果需要插件第一个处理未经更改的源码或数据可以指定执行顺序
export default {
enforce:"pre"|"post"|"不指定"
}
它的执行顺序如下
alias:vite对配置的别名解析,插件中可以使用别名引入- 带有
enforce: 'pre'的用户插件 - Vite 核心插件
- 没有
enforce值的用户插件 - Vite 构建用的插件
- 带有
enforce: 'post'的用户插件 - Vite 后置构建插件(最小化,manifest,报告)
2.常用属性
vite插件运行在vite内置一个rollup插件环境中,所以它的属性除了vite特有的其他的都和rollup插件一致。
这里我们标准一些使用频率较高的属性
export default {
name:"plugin-name",
apply:"server",
config(configOptions){}, // 修改配置
transform(code,id){}, // 转换源码
handleHotUpdate(ctx){}, // 修改热更新时加载的代码
}
3.vite插件工作机制
有的人会疑惑,vite不是在开发时使用了esbuild进行依赖处理,只在打包时使用rollup进行打包任务。
那么为什么通过rollup插件环境执行的vite插件在开发阶段还会执行呢?
其实rollup在vite扮演了相当重要的一个角色。
- 生产环境:完全使用rollup进行打包
- 开发环境:vite直接使用了rollup的插件系统(通过
rollup-plugin-container实现)
因此,vite和rollup的插件可以共用。但是vite插件中特有的钩子,在rollup中使用时不会执行
4.rollup比esbuild慢,在开发阶段rollup插件环境是否会影响性能
在构建阶段,vite使用了esbuild处理依赖,众所周知esbuild使用go编写,执行速度比rollup快10-100倍,那么我们使用vite插件对依赖进行处理是否会降低开发阶段的性能呢?
会!但是影响极小。vite设计了一套优化策略,对node_modules中的依赖和源码文件(ts\js)的处理都交给了esbuild,只有一些特殊的文件必须需要rollup插件处理才会走rollup
graph TD
A[浏览器请求] --> B{是否为预构建依赖?}
B -->|是| C[直接返回预编译后文件]
B -->|否| D{是否需要插件处理?}
D -->|否| E[用 esbuild 原生转换]
D -->|是| F[进入 Rollup 插件容器]