给 Vite 项目创建一个自定义插件

前言

Vite 是一个前端构建工具,以其极快的开发服务器启动和模块热更新(HMR)功能而广受欢迎。它提供了灵活的插件系统,允许开发者扩展其功能。本文将带你一步步了解如何为 Vite 创建一个自定义插件,帮助你在项目中实现特定需求。

什么是 Vite 插件

Vite 插件是用于扩展 Vite 功能的自定义模块。它们可以在构建过程中执行特定任务,如转换代码、注入内容、优化性能等。

插件的作用和使用场景

Vite 插件的作用包括但不限于:

  • 文件解析和转换(如支持自定义文件类型)
  • 开发服务器功能扩展(如代理、Mock 数据)
  • 构建过程优化(如压缩、代码拆分)
  • 代码注入和替换

Vite 插件系统的优点

  • 灵活性:支持各种类型的插件,从简单的转换到复杂的编译器插件。
  • 易用性:通过简单的 API 即可创建和使用插件。
  • 性能:Vite 插件系统高效且性能优越。
  • Rollup Vite 插件扩展了设计出色的 Rollup 接口 所以相当数量的 Rollup 插件将直接作为 Vite 插件工作

设置开发环境 创建项目

  • 设置node 环境 我 node 版本采用的是16.20.2
  • 创建项目 我创建的是vue3 typescript 项目
kotlin 复制代码
npm init vite@latest
cd vite-project
npm i
npm run dev

vite 插件构建过程生命周期和 rollup 有点类似 参考下面图片

  • buildStart:构建开始前调用。

  • resolveId:解析模块路径时调用。

  • load:加载模块内容时调用。

  • transform:转换模块内容时调用。

  • buildEnd:构建结束后调用。

实现一个简单的插件

主要功能包含了2个 运行过程中文件内容替换 打包完成后将打包后的产物复制到其他目录

  • 在项目根目录创建文件 vite-plugin-files-diy.ts

这里 需要注意 用到了 node:fs 文件操作 所以需要安装 @types/node

css 复制代码
npm i --save-dev @types/node

vite-plugin-files-diy.ts 代码如下

vite-plugin-files-diy.ts 复制代码
import { ResolvedConfig } from 'vite'
import { createReadStream, createWriteStream, mkdirSync, existsSync } from 'node:fs';

// 自定义插件
export default function vitePluginFilesDiy() {
    let config: any = {}
    return {
        name: 'vite-plugin-files-diy', // 必须的 插件的名称,用于在警告和错误消息中标识插件。
        version: "1.0.0", //插件的版本,用于插件间通信场景。
        //apply: 'build', // 或 'serve' apply 属性指明它们仅在 'build' 或 'serve' 模式时调用
        configResolved(resolvedConfig: ResolvedConfig ) { //Vite 独有钩子 在解析 Vite 配置后调用。使用这个钩子读取和存储最终解析的配置。当插件需要根据运行的命令做一些不同的事情时,它也很有用。
            // 存储最终解析的配置
            config = resolvedConfig
        },
        // 在其他钩子中使用存储的配置
        transform(code:string, id: string) { //code 文件内容 id 是文件路径
            if (config.command === 'serve') {
                // dev: 由开发服务器调用的插件
                if (id.indexOf('.vue')>-1) {
                    const transformedCode = code.replace(/nnm/g, 'xxxxxxx');
                    return {
                        code: transformedCode,
                        map: null,
                    };
                }
            } else {
                // build: 由 Rollup 调用的插件
            }
        },
        async writeBundle() { //要在写入文件后修改文件
            //创建 newFile文件夹
            if (!existsSync('newFile')){
              await  mkdirSync('newFile') 
            }
            // 复制文件到 newFile 目录下
           await  createReadStream('./dist/index.html').pipe(createWriteStream(`./newFile/index.html`));

        }
        
    }
}

代码讲解-文件内容替换

  1. 在 configResolved 钩子中 把运行的配置信息存储了下来
  2. 在 transform 钩子中 用 config.command 判断环境 然后用id.indexOf 判断文件路径后缀为.vue的文件,再用正则替换代码内容 3.然后修改 components/HelloWorld.vue 内容

最终执行效果图如下

html 内容

js 输出

代码讲解-将打包后产物dist/index.html内容复制到newFile目录下

  1. 在 writeBundle 是 rollup 下面的钩子 ,仅在 bundle.write() 结束时调用,一旦所有文件都已写入开始执行 writeBundle钩子。rollup执行顺序可以参考下面图片

2. 利用 existsSync 判断文件夹是否存在着,不存在则 利用 mkdirSync 创建文件夹 newFile 3. 利用 createReadStream 读取文件流 后再利用pipe机制用 createWriteStream 写入文件流

当执行打包命令 npm run build 后 执行效果如下

总结

希望这篇文章能帮助你了解如何为 Vite 创建自定义插件。在平时开发难免遇到一些奇奇怪怪的需求,希望本篇文章能给你带来一些新的灵感,特别是代码注入、替换、转换、和性能优化、文件复制等操作。

相关推荐
treasure14010 小时前
【复古】浅尝Django前后端不分离
前端·css·python·django·bootstrap·html·web
jay神11 小时前
基于 YOLOv8 的手势识别系统(Web 版)
前端·人工智能·python·深度学习·yolo·计算机视觉·计算机毕业设计
屏什么录11 小时前
长时间录屏中途崩溃:MP4 打不开的 6 种救回方案与参数设置
前端·音视频开发
code_Bo12 小时前
不只命令行:我把跨 Agent 会话同步做成了桌面应用
前端·javascript·后端
kyriewen12 小时前
AI 能把页面写出来,为什么改个需求就开始崩?
前端·javascript·人工智能
涛涛ing13 小时前
2026年最值得关注的前端变化,藏在“默认值”里
前端
亿元程序员15 小时前
太牛了!这AI做出来的游戏,居然还能变现!
前端
hellice15 小时前
闪传 FlashDrop 实战:我用 300 行 Node 代码做了个「4 位取件码」临时文件中转站
前端·产品
用户08297732600515 小时前
RTX 5500 MIG 踩坑记录:切分之后模型跑不起来,排错整整一下午
前端
Lank_M15 小时前
AI 放大后的图更清楚,但它不能当原图入库
前端