给 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. writeBundlerollup 下面的钩子 ,仅在 bundle.write() 结束时调用,一旦所有文件都已写入开始执行 writeBundle钩子。rollup执行顺序可以参考下面图片

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

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

总结

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

相关推荐
程序员阿超的博客1 小时前
React动态渲染:如何用map循环渲染一个列表(List)
前端·react.js·前端框架
magic 2451 小时前
模拟 AJAX 提交 form 表单及请求头设置详解
前端·javascript·ajax
小小小小宇5 小时前
前端 Service Worker
前端
只喜欢赚钱的棉花没有糖6 小时前
http的缓存问题
前端·javascript·http
小小小小宇6 小时前
请求竞态问题统一封装
前端
loriloy6 小时前
前端资源帖
前端
源码超级联盟6 小时前
display的block和inline-block有什么区别
前端
GISer_Jing6 小时前
前端构建工具(Webpack\Vite\esbuild\Rspack)拆包能力深度解析
前端·webpack·node.js
让梦想疯狂6 小时前
开源、免费、美观的 Vue 后台管理系统模板
前端·javascript·vue.js
海云前端7 小时前
前端写简历有个很大的误区,就是夸张自己做过的东西。
前端