Vite 插件编写之虚拟模块

Vite 相对于 Webpack 上手难度小,简单的配置,开箱即用。虽然目前生态不如 Webpack,不过生态也逐渐的丰富起来。
经过了一些 Vite 插件编写实践,今天来说说虚拟模块(Virtual Modules ),也顺便介绍下 vite-plugin-project-info 插件。
虚拟模块的概念 【Vite 插件编写之虚拟模块】虚拟模块是 Vite 沿用 Rollup 的虚拟模块,虚拟模块类似 alias 别名,但是模块的内容并非直接从磁盘中读取,而是编译时生成。

虚拟模块是一种很实用的模式,使你可以对使用 ESM 语法的源文件传入一些编译时信息。
虚拟模块实现例子 首先你可能需要先了解插件编写的 API。
这里直接搬运官网的例子:
export default function myPlugin() { const virtualModuleId = 'virtual:my-module' const resolvedVirtualModuleId = '\0' + virtualModuleIdreturn { name: 'my-plugin', resolveId(id) { if (id === virtualModuleId) { return resolvedVirtualModuleId } }, load(id) { if (id === resolvedVirtualModuleId) { return `export const msg = "from virtual module"` } } } }

然后代码中引入这些模块:
import { msg } from 'virtual:my-module'console.log(msg)

实践分析: vite-plugin-project-info Vite 插件编写之虚拟模块
文章图片

vite-plugin-project-info 是 Vite 项目信息插件,使用后会在 Conole 面板输出版本、构建时间等信息。
配合虚拟模块实现插件
  1. resolveId 钩子函数:真实虚拟模块 ID 转换为内部虚拟模块 ID。
  2. load 钩子函数:匹配内部虚拟模块 ID,并返回编译时的代码,最终实现了 virtual:project-info 模块。
  3. transform 钩子函数:实现自动 import 功能
    截止第二步其实已经实现了虚拟模块的功能,但是我们
export default function projectInfoPlugin(opts: ProjectInfoPluginOptions = {}): PluginOption { const { entry = path.resolve('src/main'), locale } = opts; const lastEntry = entry.split('.')[0]; const virtualModuleId = 'virtual:project-info'; const resolvedVirtualModuleId = '\0' + virtualModuleId; return { name: 'vite:project-info', enforce: 'pre', resolveId(id) { if (id === virtualModuleId) { return resolvedVirtualModuleId; } }, load(id) { if (id === resolvedVirtualModuleId) { return createCode({ locale, }); } }, transform(code, id) { if (id.includes(path.resolve(lastEntry).replace(/\\/g, '/'))) { return { code: `import '${virtualModuleId}'; \n${code}`, map: this.getCombinedSourcemap(), }; } }, }; }

功能使用
支持直接在浏览器 Console 中输出相关项目信息,同时支持如下代码使用:
import projectInfo from 'virtual:project-info'; console.log(projectInfo.version); // 版本信息 console.log(projectInfo.buildTime); // 构建时间 console.log(projectInfo.name); // 项目名称 console.log(projectInfo.description); // 项目描述 console.log(projectInfo.repository); // 仓库链接 console.log(projectInfo.author); // 项目负责人或者作者

    推荐阅读