一、项目架构设计
1. 技术栈
- 主应用(Vue3):Vite + Vue3 + Pinia + Wujie
- 子应用(Vue2 权限模块):Webpack + Vue2 + Vuex + ElementUI
- 子应用(Vue3 数据看板):Vite + Vue3 + ECharts/AntV + Wujie
- 通信机制:无界事件总线 + Pinia/Vuex 状态共享
- 部署方案:Nginx 独立部署 + 主应用路由分发
2. 功能模块
- 权限模块(Vue2):RBAC 模型、动态路由、按钮级权限控制
- 数据看板(Vue3):动态图表、实时数据筛选、多维度分析
- 主应用:微应用容器、全局状态管理、用户登录/退出
二、主应用配置(Vue3)
1. 安装依赖
# 主应用
npm install wujie-vue3 -S
2. 初始化无界
// main.js
import { createApp } from 'vue';
import WujieVue from 'wujie-vue3';
const app = createApp(App);
app.use(WujieVue);
3. 加载子应用
<!-- App.vue -->
<template>
<!-- 权限子应用(Vue2) -->
<WujieVue
name="permission"
url="http://localhost:7101"
:alive="true"
:props="{ user: userStore.user }"
@filter-change="handleFilter"
/>
<!-- 数据看板子应用(Vue3) -->
<WujieVue
name="dashboard"
url="http://localhost:7102"
:preload="true"
/>
</template>
<script setup>
import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
// 接收子应用筛选条件
const handleFilter = (filter) => {
userStore.updateFilter(filter);
};
</script>
4. 全局状态管理(Pinia)
// stores/user.js
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({
user: { role: 'admin' },
filter: {}
}),
actions: {
updateFilter(filter) {
this.filter = filter;
}
}
});
三、子应用配置
1. Vue2 权限模块
入口改造
// main.js
if (window.__POWERED_BY_WUJIE__) {
let instance;
window.__WUJIE_MOUNT = () => {
instance = new Vue({ store, router, render: h => h(App) }).$mount('#app');
};
window.__WUJIE_UNMOUNT = () => instance.$destroy();
} else {
new Vue({ store, router, render: h => h(App) }).$mount('#app');
}
RBAC 权限控制(Vuex)
// store/permission.js
export default new Vuex.Store({
state: {
roles: [],
routes: []
},
mutations: {
SET_ROUTES(state, routes) {
state.routes = routes;
}
},
actions: {
async generateRoutes({ commit }, roles) {
const dynamicRoutes = await fetchRoutesByRole(roles); // 根据角色获取路由
commit('SET_ROUTES', dynamicRoutes);
}
}
});
动态路由加载
// router.js
router.beforeEach((to, from, next) => {
const roles = store.state.user.roles;
if (to.meta.roles && !to.meta.roles.includes(roles)) {
next('/403'); // 无权限跳转
} else {
next();
}
});
2. Vue3 数据看板
Vite 跨域配置
// vite.config.js
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://主应用域名',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
});
图表与事件通信
<script setup>
import { onMounted } from 'vue';
import { useChartData } from '@/composables/chart';
const props = defineProps(['filter']);
const { loadData } = useChartData();
// 监听主应用筛选条件
watch(() => props.filter, (newFilter) => {
loadData(newFilter);
});
// 向主应用发送事件
const emitChartClick = (data) => {
window.parent.$wujie?.bus.$emit('chart-click', data);
};
</script>
四、通信与优化
1. 跨应用通信
- 主传子:通过
props
传递全局状态(如用户信息) - 子传主:通过无界事件总线
$wujie.bus
发送事件(如筛选条件变更)
2. 保活模式优化
- 配置
alive: true
保留子应用状态,避免重复渲染。 - 使用
preloadApp
预加载高频子应用资源
3. 样式隔离
- 无界通过 Shadow DOM 实现 CSS 沙箱。
- 子应用添加 CSS 命名空间(如
.permission-btn
)避免冲突
五、部署与调试
1. 独立部署
# 主应用 Nginx 配置
location / {
root /usr/share/nginx/html/main-app;
try_files $uri $uri/ /index.html;
}
# 子应用路由配置
location /sub-permission {
alias /usr/share/nginx/html/sub-permission;
try_files $uri $uri/ /sub-permission/index.html;
}
2. 调试技巧
- 使用 Chrome 开发者工具 Application > Frames 查看子应用 DOM。
- 通过
window.__WUJIE
查看无界注入的全局对象
六、扩展功能
1. 权限管理扩展
- 数据权限:通过 Vuex 控制数据可见性(如部门隔离)
- 审计日志:记录用户操作至 Elasticsearch,通过 Kibana 可视化
2. 性能监控
- 使用
window.performance
记录子应用加载耗时。 - 集成 Sentry 监控前端异常
七、避坑指南
- 子应用路由冲突:主应用使用唯一路径前缀(如
/micro/*
),子应用配置base
参数 - 静态资源 404:子应用设置
publicPath: '/sub-app/'
修正资源路径 - 跨域 Cookie:主应用配置
withCredentials: true
,子应用启用 CORS