@star_work/vite-plugin-virtual-mpa
v2.0.3
Published
Enhanced fork of vite-plugin-virtual-mpa with file scan mode, virtual module CORS fix, and improved documentation.
Maintainers
Readme
@star_work/vite-plugin-virtual-mpa ⚡
增强版 fork,基于 vite-plugin-virtual-mpa 开发,包含额外功能和改进。
开箱即用的 Vite MPA插件 📦,支持HTML模板引擎和虚拟文件功能,能够使用一份模板生成多个文件。
原项目: vite-plugin-virtual-mpa by QinXuYang
English | 中文
✨ 增强功能(相比原版)
本 fork 版本包含以下增强:
- 🆕 文件扫描模式:自动从目录中的 Vue/React 文件生成页面
- 扫描子目录中的
.vue、.tsx、.jsx文件 - 每个文件自动成为独立的 HTML 页面
- 只扫描直接子目录(可配置深度)
- 扫描子目录中的
- 🎯 页面配置扫描功能:自动提取页面中的
definePage配置- 扫描页面目录,提取
definePage({ ... })配置 - 生成
virtual:page-configs虚拟模块供运行时使用 - 自动注入
definePage函数,避免运行时错误 - 支持热更新,文件变化时自动重新扫描
- 扫描页面目录,提取
- 🐛 修复虚拟模块跨域问题:自动使用
/@id/前缀处理虚拟模块- 不再出现加载虚拟入口文件时的 CORS 错误
- 浏览器兼容的虚拟模块路径
- 🔧 增强的入口模板:文件扫描模式下支持
componentPath变量 - 📝 完善的文档:完整的使用示例和指南
主要功能
- 💡 EJS 模板渲染(支持 HTML 和 Entry 模板)
- 💡 完备的 TypeScript 类型提示支持,是一款小而美的插件
- 🛠️ 自定义模板HTML文件的输出路径,使用一份模板生成多份文件
- 🛠️ 文件扫描模式:从组件文件自动生成页面
- 🛠️ 虚拟入口模板:使用一个 entry 模板文件生成多个虚拟入口文件,减少重复代码
- 🎯 页面配置扫描:自动提取
definePage配置,生成虚拟模块 - 🛠️ 支持 MPA 多页面应用,为开发和预览服务器提供 History Fallback 支持
- 🐛 修复虚拟模块跨域问题
安装
pnpm add -D @star_work/vite-plugin-virtual-mpa
# 或
npm install -D @star_work/vite-plugin-virtual-mpa使用方式
// vite.config.ts
import { createMpaPlugin, createPages } from '@star_work/vite-plugin-virtual-mpa'
// @see https://vitejs.dev/config/
export default defineConfig({
plugins: [
createMpaPlugin({
pages: [
// 你可以直接在这里书写页面配置,也可以单独使用 `createPages` 函数并将结果传递到这里。
]
}),
],
})
/**
* 该函数仅仅是将参数转换为一个 pages 数组。
* 它帮助你在插件之外创建页面配置,主要是为了能够拥有类型提示。
* 同时在别处统一管理配置的方式可能也能帮助你简化 vite 的配置文件。
*/
const pages = createPages([
// 你可以传递一个 page 对象或一个 pages 数组。
])
// @see https://vitejs.dev/config/
export default defineConfig({
plugins: [
createMpaPlugin({
pages,
}),
],
})Options
type FilterPattern = string | RegExp | (string | RegExp)[]
type RewriteRule = false | Rewrite[]
interface WatchHandler {
(ctx: {
server: ViteDevServer,
file: string,
type: Event
/**
* 可以调用这个方法更新页面配置
* @params pages MPA 页面核心配置,这将会替换默认的 `pages`
*/
reloadPages: (pages: Page[]) => void
}): void
}
interface MpaOptions {
/**
* 是否在控制台打印log
* @default true
*/
verbose?: boolean,
/**
* 默认模板文件
* @default index.html
*/
template?: `${string}.html`,
/**
* 默认入口模板文件,用于生成虚拟入口文件。
* 与 `template` 类似,允许使用一个模板文件生成多个入口文件。
* 如果页面配置中指定了 `entryTemplate`,将优先使用页面级别的配置。
* @see 关于虚拟入口文件章节
*/
entryTemplate?: string,
/**
* 为开发服务器配置 fallback rewrite rules,只会处理 accept=text/html 的文件请求。
* @see https://github.com/bripkens/connect-history-api-fallback
*/
rewrites?: RewriteRule,
/**
* 为预览服务器配置重定向规则,配置方式同 rewrites。
* @see https://github.com/bripkens/connect-history-api-fallback
*/
previewRewrites?: RewriteRule,
/**
* 处理模版 HTML 文件,继承自 `transformIndexHtml`。
* @see https://vitejs.dev/guide/api-plugin#transformindexhtml
*/
transformHtml?: (
html: string,
ctx: IndexHtmlTransformContext & { page: Page },
) => IndexHtmlTransformResult;
/**
* 用于扫描相似的目录结构,自动生成 pages 配置。
* 扫描到的配置会追加到 `pages` 中,具有相同 name 的 page 将被忽略
*/
scanOptions?: {
/**
* 要扫描的目录,子目录名称将作为唯一的 page name。
*/
scanDirs: string | string[];
/**
* 扫描模式:'directory' 扫描子目录(默认),'file' 扫描匹配 filePattern 的文件。
* 当 scanMode 为 'file' 时,只扫描 scanDirs 的直接子目录下的文件。
* 更深层的文件和 scanDirs 根目录下的文件将被忽略。
* @default 'directory'
*/
scanMode?: 'directory' | 'file';
/**
* 当 scanMode 为 'file' 时匹配的文件模式(如 '*.vue', '*.tsx')。
* 支持 glob 模式。只有匹配此模式的文件才会被扫描。
* 文件只在 scanDirs 的直接子目录中扫描,不会扫描更深层。
* @default '*.vue'
*/
filePattern?: string;
/**
* 相对于扫描目录的入口文件路径
* 当 scanMode 为 'file' 时,此选项将被忽略,应使用 entryTemplate 代替。
*/
entryFile?: string;
/**
* 文件扫描模式的入口模板文件。
* 当 scanMode 为 'file' 时,此模板将用于生成虚拟入口文件。
* 模板可以使用 EJS 语法,支持变量:componentPath(文件路径)、pageName 和 data 字段。
*/
entryTemplate?: string;
/**
* 自定义虚拟文件的名称(输出文件名)
* @param name 子目录名称(目录模式)或相对于 scanDirs 的文件路径(文件模式)
* @param filePath 完整文件路径(仅文件模式)
*/
filename?: (name: string, filePath?: string) => string;
/**
* 为每个扫描到的页面注入的数据。
* 可以是函数,接收文件/目录信息并返回数据对象。
*/
data?: Record<string, any> | ((info: { name: string; path: string; dir: string }) => Record<string, any>);
};
/**
* 当项目目录下有一些文件触发相应的事件如添加、删除、修改时,你可能想要重新加载 `pages` 配置 或 重启 ViteDevServer。
* 你可以通过设置 `watchOptions` 来实现这一目的。
*/
watchOptions?: WatchHandler | {
/**
* 指定需要**包含**的文件,基于 `Rollup.createFilter` 过滤
* @see https://vitejs.dev/guide/api-plugin.html#filtering-include-exclude-pattern
*/
include?: Exclude<FilterPattern, null>,
/**
* 指定需要**排除**的文件,基于 `Rollup.createFilter` 过滤
* @see https://vitejs.dev/guide/api-plugin.html#filtering-include-exclude-pattern
*/
excluded?: Exclude<FilterPattern, null>,
/**
* 想要监听的文件事件
* @default ['add', 'unlink', 'change', 'unlinkDir', 'addDir']
*/
events?: Event[],
/**
* 定义的文件事件触发后,执行自定义逻辑
*/
handler: WatchHandler
},
pages: Array<{
/**
* 必填。该名称是一个不包含'/'的普通字符串,它用于生成默认的重定向规则。
* 如果你想自定义生成文件的路径,请使用filename选项,而不是name选项。
*/
name: string;
/**
* 相对于`build.outDir`的路径,应该以html结尾
* @default `${name}.html`
*/
filename?: `${string}.html`;
/**
* 更高优先级的模板文件,将会覆盖默认模板
*/
template?: string;
/**
* 自动注入入口文件,如果设置了entry,需要移除模板文件中的entry。
* 入口文件路径必须以 `'/'` 开头(相对于项目根目录),
* 或者使用 Vite 虚拟模块格式(以 `'virtual:'` 或 `'\0'` 开头)。
* 如果同时设置了 `entryTemplate`,此选项将被忽略。
*/
entry?: string;
/**
* 入口模板文件,用于生成虚拟入口文件。
* 与 `template` 类似,允许使用一个模板文件生成多个入口文件。
* 模板文件支持 EJS 语法,可以注入页面数据(`data`)和页面名称(`pageName`)。
* 如果页面配置中未指定,将使用全局的 `entryTemplate` 配置。
*
* **注意**:不能同时使用 `entry` 和 `entryTemplate`。
*
* @example
* ```js
* // entry-template.js
* import App from '/src/pages/<%= pageName %>/App.vue';
* console.log('Page:', '<%= pageName %>');
* createApp(App).mount('#root');
* ```
*/
entryTemplate?: string;
/**
* 注入到模板文件的数据
*/
data?: Record<string, any>,
}>,
/**
* 是否使用 html-minify-terser 压缩 html 文件
* @default false
* @see https://github.com/terser/html-minifier-terser
*/
htmlMinify?: Options | boolean,
/**
* 是否启用页面配置扫描功能。
* 如果为 true,将自动扫描页面目录并生成 virtual:page-configs 虚拟模块。
* 如果为对象,可以自定义配置选项。
* @default false
*/
pageConfigs?:
| boolean
| {
/**
* 要扫描的页面目录
* @default 'src/pages'
*/
pagesDir?: string | string[];
/**
* 文件匹配模式
* @default '*.vue'
*/
filePattern?: string;
/**
* 虚拟模块 ID
* @default 'virtual:page-configs'
*/
virtualModuleId?: string;
};
}Examples
注意:CodeSandbox 示例链接到原项目仓库。要体验增强功能(文件扫描模式),请查看下面的示例部分。
点击链接 codesandbox 快速体验原项目功能!
基础示例(使用 entry)
// vite.config.ts
import { normalizePath } from "vite";
import { createMpaPlugin } from "vite-plugin-virtual-mpa"
const base = "/sites/"
// @see https://vitejs.dev/config/
export default defineConfig({
base,
plugins: [
createMpaPlugin({
htmlMinify: false,
pages: [
{
name: "apple",
/**
* 文件名是可选的,默认将会是`${name}.html`,这个路径是相对于`build.outDir`
*/
filename: "fruits/apple.html", // 将会在编译时输出到sites/fruits/apple.html
entry: "/src/fruits/apple/index.js",
data: {
title: "This is Apple page"
}
},
{
name: "banana",
filename: "fruits/banana.html",
entry: "/src/fruits/banana/index.js",
data: {
title: "This is Banana page"
}
},
{
name: "strawberries",
filename: "fruits/strawberries.html",
entry: "/src/fruits/strawberries/index.js",
data: {
title: "This is Strawberries page"
}
}
],
/**
* 以下示例的 scanOptions 配置可以替换上面的 pages 配置,除了 data 的注入。
*/
scanOptions: {
scanDirs: 'src/fruits',
entryFile: 'index.js',
filename: name => `fruits/${name}.html`,
template: '../../template.html',
},
/**
* 使用入口模板生成虚拟入口文件(可选)
* 这样可以避免为每个页面创建重复的入口文件
*/
// entryTemplate: 'src/entry-template.js',
/**
* 通过该选项来配置 history fallback rewrite rules
* 如果你像上面这样配置页面的话,那下面的这份配置将会自动生成。
* 否则你需要自己编写重定向规则。
*/
rewrites: [
{
from: new RegExp(normalizePath(`/${base}/(apple|banana|strawberries)`)),
to: (ctx) => normalizePath(`/fruits/${ctx.match[1]}.html`),
}
],
/**
* 配置预览服务器的重定向规则,配置方式同 rewrites
*/
previewRewrites: [
// 如果产物目录没有 index.html,你需要手动配置规则,以便服务器能正确找到入口文件。
{ from: /.*/, to: '/home.html' },
],
/** 自定义处理模板内容 */
transformHtml(html, ctx) {
return {
html,
tags: [
{
tag: 'div',
injectTo: 'body-prepend',
children: `[Auto Injected] Page name: ${ctx.page.name}`,
},
],
};
},
}),
],
})文件扫描模式示例
当你希望为 pages 目录下的每个 Vue 文件生成独立的 HTML 页面时,可以使用文件扫描模式:
1. 创建入口模板文件
// src/entry-template-vue.js
import { createApp } from 'vue';
// 根据 componentPath 动态导入 Vue 组件
import Component from '<%= componentPath %>';
// 页面特定的数据可以在这里使用
console.log('组件路径:', '<%= componentPath %>');
console.log('页面标题:', '<%= title %>');
// 挂载 Vue 应用
createApp(Component).mount('#root');2. 配置插件
// vite.config.ts
import { createMpaPlugin } from "vite-plugin-virtual-mpa"
export default defineConfig({
plugins: [
createMpaPlugin({
template: 'src/template.html',
scanOptions: {
scanDirs: 'src/pages',
scanMode: 'file', // 扫描文件而不是目录
filePattern: '*.vue', // 匹配 .vue 文件
entryTemplate: 'src/entry-template-vue.js', // 用于生成入口文件的模板
filename: (name) => `${name}.html`, // 输出:apple/About.html, apple/App.html 等
data: ({ name, dir }) => ({
title: `${dir} - ${name.split('/').pop()}`,
}),
},
}),
],
})扫描规则:
- 只扫描
scanDirs的直接子目录下的文件 - 忽略更深层嵌套目录中的文件
- 忽略
scanDirs根目录下的文件 - 每个匹配的文件都会成为一个独立的 HTML 页面
目录结构示例:
src/pages/
├── apple/
│ ├── About.vue ✅ 扫描 → apple/About.html
│ ├── App.vue ✅ 扫描 → apple/App.html
│ └── deep/
│ └── Deep.vue ❌ 忽略(更深层)
├── page2/
│ └── App.vue ✅ 扫描 → page2/App.html
└── Root.vue ❌ 忽略(不在子目录下)entryTemplate 中可用的变量:
<%= componentPath %>- Vue 组件文件的完整路径(自动注入)<%= pageName %>- 页面名称(如 "apple/About")<%= title %>- 来自data.title<%= customVar %>-data配置中的任何自定义变量<%= VITE_XXX %>- 以VITE_开头的环境变量
使用入口模板(entryTemplate)示例
使用 entryTemplate 可以避免为每个页面创建重复的入口文件:
1. 创建入口模板文件
// src/entry-template.js
import { createApp } from 'vue';
// 使用 EJS 语法动态导入对应页面的组件
import App from '/src/pages/<%= pageName %>/App.vue';
// 页面数据会自动注入
console.log('🚀 Page name:', '<%= pageName %>');
console.log('📄 Page title:', '<%= title %>');
// 如果有自定义数据,也可以使用
// console.log('Custom data:', '<%= customData %>');
createApp(App).mount('#root');2. 在配置中使用
// vite.config.ts
import { createMpaPlugin } from "vite-plugin-virtual-mpa"
export default defineConfig({
plugins: [
createMpaPlugin({
template: 'src/template.html',
// 全局入口模板(所有页面共享)
entryTemplate: 'src/entry-template.js',
pages: [
{
name: "apple",
filename: "fruits/apple.html",
// 使用全局 entryTemplate,无需单独指定
data: {
title: "This is Apple page",
customData: "Apple specific data"
}
},
{
name: "banana",
filename: "fruits/banana.html",
// 也可以为特定页面指定不同的入口模板
// entryTemplate: 'src/banana-entry-template.js',
data: {
title: "This is Banana page"
}
},
{
name: "strawberries",
filename: "fruits/strawberries.html",
data: {
title: "This is Strawberries page"
}
}
],
// ... 其他配置
}),
],
})优势对比:
- 传统方式:需要为每个页面创建
index.js文件,代码重复 - 使用 entryTemplate:只需一个模板文件,通过 EJS 动态生成,减少重复代码
注意事项:
- Entry 模板中的 import 路径建议使用绝对路径(以
/src/开头) - 不能同时使用
entry和entryTemplate - 页面级别的
entryTemplate会覆盖全局配置
本 Fork 版本的新特性
这是基于原版 vite-plugin-virtual-mpa 的增强版本,包含以下改进:
🆕 文件扫描模式(v1.13.0+)
自动扫描并生成页面,无需手动配置每个页面:
- 自动发现:扫描子目录中的
.vue、.tsx、.jsx文件 - 智能过滤:只扫描直接子目录(可配置)
- 基于模板:使用入口模板生成虚拟入口文件
- 灵活配置:支持自定义文件模式和数据注入
🐛 虚拟模块跨域修复(v1.13.1+)
修复了浏览器加载虚拟入口模块时的 CORS 问题:
- 自动路径转换:使用
/@id/前缀确保浏览器兼容性 - 无需手动操作:插件自动处理所有路径转换
- 开箱即用:无需额外配置
🎯 页面配置扫描功能(v2.0.0+)
自动扫描并提取页面中的 definePage 配置,生成虚拟模块供运行时使用:
- 自动扫描:递归扫描页面目录,提取
definePage({ ... })配置 - 虚拟模块:生成
virtual:page-configs虚拟模块,提供配置数据 - 运行时支持:自动注入
definePage函数,避免运行时错误 - 热更新:文件变化时自动重新扫描并更新配置
- 类型安全:完整的 TypeScript 类型支持
📚 完善的文档
包含所有功能的完整示例和使用指南,包括文件扫描模式的使用方法。
关于原项目
本插件基于 vite-plugin-virtual-mpa(作者:QinXuYang)开发。原项目旨在解决使用 Vite 构建多页面应用(MPA)时的以下需求:
- 支持模板引擎(如 EJS),能够使用一个模板生成多份文件,且能自定义构建时生成文件的路径
- 自动配置
rollupOptions.input,并提供能力配置开发服务器的代理(主要是 history fallback API)
关于原项目的设计理念和与其他插件的对比,请参考原项目仓库。
默认重定向规则
正如上面提到的👆🏻,如果你的配置遵循约定,插件将会自动生成一份重定向规则,这份配置会同时应用到开发和预览服务器,如下:
{
from: new RegExp(normalizePath(`/${base}/(${Object.keys(inputMap).join('|')})`)),
to: ctx => normalizePath(`/${base}/${inputMap[ctx.match[1]]}`),
}其中, inputMap 是一个name到对应虚拟文件的映射,结构如下:
{
apple: 'fruits/apple.html',
banana: 'fruits/banana.html',
strawberries: 'fruits/strawberries.html',
}请求Url/sites/apple/xxx将会被默认重定向规则处理并重定向到对应的url,也就是/fruits/apple.html(name 'apple' 对应 'fruits/apple.html', 其他同理),重定向后的路径将会基于viteConfig.base(这里是'/sites/')去寻找目标文件,所以最终的Url会变成/sites/fruits/apple.html.
关于虚拟入口文件
通常在开发时,我们的文件都是写在本地的,我们通过DevServer的代理能够通过url访问到本地对应的文件。虚拟文件也是如此,只不过对应的文件没有写到文件系统中,而是保存在内存中而已。
该插件通过模板系统生成了对应的虚拟文件,让你可以在开发时通过代理访问到内存中的虚拟文件,并在构建时生成到对应的目录下。
你完全可以认为这些虚拟文件是真实存在的,这将有助于你在脑海中构建关于虚拟文件的直觉,以便能够正确地编写代理配置。
虚拟模块路径格式
从 v1.13.1 开始,插件自动使用 /@id/ 前缀来生成虚拟入口模块的路径,确保浏览器可以正确加载虚拟模块,避免 CORS 错误。
生成的 HTML 格式:
<!-- ✅ 正确的格式(v1.13.1+) -->
<script type="module" src="/@id/virtual:entry:pageName"></script>为什么需要 /@id/ 前缀?
- 浏览器无法直接识别
virtual:entry:xxx这种裸模块标识符 - Vite 开发服务器通过
/@id/前缀来识别和处理虚拟模块 - 这样可以确保虚拟模块在浏览器中正确加载,避免 CORS 错误
插件会自动处理路径转换,你无需手动添加 /@id/ 前缀。
虚拟入口模板(entryTemplate)
从 v1.12.2 开始,插件支持虚拟入口模板功能,允许你像使用 HTML 模板一样,使用一个 entry 模板文件生成多个虚拟入口文件。
使用场景
当你需要为多个页面生成相似的入口文件时,可以使用 entryTemplate 来避免重复代码:
- 传统方式:每个页面都需要一个独立的
index.js文件 - 使用 entryTemplate:只需要一个模板文件,通过 EJS 语法动态生成每个页面的入口文件
基本用法
1. 创建入口模板文件
// src/entry-template.js
import { createApp } from 'vue';
// 使用 EJS 语法注入页面名称
import App from '/src/pages/<%= pageName %>/App.vue';
// 页面数据会自动注入
console.log('Page name:', '<%= pageName %>');
console.log('Page title:', '<%= title %>');
createApp(App).mount('#root');2. 在配置中使用
// vite.config.ts
export default defineConfig({
plugins: [
createMpaPlugin({
template: 'src/template.html',
// 全局入口模板(可选)
entryTemplate: 'src/entry-template.js',
pages: [
{
name: 'apple',
entryTemplate: 'src/entry-template.js', // 页面级别配置(优先级更高)
data: {
title: 'This is Apple page',
// 自定义数据也会注入到模板中
}
},
{
name: 'banana',
// 使用全局 entryTemplate
data: {
title: 'This is Banana page',
}
}
]
})
]
})可用变量
在 entryTemplate 中,你可以使用以下变量:
<%= pageName %>- 页面名称(自动注入)<%= componentPath %>- 组件文件路径(仅在文件扫描模式下可用,自动注入)<%= title %>- 来自data.title的数据<%= customVar %>- 来自data配置的任何自定义变量<%= VITE_XXX %>- 以VITE_开头的环境变量(自动注入)
注意事项
路径问题:在 entry 模板中使用 import 时,建议使用绝对路径(以
/src/开头),因为虚拟入口文件没有实际的文件系统路径。不能同时使用:不能同时设置
entry和entryTemplate,否则会报错。优先级:页面级别的
entryTemplate配置会覆盖全局配置。热更新:修改 entry 模板文件会自动触发页面重载。
对比示例
传统方式(使用 entry):
pages: [
{
name: 'apple',
entry: '/src/pages/apple/index.js', // 需要为每个页面创建文件
},
{
name: 'banana',
entry: '/src/pages/banana/index.js', // 重复的代码结构
}
]使用 entryTemplate:
pages: [
{
name: 'apple',
entryTemplate: 'src/entry-template.js', // 共享模板
},
{
name: 'banana',
entryTemplate: 'src/entry-template.js', // 共享模板
}
]使用 entryTemplate 可以大大减少重复代码,特别是在页面结构相似的情况下。
页面配置扫描示例
页面配置扫描功能允许你在 Vue 文件中使用 definePage 定义页面配置,然后通过虚拟模块在运行时访问这些配置。
1. 在 Vue 文件中定义页面配置
<!-- src/pages/apple/About.vue -->
<script setup>
// 使用 definePage 定义页面配置
definePage({
name: 'About',
title: '关于我们',
platform: ['web', 'mobile'],
locale: 'zh-CN',
meta: {
description: '这是关于页面',
},
});
</script>
<template>
<div>This is Apple About</div>
</template>2. 在 vite.config.ts 中启用页面配置扫描
// vite.config.ts
import { createMpaPlugin } from '@star_work/vite-plugin-virtual-mpa'
export default defineConfig({
plugins: [
createMpaPlugin({
template: 'src/template.html',
scanOptions: {
scanDirs: 'src/pages',
scanMode: 'file',
filePattern: '*.vue',
entryTemplate: 'src/entry-template-vue.js',
},
// 启用页面配置扫描
pageConfigs: true, // 或 { pagesDir: 'src/pages', filePattern: '*.vue' }
}),
],
})3. 在代码中使用页面配置
// 导入页面配置
import { pageConfigs, getPageConfig } from 'virtual:page-configs';
// 获取所有页面配置
console.log('All page configs:', pageConfigs);
// 输出: [{ path: 'apple/About', name: 'About', title: '关于我们', ... }, ...]
// 根据路径获取特定页面配置
const aboutConfig = getPageConfig('apple/About');
console.log('About page config:', aboutConfig);
// 输出: { path: 'apple/About', name: 'About', title: '关于我们', ... }
// 业务逻辑:根据平台筛选配置(自己实现)
function getPageConfigsByPlatform(platform) {
return pageConfigs.filter((config) => {
if (!config.platform) return false;
if (typeof config.platform === 'string') {
return config.platform === platform;
}
return config.platform.includes(platform);
});
}
const webConfigs = getPageConfigsByPlatform('web');
console.log('Web platform configs:', webConfigs);虚拟模块提供的功能:
pageConfigs- 所有页面配置数组(原始数据)getPageConfig(path)- 根据路径获取配置,如getPageConfig('apple/About')
注意事项:
definePage函数会在编译时自动注入,无需手动导入- 如果页面没有
definePage,插件会创建默认配置(使用页面路径作为名称) - 业务逻辑的筛选函数(如按平台、语言筛选)需要自己实现
- 文件变化时会自动重新扫描配置并更新虚拟模块
关于 EJS 模板引擎
插件使用 ejs 模板引擎进行数据注入,支持两种模板类型:
HTML 模板(template)
用于生成 HTML 文件,除页面配置中提供的 data 外,插件默认会将以 'VITE_' 开头的环境变量注入所有的页面配置中。
入口模板(entryTemplate)
用于生成虚拟入口文件(如 index.js),支持以下变量:
<%= pageName %>- 页面名称(自动注入,无需在data中配置)<%= title %>- 来自data.title的数据<%= customVar %>- 来自data配置的任何自定义变量<%= VITE_XXX %>- 以VITE_开头的环境变量(自动注入)
示例:
// entry-template.js
import App from '/src/pages/<%= pageName %>/App.vue';
console.log('Page:', '<%= pageName %>');
console.log('Title:', '<%= title %>');
console.log('Custom:', '<%= customData %>');更多关于环境变量的信息可以查看官网 —— envprefix。
