@simposons/vite-plugin-mpa
v1.0.3
Published
A Vite plugin for Multi-Page Applications (MPA) with shared entry and auto-scanning
Downloads
589
Maintainers
Readme
vite-plugin-mpa
一个 Vite 插件,用于多页面应用(MPA)构建,支持共享入口和自动扫描。
特性
- 🚀 自动扫描 – 自动扫描
src/pages目录下的.vue文件,生成对应的 HTML 入口。 - 🔗 共享入口 – 所有页面共享同一个 JavaScript 入口文件(如
src/main.ts)。 - 📄 基于模板生成 HTML – 使用一个 HTML 模板(如
index.html)自动生成所有页面,支持动态标题。 - 🎯 TypeScript 支持 – 包含完整的类型定义。
- ⚡ 灵活切换 – 通过
enable选项或--mpa命令行标志控制是否启用 MPA。 - 🧩 高度可定制 – 支持手动指定页面列表、自定义输出目录、自定义标题等。
- 📝 组件内定义标题 – 支持在
.vue组件中使用defineOptions({ title: '页面标题' })自定义页面标题。
安装
npm install -D @simposons/vite-plugin-mpa使用
基本配置
在 vite.config.ts 中:
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import mpa from '@simposons/vite-plugin-mpa'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [
vue(),
mpa({
enable: env.VITE_MPA === 'true', // 通过环境变量控制
pagesDir: 'src/pages', // 页面组件目录
template: 'index.html', // HTML 模板文件
entry: 'src/main.ts', // 共享入口文件
verbose: true,
}),
],
}
})目录结构
project/
├── index.html # 模板 HTML(包含 <!-- PAGE_TITLE -->)
├── src/
│ ├── main.ts # 共享入口
│ ├── pages/
│ │ ├── index/
│ │ │ └── index.vue # → 生成 index.html
│ │ ├── about/
│ │ │ └── index.vue # → 生成 about.html
│ │ └── user/
│ │ ├── profile.vue # → 生成 user-profile.html
│ │ └── settings.vue # → 生成 user-settings.html
│ └── ...
└── vite.config.ts模板 HTML(index.html)
在模板中放置 <!-- PAGE_TITLE --> 占位符,插件会自动替换为页面标题。如果模板中没有该占位符,插件会自动将 <title> 标签内容替换为占位符。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><!-- PAGE_TITLE --></title>
</head>
<body>
<div id="app"></div>
<script type="module" src="<!-- ENTRY_PATH -->"></script>
</body>
</html>自定义页面标题
在页面组件中使用 defineOptions 设置标题:
<!-- src/pages/about/index.vue -->
<script setup lang="ts">
defineOptions({
title: '关于我们'
})
</script>
<template>
<div>关于我们页面</div>
</template>标题优先级:手动配置 pages > 组件内 defineOptions > defaultTitle
构建与开发
在 package.json 中添加脚本:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"build:mpa": "vite build --mode staging"
}
}环境变量控制(推荐)
通过环境变量 VITE_MPA 统一控制插件和应用行为:
.env.development
VITE_MPA=false.env.stage
VITE_MPA=truevite.config.ts
import { defineConfig, loadEnv } from 'vite'
import mpa from '@simposons/vite-plugin-mpa'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [
mpa({
enable: env.VITE_MPA === 'true',
}),
],
}
})main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
async function bootstrap() {
const isMPA = import.meta.env.VITE_MPA === 'true'
if (isMPA) {
// MPA 模式:根据页面动态加载组件
const pageName = window.location.pathname
.split('/')
.pop()
?.replace(/\\.html$/, '') || 'index'
try {
const { default: PageComponent } = await import(`./pages/${pageName}/index.vue`)
const app = createApp(PageComponent)
app.use(createPinia())
app.mount('#app')
} catch {
const { default: PageComponent } = await import('@/pages/index/index.vue')
const app = createApp(PageComponent)
app.use(createPinia())
app.mount('#app')
}
} else {
// SPA 模式:使用 Vue Router
const { default: App } = await import('@/App.vue')
const { default: router } = await import('@/router')
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
}
}
bootstrap()开发模式使用 History 路由
配置路由使用 createWebHistory(),实现开发 SPA 与构建 MPA 的无缝切换:
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
// 路由配置
],
})配置选项
| 选项 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| enable | boolean | undefined | 强制启用/禁用 MPA。如果未设置,则回退到检测 --mpa 标志。 |
| pagesDir | string | 'src/pages' | 扫描页面组件(.vue)的目录。 |
| template | string | 'template.html' | HTML 模板文件。 |
| entry | string | 'src/main.ts' | 所有页面共享的 JavaScript 入口文件。 |
| outDir | string | 'node_modules/.vite-mpa' | 生成的 HTML 文件临时存放目录。 |
| modeFlag | string | '--mpa' | 启用 MPA 的命令行标志(当 enable 未设置时生效)。 |
| verbose | boolean | false | 是否打印详细日志。 |
| defaultTitle | string | 'App' | 默认页面标题(页面未指定标题时使用)。 |
| pages | Page[] | undefined | 手动指定页面列表(优先级最高)。每个 Page 可包含 name、title、template、entry。 |
工作原理
- 启用插件后,它会扫描
pagesDir目录下的.vue文件。 - 从文件路径中提取页面名称(例如
about/index.vue→about)。 - 读取每个
.vue文件,提取defineOptions({ title: '...' })中的标题。 - 基于模板为每个页面生成 HTML 文件,将
<!-- PAGE_TITLE -->替换为页面标题。 - 将生成的 HTML 文件路径设置为
build.rollupOptions.input,让 Vite 将其视为多入口。 - 所有页面共享同一个 JavaScript 入口(
entry选项),保证全局初始化逻辑一致。
许可证
MIT
版本更新日志
- 1.0.3: 增加title优先级,手动配置 > 组件内 defineOptions > defaultTitle
- 1.0.2: 完善文档-新增环境变量控制(推荐)
- 1.0.1: 修复生成的html文件中引用路径问题。
- 1.0.0: 初始版本,支持基本功能。
