vite 【vite 插件开发】

220 阅读3分钟

前言

一个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"|"不指定"
}

它的执行顺序如下

  1. alias:vite对配置的别名解析,插件中可以使用别名引入
  2. 带有enforce: 'pre'的用户插件
  3. Vite 核心插件
  4. 没有enforce值的用户插件
  5. Vite 构建用的插件
  6. 带有enforce: 'post'的用户插件
  7. 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 插件容器]