Vite Plugin 开发完全指南

 更新时间:2026年05月25日 09:18:32   作者:兆子龙  
本篇文章详细介绍了Vite插件开发,涵盖VitePlugin基础使用、核心钩子详解、Rollup环插件应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、第一个 Vite Plugin

1.1 创建基础 Plugin

// plugins/vite-plugin-example.js
export default function examplePlugin() {
  return {
    name: 'vite-plugin-example',
    
    config(config) {
      console.log('config hook');
      return {
        define: {
          __PLUGIN_VERSION__: '"1.0.0"'
        }
      };
    },
    
    configResolved(config) {
      console.log('configResolved hook');
    },
    
    transform(code, id) {
      console.log('transform:', id);
      return code;
    }
  };
}

1.2 在 Vite 配置中使用

// vite.config.js
import { defineConfig } from 'vite';
import examplePlugin from './plugins/vite-plugin-example';

export default defineConfig({
  plugins: [
    examplePlugin()
  ]
});

二、核心钩子详解

2.1 config 和 configResolved

export default function configPlugin() {
  return {
    name: 'config-plugin',
    
    config(config, { command, mode }) {
      console.log('Command:', command); // 'serve' or 'build'
      console.log('Mode:', mode); // 'development' or 'production'
      
      // 修改配置
      return {
        server: {
          port: 3000
        },
        build: {
          outDir: 'dist'
        }
      };
    },
    
    configResolved(config) {
      // 读取最终配置
      console.log('Final config:', config);
    }
  };
}

2.2 configureServer 开发服务器

export default function devServerPlugin() {
  return {
    name: 'dev-server-plugin',
    
    configureServer(server) {
      // 添加中间件
      server.middlewares.use((req, res, next) => {
        console.log('Request:', req.url);
        next();
      });
      
      // 自定义路由
      server.middlewares.use('/api/hello', (req, res) => {
        res.end('Hello from Vite Plugin!');
      });
      
      // 监听 WebSocket 事件
      server.ws.on('connection', (ws) => {
        ws.send('Welcome!');
      });
    }
  };
}

2.3 transformIndexHtml 转换 HTML

export default function htmlPlugin() {
  return {
    name: 'html-plugin',
    
    transformIndexHtml(html) {
      return html.replace(
        '<head>',
        `<head>
          <meta name="plugin-version" content="1.0.0">
        `
      );
    }
    
    // 或者返回对象
    transformIndexHtml(html) {
      return {
        html,
        tags: [
          {
            tag: 'script',
            attrs: { src: '/custom-script.js' },
            injectTo: 'head'
          }
        ]
      };
    }
  };
}

三、Rollup 钩子在 Vite 中的应用

3.1 resolveId 解析模块

export default function resolvePlugin() {
  return {
    name: 'resolve-plugin',
    
    resolveId(source, importer) {
      if (source === 'virtual:my-module') {
        // 标记为虚拟模块
        return '\0virtual:my-module';
      }
      return null; // 让其他插件处理
    }
  };
}

3.2 load 加载模块

export default function loadPlugin() {
  return {
    name: 'load-plugin',
    
    load(id) {
      if (id === '\0virtual:my-module') {
        return `
          export const message = 'Hello from virtual module!';
          export const version = '1.0.0';
        `;
      }
      return null;
    }
  };
}

3.3 transform 转换代码

