vue 微前端 项目
- 核心前置知识
- 第一步:环境准备
- 第二步:创建主应用(基座应用)
-
- [1. 创建并初始化主应用](#1. 创建并初始化主应用)
- [2. 配置主应用核心代码](#2. 配置主应用核心代码)
-
- [(1)修改主应用入口文件 src/main.js](#(1)修改主应用入口文件 src/main.js)
- [(2)修改主应用根组件 src/App.vue](#(2)修改主应用根组件 src/App.vue)
- [(3)修改主应用路由 src/router/index.js](#(3)修改主应用路由 src/router/index.js)
- (4)配置主应用端口(避免和子应用冲突)
- [第三步:创建子应用(Vue 子应用)](#第三步:创建子应用(Vue 子应用))
-
- [1. 创建并初始化子应用](#1. 创建并初始化子应用)
- [2. 配置子应用核心代码](#2. 配置子应用核心代码)
-
- [(1)修改子应用入口文件 src/main.js](#(1)修改子应用入口文件 src/main.js)
- [(2)修改子应用路由 src/router/index.js](#(2)修改子应用路由 src/router/index.js)
- (3)配置子应用打包和跨域
- [(4)解决子应用路由懒加载的 chunk 路径问题](#(4)解决子应用路由懒加载的 chunk 路径问题)
- 第四步:启动并验证微前端
-
- [1. 启动子应用](#1. 启动子应用)
- [2. 启动主应用](#2. 启动主应用)
- [3. 验证效果](#3. 验证效果)
- 关键注意事项(避坑指南)
- 总结
创建一个基于 Vue 的微前端项目,以 qiankun(乾坤) 框架为例,从零搭建「主应用 + 子应用」的微前端架构,步骤清晰且可直接落地。
核心前置知识
- 微前端核心:将多个独立的 Vue 应用(子应用)嵌入到一个主应用中,实现独立开发、独立部署、整体集成。
- 技术选型:主应用(Vue 3) + 子应用(Vue 3) + qiankun(微前端框架),兼容 Vue 2(只需微调配置)。
第一步:环境准备
确保已安装:
- Node.js ≥ 14.18.0
- npm/yarn/pnpm(推荐 npm)
- @vue/cli ≥ 5.0.0(vue --version 验证)
第二步:创建主应用(基座应用)
1. 创建并初始化主应用
bash
# 创建主应用(命名为 main-app)
vue create main-app
# 选择 Vue 3 + Default 模板(回车确认)
cd main-app
# 安装 qiankun
npm install qiankun -S
npm install vue-router -S
2. 配置主应用核心代码
(1)修改主应用入口文件 src/main.js
javascript
import { createApp } from 'vue'
import { registerMicroApps, start } from 'qiankun'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router).mount('#app')
// 1. 注册子应用
registerMicroApps([
{
name: 'vue-sub-app', // 子应用唯一标识(需和子应用 package.json name 一致)
entry: '//localhost:8081', // 子应用运行地址
container: '#sub-app-container', // 子应用挂载的 DOM 容器(需在 App.vue 中定义)
activeRule: '/vue-sub-app', // 触发子应用激活的路由规则
},
])
// 2. 启动 qiankun
start({
sandbox: { strictStyleIsolation: true }, // 开启样式隔离,避免子应用样式污染主应用
})
(2)修改主应用根组件 src/App.vue
html
<template>
<div id="app">
<h1>Vue 微前端主应用</h1>
<!-- 主应用导航 -->
<nav>
<router-link to="/">主应用首页</router-link> |
<router-link to="/vue-sub-app">子应用</router-link>
</nav>
<!-- 子应用挂载容器 -->
<div id="sub-app-container"></div>
</div>
</template>
<style scoped>
nav {
margin: 20px 0;
}
a {
margin-right: 10px;
text-decoration: none;
color: #409eff;
}
</style>
(3)修改主应用路由 src/router/index.js
javascript
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView,
},
// 新增:子应用路由占位(必须和 activeRule 匹配,且不能有 component)
{
path: '/vue-sub-app/*', // 通配符匹配子应用所有路由
name: 'vue-sub-app',
},
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
})
export default router
(4)配置主应用端口(避免和子应用冲突)
在主应用根目录创建 vue.config.js:
javascript
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
devServer: {
port: 8080, // 主应用运行在 8080 端口
headers: {
'Access-Control-Allow-Origin': '*', // 允许跨域(子应用加载必需)
},
},
})
第三步:创建子应用(Vue 子应用)
1. 创建并初始化子应用
bash
# 回到上级目录,创建子应用(命名为 vue-sub-app)
cd ..
vue create vue-sub-app
# 选择 Vue 3 + Default 模板
cd vue-sub-app
npm install vue-router -S
2. 配置子应用核心代码
(1)修改子应用入口文件 src/main.js
javascript
import '../public-path'; // 必须放在最顶部!(解决路由懒加载的 chunk 路径解析问题)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
let app = null
// 微前端环境下的挂载函数
function render(props = {}) {
const { container } = props
// 挂载容器:微前端环境用主应用提供的容器,否则用默认 #app
const mountNode = container ? container.querySelector('#app') : '#app'
app = createApp(App)
app.use(router).mount(mountNode)
}
// 独立运行时直接挂载
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
// 微前端生命周期:子应用必须暴露这三个函数
export async function bootstrap() {
console.log('vue-sub-app bootstrap')
}
export async function mount(props) {
console.log('vue-sub-app mount')
render(props)
}
export async function unmount() {
console.log('vue-sub-app unmount')
app.unmount() // 卸载应用
app = null
}
(2)修改子应用路由 src/router/index.js
javascript
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
// 微前端环境下,路由基础路径要和主应用的 activeRule 一致
const base = window.__POWERED_BY_QIANKUN__ ? '/vue-sub-app' : process.env.BASE_URL
const routes = [
{
path: '/',
name: 'home',
component: HomeView,
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue'),
},
]
const router = createRouter({
history: createWebHistory(base), // 动态设置基础路径
routes,
})
export default router
(3)配置子应用打包和跨域
在子应用根目录创建 vue.config.js:
javascript
const { defineConfig } = require('@vue/cli-service')
const { name } = require('./package.json')
module.exports = defineConfig({
devServer: {
port: 8081, // 子应用运行在 8081 端口
headers: {
'Access-Control-Allow-Origin': '*', // 允许跨域
},
},
// 配置打包为 umd 格式(qiankun 要求)
configureWebpack: {
output: {
library: `${name}-[name]`,
libraryTarget: 'umd', // 关键:输出为 umd 模块
chunkLoadingGlobal: `webpackJsonp_${name}`,
},
},
})
(4)解决子应用路由懒加载的 chunk 路径问题
javascript
// vue-sub-app/public-path.js
// 微前端环境下,动态设置 publicPath 为子应用的 entry 地址
if (window.__POWERED_BY_QIANKUN__) {
// __INJECTED_PUBLIC_PATH_BY_QIANKUN__ 是 qiankun 自动注入的子应用 entry 地址(如 //localhost:8081/)
// 忽略 __webpack_public_path__ 的 ESLint 未定义校验
/* eslint-disable-next-line no-undef */
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
} else {
// 独立运行时,publicPath 为根路径
/* eslint-disable-next-line no-undef */
__webpack_public_path__ = process.env.BASE_URL;
}
第四步:启动并验证微前端
1. 启动子应用
bash
cd vue-sub-app
npm run serve
# 验证:访问 http://localhost:8081 能看到子应用独立运行
2. 启动主应用
bash
cd ../main-app
npm run serve
# 访问 http://localhost:8080
3. 验证效果
- 访问 http://localhost:8080:看到主应用首页;
- 点击「子应用」链接:页面跳转到 /vue-sub-app,子应用成功嵌入主应用;
- 子应用内点击「About」:子应用路由正常跳转,主应用布局保持不变。
关键注意事项(避坑指南)
- 跨域问题: 主 / 子应用都必须配置 Access-Control-Allow-Origin: *,否则子应用无法加载;
- 路由冲突:
- 主应用路由需添加子应用的通配符路由(/vue-sub-app/*);
- 子应用路由基础路径要适配微前端环境(window.POWERED_BY_QIANKUN);
- 样式隔离: 主应用启动 qiankun 时开启 strictStyleIsolation: true,避免子应用样式污染主应用;
- Vue 2 适配:
子应用 main.js 中替换为 Vue 2 的写法:
javascript
import Vue from 'vue'
import App from './App.vue'
import router from './router'
let app = null
function render(props = {}) {
const { container } = props
app = new Vue({
router,
render: h => h(App)
}).$mount(container ? container.querySelector('#app') : '#app')
}
- 生产环境部署:
- 子应用需打包为 umd 格式(已配置);
- 主应用 registerMicroApps 中 entry 改为子应用的生产环境地址(如
https://sub-app.example.com)。
总结
- 微前端核心:主应用通过 qiankun 注册子应用,子应用暴露 bootstrap/mount/unmount 生命周期;
- 关键配置:子应用打包为 umd 格式、主 / 子应用配置跨域、路由适配微前端环境;
3.启动顺序:先启动子应用,再启动主应用,验证时先确认子应用独立运行正常。