实现将 Vue2 子应用通过无界(Wujie)微前端框架接入到 Vue3 主应用中 (即 Vue3 主应用集成 Vue2 子应用)。无界的核心优势就是子应用零改造接入,Vue2 子应用无需安装无界依赖,只需保证能独立运行即可。下面是超级详细的实现步骤:
一、前提准备
- Vue3 主应用:已搭建(若未搭建,可参考之前的 Vue3+Vite 搭建教程);
- Vue2 子应用 :已搭建且能独立运行(如运行在
http://localhost:8080); - 无界适配包 :Vue3 主应用需安装
wujie-vue3(无界针对 Vue3 的适配包)。
二、步骤 1:Vue2 子应用准备(零改造)
Vue2 子应用无需任何修改,只需确保:
- 能独立运行(如通过
npm run serve启动,默认端口8080); - 若使用
history路由模式,需配置开发环境的publicPath(避免子应用资源路径错误)。
(可选)Vue2 子应用路由配置(history 模式)
若 Vue2 子应用用history模式,修改src/router/index.js:
js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/views/Home'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL, // 开发环境为'/',生产环境可配置为子应用路径(如'/vue2-app/')
routes: [
{ path: '/', name: 'Home', component: Home },
{ path: '/about', name: 'About', component: () => import('@/views/About') }
]
})
启动 Vue2 子应用:
bash
cd vue2-app
npm run serve # 运行在http://localhost:8080
三、步骤 2:Vue3 主应用集成无界
1. Vue3 主应用安装无界 Vue3 适配包
bash
cd vue3-main-app
npm install wujie-vue3 # 或pnpm install wujie-vue3
2. Vue3 主应用配置接入 Vue2 子应用
在 Vue3 主应用中创建专门的页面组件(如src/views/Vue2App.vue),用于承载 Vue2 子应用:
vue
<template>
<div class="vue2-app-container">
<h2>Vue3主应用集成Vue2子应用(无界)</h2>
<!-- 无界微前端容器:接入Vue2子应用 -->
<WujieVue
name="vue2-app" <!-- 子应用唯一标识(不可重复) -->
url="http://localhost:8080/" <!-- Vue2子应用独立访问地址 -->
width="100%" <!-- 子应用宽度 -->
height="600px" <!-- 子应用高度 -->
:props="{ token: 'vue3-main-token', user: { name: 'admin' } }" <!-- 主应用传参给Vue2子应用 -->
:sync="true" <!-- 同步子应用路由到主应用URL(可选) -->
prefix="/vue2-app" <!-- 子应用路由前缀(配合sync使用,可选) -->
@subAppMounted="handleVue2Mounted" <!-- 监听子应用挂载完成事件 -->
/>
</div>
</template>
<script setup>
// 引入无界Vue3组件
import WujieVue from 'wujie-vue3';
// Vue2子应用挂载完成后的回调
const handleVue2Mounted = (appWindow) => {
console.log('Vue2子应用挂载完成', appWindow);
// 调用Vue2子应用暴露的全局方法(若有)
if (appWindow.vue2AppMethod) {
appWindow.vue2AppMethod('来自Vue3主应用的调用');
}
};
</script>
<style scoped>
.vue2-app-container {
padding: 20px;
}
</style>
3. Vue3 主应用配置路由(可选)
在 Vue3 主应用的路由配置中添加 Vue2 子应用的路由(src/router/index.js):
js
import { createRouter, createWebHistory } from 'vue-router';
import Home from '@/views/Home.vue';
import Vue2App from '@/views/Vue2App.vue'; // 引入Vue2子应用容器组件
const routes = [
{ path: '/', name: 'Home', component: Home },
{ path: '/vue2-app', name: 'Vue2App', component: Vue2App }, // 新增路由
];
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
});
export default router;
4. Vue3 主应用添加导航(可选)
在 Vue3 主应用的根组件(App.vue)中添加跳转到 Vue2 子应用的导航:
vue
<template>
<div id="app">
<nav>
<router-link to="/">Vue3首页</router-link> |
<router-link to="/vue2-app">Vue2子应用</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:Vue2 子应用与主应用通信(可选)
无界会将主应用传递的props挂载到 Vue2 子应用的window.$wujie.props上,Vue2 子应用可直接读取;也可暴露全局方法供主应用调用。
1. Vue2 子应用读取主应用参数
修改 Vue2 子应用的src/App.vue:
vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<h1>Vue2子应用</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>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
mainProps: null
};
},
mounted() {
// 读取无界挂载的主应用参数
this.mainProps = window.$wujie?.props;
// 暴露全局方法给Vue3主应用调用
window.vue2AppMethod = (msg) => {
alert(`Vue2子应用收到主应用消息:${msg}`);
};
},
beforeDestroy() {
// 组件销毁时清理全局方法(避免污染)
delete window.vue2AppMethod;
}
};
</script>
2. Vue2 子应用向主应用发送消息
Vue2 子应用可通过window.$wujie.bus触发事件,主应用监听后处理:
js
// Vue2子应用中(如按钮点击事件)
sendMsgToMain() {
window.$wujie?.bus.$emit('vue2-to-vue3', { data: 'Hello Vue3主应用!' });
}
Vue3 主应用监听事件(在Vue2App.vue中):
vue
<script setup>
import WujieVue from 'wujie-vue3';
import { bus } from 'wujie-vue3'; // 引入无界事件总线
// 监听Vue2子应用发送的事件
bus.$on('vue2-to-vue3', (data) => {
console.log('Vue3主应用收到Vue2子应用消息:', data);
alert(`Vue3主应用收到:${data.data}`);
});
const handleVue2Mounted = (appWindow) => {
// ...
};
</script>
五、步骤 4:启动测试
- 启动 Vue2 子应用:
cd vue2-app && npm run serve(运行在http://localhost:8080); - 启动 Vue3 主应用:
cd vue3-main-app && npm run dev(运行在http://localhost:5173); - 访问 Vue3 主应用的
/vue2-app路径,即可看到 Vue2 子应用被嵌入到 Vue3 主应用中,且能正常交互。
六、常见问题与解决方案
1. Vue2 子应用资源加载失败(跨域)
- 原因:浏览器同源策略限制,Vue3 主应用访问 Vue2 子应用的资源时跨域;
- 解决方案:无界在开发环境会自动代理子应用请求,无需额外配置;生产环境需配置 Nginx 反向代理(见下文)。
2. Vue2 子应用路由刷新 404(history 模式)
-
原因 :子应用
history模式下,刷新主应用 URL(如http://localhost:5173/vue2-app/about)时,主应用服务器无法识别子应用路由; -
解决方案:
-
开发环境:Vue3 主应用(Vite)配置
server.proxy代理子应用路由:js// Vue3主应用的vite.config.js import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import path from 'path'; export default defineConfig({ plugins: [vue()], server: { proxy: { // 代理Vue2子应用路由请求 '/vue2-app': { target: 'http://localhost:8080', changeOrigin: true, rewrite: (path) => path.replace(/^\/vue2-app/, '') // 去掉前缀 } } }, resolve: { alias: { '@': path.resolve(__dirname, 'src') } } }); -
生产环境:配置 Nginx 代理(见下文)。
-
3. Vue2 子应用样式污染主应用
- 原因 :无界默认通过 Shadow DOM 隔离样式,但 Vue2 子应用的全局样式(如
body样式)可能穿透; - 解决方案 :Vue2 子应用的样式添加
scoped(组件内样式),或主应用通过:global()覆盖全局样式。
七、生产环境部署配置(Nginx)
生产环境需配置 Nginx 反向代理,解决跨域和路由问题:
nginx
server {
listen 80;
server_name your-domain.com;
# Vue3主应用
location / {
root /path/to/vue3-main-app/dist;
index index.html;
try_files $uri $uri/ /index.html; # 处理Vue3主应用history路由
}
# Vue2子应用代理(配合无界的prefix="/vue2-app")
location /vue2-app/ {
proxy_pass http://localhost:8080/; # Vue2子应用的生产地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
try_files $uri $uri/ /index.html; # 处理Vue2子应用history路由
}
}
总结
- 核心逻辑 :Vue3 主应用安装
wujie-vue3,通过<WujieVue>组件配置 Vue2 子应用的name和url即可接入,Vue2 子应用零改造; - 通信方式 :主应用通过
props传参,子应用通过window.$wujie.props接收;通过无界事件总线bus实现双向通信; - 关键配置 :生产环境需配置 Nginx 代理解决跨域和路由刷新问题,
history模式需配合prefix和sync实现路由同步。
通过无界,你可以轻松实现 Vue3 主应用集成 Vue2 子应用,甚至同时集成 React、jQuery 等其他技术栈的子应用,真正做到技术栈无关的微前端架构。