export default function transformPlugin() {
  return {
    name: 'transform-plugin',
    
    transform(code, id) {
      // 只处理 .js 文件
      if (!id.endsWith('.js')) return;
      
      // 简单的代码转换
      const transformedCode = code.replace(
        /console\.log\(/g,
        'console.log("[Plugin] "'
      );
      
      return {
        code: transformedCode,
        map: null // sourcemap
      };
    }
  };
}

四、实战案例一:虚拟模块

4.1 创建虚拟模块 Plugin

// plugins/vite-plugin-virtual.js
export default function virtualModulePlugin() {
  const virtualModuleId = 'virtual:env-info';
  const resolvedVirtualModuleId = '\0' + virtualModuleId;

  return {
    name: 'vite-plugin-virtual',

    resolveId(id) {
      if (id === virtualModuleId) {
        return resolvedVirtualModuleId;
      }
    },

    load(id) {
      if (id === resolvedVirtualModuleId) {
        return `
          export const NODE_ENV = '${process.env.NODE_ENV || 'development'}';
          export const VERSION = '${process.env.npm_package_version || '1.0.0'}';
          export const BUILD_TIME = '${new Date().toISOString()}';
        `;
      }
    }
  };
}

4.2 使用虚拟模块

// src/main.js
import { NODE_ENV, VERSION, BUILD_TIME } from 'virtual:env-info';

console.log('Environment:', NODE_ENV);
console.log('Version:', VERSION);
console.log('Build Time:', BUILD_TIME);

五、实战案例二:处理自定义文件

5.1 处理 .yaml 文件

// plugins/vite-plugin-yaml.js
import yaml from 'js-yaml';

export default function yamlPlugin() {
  return {
    name: 'vite-plugin-yaml',
    
    transform(code, id) {
      if (id.endsWith('.yaml') || id.endsWith('.yml')) {
        try {
          const data = yaml.load(code);
          return {
            code: `export default ${JSON.stringify(data)};`
          };
        } catch (e) {
          this.error(e.message);
        }
      }
    }
  };
}

5.2 使用 YAML 文件

# config.yaml
app:
  name: My App
  version: 1.0.0
database:
  host: localhost
  port: 5432
import config from './config.yaml';

console.log(config.app.name);
console.log(config.database.port);

六、实战案例三:热更新处理

6.1 自定义 HMR

// plugins/vite-plugin-hmr.js
export default function hmrPlugin() {
  return {
    name: 'vite-plugin-hmr',
    
    handleHotUpdate({ file, server, modules }) {
      console.log('File changed:', file);
      
      // 自定义更新逻辑
      if (file.endsWith('.special')) {
        server.ws.send({
          type: 'custom',
          event: 'special-update',
          data: { file }
        });
        return []; // 不触发默认更新
      }
      
      return modules; // 默认行为
    }
  };
}

6.2 客户端接收 HMR

// src/hmr-client.js
if (import.meta.hot) {
  import.meta.hot.on('special-update', (data) => {
    console.log('Special update:', data);
    // 自定义更新处理
  });
}

七、插件开发技巧

7.1 区分开发与生产环境

export default function envPlugin() {
  let isDev;

  return {
    name: 'env-plugin',
    
    configResolved(config) {
      isDev = config.command === 'serve';
    },
    
    transform(code, id) {
      if (isDev) {
        // 开发环境逻辑
        return code + '\nconsole.log("Dev only");';
      } else {
        // 生产环境逻辑
        return code;
      }
    }
  };
}

7.2 插件排序

// vite.config.js
export default defineConfig({
  plugins: [
    pluginA(), // 先执行
    pluginB(), // 后执行
  ]
});

// 使用 enforce
export default function plugin() {
  return {
    name: 'my-plugin',
    enforce: 'pre', // 'pre' | 'post' | undefined
  };
}

八、调试与测试

8.1 调试 Plugin

// 使用 debug
import createDebug from 'debug';
const debug = createDebug('vite-plugin-example');

export default function debugPlugin() {
  return {
    name: 'debug-plugin',
    
    transform(code, id) {
      debug('Transforming:', id);
      return code;
    }
  };
}

8.2 测试 Plugin

// test/plugin.test.js
import { createServer } from 'vite';
import myPlugin from '../index.js';

test('plugin works', async () => {
  const server = await createServer({
    plugins: [myPlugin()]
  });
  
  // 测试逻辑
  
  await server.close();
});

九、最佳实践

  1. 命名规范:使用 vite-plugin- 前缀
  2. TypeScript:使用 TS 开发,提供类型
  3. 文档:完善的 README
  4. 测试:提供单元测试
  5. 兼容性:考虑不同 Vite 版本

到此这篇关于Vite Plugin 开发完全指南的文章就介绍到这了,更多相关Vite Plugin 开发内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • ElementUI 详细分析DatePicker 日期选择器实战

    ElementUI 详细分析DatePicker 日期选择器实战

    这篇文章主要介绍了ElementUI详细分析DatePicker 日期选择器实战教程,本文通过实例代码图文介绍给大家讲解的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • vue用复选框实现组件且支持单选和多选操作方式

    vue用复选框实现组件且支持单选和多选操作方式

    这篇文章主要介绍了vue用复选框实现组件且支持单选和多选操作方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • vue如何使用js对图片进行点击标注圆点并记录它的坐标

    vue如何使用js对图片进行点击标注圆点并记录它的坐标

    这篇文章主要介绍了vue如何使用js对图片进行点击标注圆点并记录它的坐标,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • vue改变循环遍历后的数据实例

    vue改变循环遍历后的数据实例

    今天小编就为大家分享一篇vue改变循环遍历后的数据实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • Vue导出Excel文件的四种实现方式

    Vue导出Excel文件的四种实现方式

    文章介绍了四种在Vue.js中导出Excel文件的方法,包括前端使用xlsx库、exceljs,使用现成组件vue-json-excel,以及后端生成,每种方法都有其适用场景和优缺点,推荐根据具体需求选择合适的方法,需要的朋友可以参考下
    2025-12-12
  • 一文详解Vue中内存泄漏的场景与预防技巧

    一文详解Vue中内存泄漏的场景与预防技巧

    即便是功能强大的 Vue.js 也无法完全避免内存泄漏的问题,内存泄漏不仅会影响应用的性能,还可能导致浏览器崩溃,下面我们来看看Vue 中常见的内存泄漏场景以及如何避免这些问题吧
    2024-12-12
  • Vue3插槽Slot实现原理详解

    Vue3插槽Slot实现原理详解

    这篇文章主要为大家介绍了Vue3插槽Slot实现原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • VUE-PDF实现pdf在线预览问题

    VUE-PDF实现pdf在线预览问题

    这篇文章主要介绍了VUE-PDF实现pdf在线预览问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • 完美解决element-ui的el-input设置number类型后的相关问题

    完美解决element-ui的el-input设置number类型后的相关问题

    这篇文章主要介绍了完美解决element-ui的el-input设置number类型后的相关问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • Vue使用Proxy代理后仍无法生效的解决

    Vue使用Proxy代理后仍无法生效的解决

    这篇文章主要介绍了Vue使用Proxy代理后仍无法生效的解决,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11

最新评论