极简实战:React + Vue 微前端(Qiankun + Vite)
微前端架构将大型应用拆解为独立开发、部署的子应用,极大提升了复杂系统的可维护性。本文将手把手教你使用 Qiankun 框架,在 Vite 构建的 React 18 主应用中集成 Vue 3 子应用。
·
✨ 微前端实战:React 主应用 + Vue 子应用
微前端架构将大型应用拆解为独立开发、部署的子应用,极大提升了复杂系统的可维护性。本文将手把手教你使用 Qiankun 框架,在 Vite 构建的 React 18 主应用中集成 Vue 3 子应用。
️ 一、主应用 (React 18 + Vite):搭好舞台
主应用就像个“大舞台”,负责调度和管理各个“演员”(子应用)。
1.请来“管家” Qiankun
npm install qiankun --save
# 或者 yarn add qiankun
2.登记“演员”信息 & 启动舞台在 React 主应用的启动文件(通常是main.jsx或App.jsx)里操作:
import { registerMicroApps, start } from 'qiankun';
// 告诉 Qiankun 有哪些子应用可以上台表演
registerMicroApps([
{
name: 'vue3-module', // 给子应用起个唯一艺名
entry: '//localhost:5500', // 子应用开发时在哪候场(开发服务器地址)
container: '#vue-app-container', // 舞台上哪个区域给这个演员(DOM元素ID)
activeRule: '/vue-module', // 什么信号(路由)一响,就该他上场了
props: { // 给演员的初始道具(数据)
greeting: 'Hello from React Boss!',
userRole: 'admin',
},
},
]);
// 灯光师、音响师就位,舞台启动!
start({
sandbox: {
experimentalStyleIsolation: true, // 重要!给演员单独化妆间(样式隔离),避免串妆
},
});
贴心提示:
activeRule: 主应用的路由(比如用了react-router-dom)匹配到这个路径时,就召唤对应的子应用。experimentalStyleIsolation: true: 强烈建议开启。这相当于给子应用套了个“透明玻璃房”(Shadow DOM),它们的 CSS 就不会跑出来把主应用或者其他子应用的页面搞乱。
3.给演员留好位置 (路由配置 - React Router v6 示例)确保主路由知道把/vue-module开头的请求交给子应用:
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function MainApp() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
{/* 这里就是留给 Vue 子应用的专属区域! */}
<Route path="/vue-module/*" element={<div id="vue-app-container" />} />
</Routes>
</BrowserRouter>
);
}
二、子应用 (Vue 3 + Vite):演员准备登场
Vue 子应用是个“独立演员”,但要学会在 Qiankun 的舞台上表演。
1.装上“舞台适配器”
npm install vite-plugin-qiankun --save-dev
# 或者 yarn add vite-plugin-qiankun -D
2.配置“化妆间”(vite.config.js)
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import qiankun from 'vite-plugin-qiankun'; // 引入适配器
export default defineConfig({
plugins: [
vue(),
qiankun('vue3-module', { // ⚠️ 艺名必须和主应用登记的一模一样!
useDevMode: true // 开发模式也要能上台排练
})
],
server: {
port: 5500, // ⚠️ 候场地址端口,必须和主应用 `entry` 一致
origin: 'http://localhost:5500' // 确保资源能找到回家的路
},
base: process.env.NODE_ENV === 'production'
? '/path/to/your/vue-subapp/' // 正式演出时的后台路径
: '/', // 排练时就在后台门口
});
关键警报:
qiankun('vue3-module', ...): 这里的'vue3-module'必须、必须、必须 和主应用registerMicroApps里的name完全一致!不然对不上号。base: 这是最容易栽跟头的地方! 开发环境设为'/',生产环境必须是你子应用最终部署在服务器上的相对路径(相对于主应用的域名)。配错了,图片、JS、CSS 全找不到!
3.学会“登台谢幕”(改造main.js)让 Vue 应用知道自己是独立演出还是在 Qiankun 的大舞台上:
import { createApp } from 'vue';
import App from './App.vue';
import router from './router'; // 子应用自己的路由
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
let vueApp = null; // 保存 Vue 应用实例
// 独立表演时的剧本
function renderStandaloneApp(container = null) {
vueApp = createApp(App);
vueApp.use(router); // 挂载自己的路由、状态管理等
// ... 其他插件
vueApp.mount(container ? container.querySelector('#app') : '#app'); // 挂载到指定或默认位置
}
// 判断:现在是独立演出吗?
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
renderStandaloneApp(); // 是,按独立方式启动
}
// Qiankun 舞台的生命周期钩子:演员要遵守舞台规则
renderWithQiankun({
// 舞台导演喊“上场!”
mount(props) {
console.log(' Vue子应用收到道具:', props); // 能看到主应用给的道具(props)
renderStandaloneApp(props.container); // 把自己挂载到舞台导演指定的容器里
// 通常这里也会初始化通信监听
},
// 第一次上场前准备 (可空)
bootstrap() {
console.log(' Vue子应用准备上场...');
},
// 导演要求临时调整表演 (可空)
update(props) {
console.log(' Vue子应用收到新剧本:', props);
},
// 导演喊“下场!”
unmount() {
console.log(' Vue子应用谢幕...');
vueApp?.unmount(); // 把自己卸载干净
vueApp = null; // 清空实例
},
});
演员修养:
qiankunWindow: 用它判断是在独立环境还是 Qiankun 舞台环境。renderWithQiankun: 告诉 Qiankun 导演:“这是我的上场(mount)、下场(unmount)方法,您随时调用”。mount(props):props.container是导演递过来的话筒支架(挂载点 DOM 元素),props里还有导演给的道具和通信工具。- 资源路径: 再次强调
base配置正确的重要性!所有相对路径资源(./assets/logo.png)都依赖它。
三、主应用和子应用“对讲机”:通信
舞台上的演员需要交流。Qiankun 提供了 initGlobalState 这个“对讲机系统”
1.主应用:安装并管理对讲机
// 主应用某处 (e.g., src/utils/qiankunState.js)
import { initGlobalState } from 'qiankun';
// 初始化对讲机公共频道和默认消息
const initialState = {
theme: 'light-mode',
currentProjectId: 123,
notifications: []
};
const globalActions = initGlobalState(initialState);
// 主应用自己也要听听公共频道
globalActions.onGlobalStateChange((newState, oldState) => {
console.log('主应用监听到:', newState, '之前是:', oldState);
// 根据消息更新主应用自己的状态或UI (比如换主题)
});
// 主应用发广播 (e.g., 用户切换了主题)
function switchAppTheme(newTheme) {
globalActions.setGlobalState({
...globalActions.getGlobalState(), // 先拿当前所有状态
theme: newTheme // 只更新 theme 字段
});
}
// 把 globalActions 导出去,哪里需要发广播哪里引入
export { globalActions };
2.子应用:加入公共频道,收听和发言在子应用mount时拿到对讲机:
renderWithQiankun({
mount(props) {
// ... 挂载逻辑
// 1. 领一个对讲机耳机,收听公共频道
props.onGlobalStateChange(
(newState, oldState) => {
console.log(' Vue子应用听到:', newState);
// 根据消息更新子应用内部状态 (比如用 Pinia/Vuex 存 theme)
if (newState.theme !== oldState?.theme) {
switchThemeLocally(newState.theme); // 本地切换主题
}
},
true // true 表示立刻用当前状态触发一次上面的回调
);
// 2. 子应用也可以发广播 (但只能更新主应用定义好的那些“话题”)
function updateProjectStatus(status) {
props.setGlobalState({
currentProjectStatus: status // 只能更新 initialState 里已有的一级属性!
});
}
},
// ... 其他生命周期
});
通信规则:
- 主控权在主应用: 主应用初始化状态和对讲机系统。
- 子应用“有限发言权”: 子应用只能修改全局状态对象中主应用已经预先定义好的一级属性(比如
theme,currentProjectId)。它不能自己发明一个新的一级属性广播出去。 - 记得“摘耳机”: Qiankun 在子应用下场(
unmount)时会自动帮它关掉监听(offGlobalStateChange),一般无需子应用自己操作。
四、必看注意事项
- 名称一致性:主/子应用的
name必须完全匹配 - base 配置:子应用生产环境需设置正确部署路径
- 样式隔离:始终开启
experimentalStyleIsolation - 路由冲突:确保主应用路由不拦截子应用路径
- 部署优化:生产环境需配置 CDN 和 CORS
更多推荐


所有评论(0)