Vite 插件开发从入门到发布
Sarah Wong | 2026-09-01T08:56:55 | JavaScript, Frontend
详解 Vite 插件的 Hook 生命周期、虚拟模块、HMR 集成、Rollup 兼容性,并手把手实现一个 Markdown 转组件插件。
# Vite 插件开发从入门到发布 ## Vite 插件本质 Vite 插件兼容 Rollup 插件接口,同时扩展了 Vite 特有的 Hook。一个最小插件的结构: ```typescript // vite-plugin-example.ts import type { Plugin } from 'vite' export default function myPlugin(options = {}): Plugin { return { name: 'vite-plugin-example', // Vite 特有 Hook configResolved(config) { console.log('Resolved config:', config.root) }, // Rollup 兼容 Hook transform(code, id) { if (id.endsWith('.custom')) { return { code: transformCustomFile(code), map: null } } } } } ``` ## 实战:Markdown 转 Vue 组件 ```typescript import MarkdownIt from 'markdown-it' import type { Plugin } from 'vite' export default function vitePluginMd(): Plugin { const md = new MarkdownIt({ html: true, linkify: true }) return { name: 'vite-plugin-md', enforce: 'pre', transform(raw, id) { if (!id.endsWith('.md')) return const html = md.render(raw) const component = [ 'import { defineComponent, h } from "vue"', 'export default defineComponent({', ' name: "MdContent",', ' setup() {', ' return () => h("div", {', ' class: "markdown-body",', ' innerHTML: ' + JSON.stringify(html), ' })', ' }', '})' ].join('\n') return { code: component, map: null } } } } ``` ## 虚拟模块 ```typescript export default function virtualModule(): Plugin { const virtualId = 'virtual:app-config' const resolvedId = '\0' + virtualId return { name: 'vite-plugin-virtual', resolveId(id) { if (id === virtualId) return resolvedId }, load(id) { if (id === resolvedId) { return 'export const buildTime = ' + JSON.stringify(new Date().toISOString()) } } } } ``` ## HMR 支持 ```typescript handleHotUpdate({ file, server }) { if (file.endsWith('.md')) { const mod = server.moduleGraph.getModuleById(file) if (mod) { server.moduleGraph.invalidateModule(mod) server.ws.send({ type: 'full-reload' }) } } } ``` 开发完成后发布到 npm 即可,建议包名以 `vite-plugin-` 前缀命名以便社区发现。