实现将 Vue3 项目作为子应用,通过无界(Wujie)微前端框架接入到 Vue2 主应用中 (Vue2 为主应用,Vue3 为子应用)。无界针对 Vue2 主应用提供了专属适配包wujie-vue2,且 Vue3 子应用无需任何修改(零改造接入)。下面是超级详细的实现步骤:
一、前提准备
- Vue2 主应用 :已搭建且能独立运行(如基于 Vue CLI 创建,运行在
http://localhost:8080); - Vue3 子应用 :已搭建且能独立运行(如基于 Vite 创建,运行在
http://localhost:5173); - 无界适配包 :Vue2 主应用需安装
wujie-vue2(无界针对 Vue2 的适配包)。
二、步骤 1:Vue3 子应用准备(零改造)
Vue3 子应用无需修改任何代码,只需保证:
- 能独立运行(如通过
npm run dev启动,默认端口5173); - 若使用
history路由模式,需配置base路径(避免子应用资源路径错误)。
(可选)Vue3 子应用路由配置(history 模式)
若 Vue3 子应用用history模式,修改src/router/index.js:
js
import { createRouter, createWebHistory } from 'vue-router';
import Home from '@/views/Home.vue';
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL || '/vue3-app/'), // 生产环境可配置前缀
routes: [
{ path: '/', name: 'Home', component: Home },
{ path: '/about', name: 'About', component: () => import('@/views/About.vue') }
]
});
export default router;
启动 Vue3 子应用:
bash
cd vue3-subapp
npm run dev # 运行在http://localhost:5173
三、步骤 2:Vue2 主应用集成无界
1. Vue2 主应用安装无界 Vue2 适配包
bash
cd vue2-mainapp
npm install wujie-vue2 # 或cnpm install wujie-vue2(若npm速度慢)
2. Vue2 主应用全局注册无界组件(可选)
在 Vue2 主应用的main.js中全局注册无界组件,方便所有页面使用:
js
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import WujieVue2 from 'wujie-vue2'; // 引入无界Vue2适配组件
Vue.config.productionTip = false;
Vue.use(WujieVue2); // 全局注册无界组件
new Vue({
router,
render: h => h(App)
}).$mount('#app');
3. Vue2 主应用创建 Vue3 子应用容器组件
在 Vue2 主应用中创建专门的页面组件(如src/views/Vue3App.vue),用于承载 Vue3 子应用:
vue
<template>
<div class="vue3-app-container">
<h2>Vue2主应用集成Vue3子应用(无界)</h2>
<!-- 无界微前端容器:接入Vue3子应用 -->
<WujieVue2
name="vue3-app" <!-- 子应用唯一标识(不可重复) -->
url="http://localhost:5173/" <!-- Vue3子应用独立访问地址 -->
width="100%" <!-- 子应用宽度 -->
height="600px" <!-- 子应用高度 -->
:props="{ token: 'vue2-main-token', user: { name: 'admin' } }" <!-- 主应用传参 -->
:sync="true" <!-- 同步子应用路由到主应用URL(可选) -->
prefix="/vue3-app" <!-- 子应用路由前缀(配合sync使用,可选) -->
@subAppMounted="handleVue3Mounted" <!-- 监听子应用挂载完成事件 -->
/>
</div>
</template>
<script>
export default {
name: 'Vue3App',
methods: {
handleVue3Mounted(appWindow) {
console.log('Vue3子应用挂载完成', appWindow);
// 调用Vue3子应用暴露的全局方法(若有)
if (appWindow.vue3AppMethod) {
appWindow.vue3AppMethod('来自Vue2主应用的调用');
}
}
}
};
</script>
<style scoped>
.vue3-app-container {
padding: 20px;
}
</style>
4. Vue2 主应用配置路由
在 Vue2 主应用的路由配置中添加 Vue3 子应用的路由(src/router/index.js):
js
import Vue from 'vue';
import Router from 'vue-router';
import Home from '@/views/Home';
import Vue3App from '@/views/Vue3App'; // 引入Vue3子应用容器组件
Vue.use(Router);
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{ path: '/', name: 'Home', component: Home },
{ path: '/vue3-app', name: 'Vue3App', component: Vue3App } // 新增路由
]
});
5. Vue2 主应用添加导航
在 Vue2 主应用的根组件(App.vue)中添加跳转到 Vue3 子应用的导航:
vue
<template>
<div id="app">
<nav>
<router-link to="/">Vue2首页</router-link> |
<router-link to="/vue3-app">Vue3子应用</router-link>
</nav>
<router-view/>
</div>
</template>
<style scoped>
nav {
padding: 20px;
background: #f5f5f5;
margin-bottom: 20px;
}
nav a {
margin-right: 10px;
text-decoration: none;
color: #409eff;
}
</style>
四、步骤 3:Vue3 子应用与 Vue2 主应用通信(可选)
无界会将 Vue2 主应用传递的props挂载到 Vue3 子应用的window.$wujie.props上,Vue3 子应用可直接读取;也可暴露全局方法供主应用调用。
1. Vue3 子应用读取主应用参数
修改 Vue3 子应用的src/App.vue:
vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/vue.svg">
<h1>Vue3子应用</h1>
<!-- 显示主应用传递的参数 -->
<div v-if="mainProps" style="margin-top: 20px; text-align: left; padding: 0 20px;">
<p>主应用传递的Token:{{ mainProps.token }}</p>
<p>用户名:{{ mainProps.user.name }}</p>
</div>
<button @click="sendMsgToVue2">给Vue2主应用发消息</button>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const mainProps = ref(null);
onMounted(() => {
// 读取无界挂载的主应用参数
mainProps.value = window.$wujie?.props;
// 暴露全局方法给Vue2主应用调用
window.vue3AppMethod = (msg) => {
alert(`Vue3子应用收到主应用消息:${msg}`);
};
});
onUnmounted(() => {
// 组件卸载时清理全局方法
delete window.vue3AppMethod;
});
// 向Vue2主应用发送消息
const sendMsgToVue2 = () => {
window.$wujie?.bus.$emit('vue3-to-vue2', { data: 'Hello Vue2主应用!' });
};
</script>
2. Vue2 主应用监听 Vue3 子应用的消息
在 Vue2 主应用的Vue3App.vue中监听无界事件总线:
vue
<script>
import { bus } from 'wujie-vue2'; // 引入无界事件总线
export default {
name: 'Vue3App',
created() {
// 监听Vue3子应用发送的事件
bus.$on('vue3-to-vue2', (data) => {
console.log('Vue2主应用收到Vue3子应用消息:', data);
alert(`Vue2主应用收到:${data.data}`);
});
},
methods: {
handleVue3Mounted(appWindow) {
console.log('Vue3子应用挂载完成', appWindow);
if (appWindow.vue3AppMethod) {
appWindow.vue3AppMethod('来自Vue2主应用的调用');
}
}
}
};
</script>
五、步骤 4:启动测试
- 启动 Vue3 子应用:
cd vue3-subapp && npm run dev(运行在http://localhost:5173); - 启动 Vue2 主应用:
cd vue2-mainapp && npm run serve(运行在http://localhost:8080); - 访问 Vue2 主应用的
/vue3-app路径,即可看到 Vue3 子应用被嵌入到 Vue2 主应用中,且能正常交互、通信。
六、常见问题与解决方案
1. Vue3 子应用资源加载失败(跨域)
- 原因:浏览器同源策略限制,Vue2 主应用访问 Vue3 子应用的资源时跨域;
- 解决方案:无界在开发环境会自动代理子应用请求,无需额外配置;生产环境需配置 Nginx 反向代理(见下文)。
2. Vue3 子应用路由刷新 404(history 模式)
-
原因 :子应用
history模式下,刷新主应用 URL(如http://localhost:8080/vue3-app/about)时,主应用服务器无法识别子应用路由; -
解决方案:
-
开发环境:Vue2 主应用(Vue CLI)配置
devServer.proxy代理子应用路由:js// Vue2主应用的vue.config.js module.exports = { devServer: { port: 8080, proxy: { '/vue3-app': { target: 'http://localhost:5173', changeOrigin: true, rewrite: (path) => path.replace(/^\/vue3-app/, '') // 去掉前缀 } } } }; -
生产环境:配置 Nginx 代理(见下文)。
-
3. Vue3 子应用样式污染 Vue2 主应用
- 原因 :无界默认通过 Shadow DOM 隔离样式,但 Vue3 子应用的全局样式(如
body样式)可能穿透; - 解决方案 :Vue3 子应用的组件样式添加
scoped,或主应用通过:global()覆盖全局样式。
七、生产环境部署配置(Nginx)
生产环境需配置 Nginx 反向代理,解决跨域和路由问题:
nginx
server {
listen 80;
server_name your-domain.com;
# Vue2主应用
location / {
root /path/to/vue2-mainapp/dist;
index index.html;
try_files $uri $uri/ /index.html; # 处理Vue2主应用history路由
}
# Vue3子应用代理(配合无界的prefix="/vue3-app")
location /vue3-app/ {
proxy_pass http://localhost:5173/; # Vue3子应用的生产地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
try_files $uri $uri/ /index.html; # 处理Vue3子应用history路由
}
}
总结
- 核心逻辑 :Vue2 主应用安装
wujie-vue2,通过<WujieVue2>组件配置 Vue3 子应用的name和url即可接入,Vue3 子应用零改造; - 通信方式 :主应用通过
props传参,子应用通过window.$wujie.props接收;通过无界事件总线bus实现双向通信; - 关键配置 :生产环境需配置 Nginx 代理解决跨域和路由刷新问题,
history模式需配合prefix和sync实现路由同步。
通过无界,你可以轻松实现 Vue2 主应用集成 Vue3 子应用,甚至同时集成 React、jQuery 等其他技术栈的子应用,实现真正的技术栈无关微前端架构。