qiankun 是基于 single-spa 的微前端框架,由阿里开源,主要解决将多个独立技术栈的前端应用整合为一个统一产品的需求。在 React 项目中落地微前端,通常分为主应用(基座)和微应用(子应用)两部分,qiankun 负责子应用的加载、渲染、生命周期管理以及应用间的隔离与通信。
为什么选择 qiankun
- 技术栈无关:子应用可以用 React、Vue、Angular 甚至原生 JS,和主应用的技术选型互不影响。
- 样式隔离与 JS 沙箱:qiankun 默认提供 StrictStyleIsolation 和实验性的 ExperimentalStyleIsolation 解决样式冲突;通过 Proxy 沙箱确保全局变量不互相污染。
- 资源预加载与缓存:支持预加载子应用资源,加快切换速度。
- 生命周期清晰:每个子应用需暴露 bootstrap、mount、unmount 三个生命周期函数,主应用通过注册管理。
主应用(React + qiankun)
安装依赖:
npm install qiankun
在主应用的入口文件中注册微应用:
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'app-react', // 微应用名称,需与子应用 package.json 中的 name 一致
entry: '//localhost:3001', // 子应用本地开发地址
container: '#subapp-viewport', // 子应用挂载的 DOM 容器
activeRule: '/app-react', // 激活路径,匹配到该路径则加载子应用
props: { globalData: '从主应用传递的数据' } // 通信数据
}
]);
start({
sandbox: { experimentalStyleIsolation: true } // 开启样式隔离
});
主应用需要在页面中预留容器:
function App() {
return (
<div>
<h1>主应用基座</h1>
<div id="subapp-viewport"></div>
</div>
);
}
微应用(React 子应用)改造
React 子应用通常使用 Webpack 或 Vite 构建,需要做以下调整:
1. 配置文件调整
使用 CRA / Webpack 的项目 需要修改 webpack 配置以支持 UMD 格式输出,因为 qiankun 通过动态加载 UMD 包获取生命周期。通常使用 @rescripts/cli 或 react-app-rewired 覆盖配置:
// config-overrides.js
module.exports = {
webpack: (config) => {
config.output.library = 'appReact'; // 包名,与 registerMicroApps 中的 name 对应
config.output.libraryTarget = 'umd';
config.output.globalObject = 'window';
return config;
}
};
使用 Vite 的项目 需要安装 vite-plugin-qiankun:
npm install vite-plugin-qiankun
// vite.config.js
import qiankun from 'vite-plugin-qiankun';
export default {
plugins: [
qiankun('app-react', { // name 需保持一致
useDevMode: true
})
]
};
2. 微应用入口改造,导出生命周期
在 src/index.js 或 main.jsx 中,需要将标准的 React 渲染逻辑包装成 qiankun 要求的生命周期函数:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
let root = null;
function render(props) {
const { container } = props;
const dom = container
? container.querySelector('#root')
: document.getElementById('root');
root = ReactDOM.createRoot(dom);
root.render(<App globalData={props.globalData} />);
}
// 独立运行(非 qiankun 环境)时直接渲染
if (!window.__POWERED_BY_QIANKUN__) {
render({});
}
// 导出三个生命周期
export async function bootstrap() {
console.log('微应用启动');
}
export async function mount(props) {
console.log('微应用挂载', props);
render(props);
}
export async function unmount(props) {
console.log('微应用卸载');
root?.unmount();
}
3. 处理跨域和公共路径
微应用资源需要允许主应用跨域加载,开发环境通常通过 webpack-dev-server 或 vite 配置 CORS 头:
- Webpack:
devServer.headers = { 'Access-Control-Allow-Origin': '*' } - Vite:
server.cors = true
另外,需确保微应用的 publicPath 正确,避免资源 404。
应用间通信
qiankun 提供三种通信方式(按推荐程度排序):
- Props 传递(官方推荐,轻量场景)
主应用通过 registerMicroApps 的 props 字段下传数据,子应用通过生命周期函数的 props 参数接收。适合简单的主→子数据下发。
- 全局状态池(
initGlobalState)
主应用创建一个全局状态池,子应用通过 onGlobalStateChange 监听变化,setGlobalState 修改。
// 主应用
import { initGlobalState } from 'qiankun';
const actions = initGlobalState({ user: 'admin' });
actions.onGlobalStateChange((state, prev) => {
console.log('状态变化', state, prev);
});
// 传递给子应用
props.setGlobalState = actions.setGlobalState;
props.onGlobalStateChange = actions.onGlobalStateChange;
子应用中获取这些方法并调用即可实现双向通信。
- 共享 Store、事件总线等自定义方案,适用于复杂场景。
常见坑点与解决方案
1. 子应用路由冲突
子应用内部使用 React Router 时,basename 需要与主应用的激活路径匹配,例如主应用 activeRule 是 /app-react,子路由的 basename 应设为 /app-react。否则可能出现点击后地址跳到 localhost:3000/about 而非 localhost:3000/app-react/about。
<BrowserRouter basename="/app-react">
<App />
</BrowserRouter>
2. 样式隔离不彻底
qiankun 默认的 strictStyleIsolation 会为每个子应用包裹 Shadow DOM,这可能导致一些 UI 组件库(如 Ant Design 的弹窗挂载到 body)样式丢失。可改用 experimentalStyleIsolation,它通过给样式加前缀来实现轻隔离,但可能仍有遗漏。建议规范 CSS 命名(BEM / CSS Modules)作为兜底。
3. 子应用动态加载的 publicPath 错误
使用 React.lazy 或动态 import 时,子应用可能从主应用的域名加载 chunk,导致 404。需在子应用入口顶部设置 __webpack_public_path__:
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
4. 开发体验不一致
子应用独立开发时可以正常访问,但嵌入主应用后可能出现错误。建议团队维护一个统一的基座本地开发环境,或者使用 qiankun 提供的 start({ prefetch: false }) 关闭预加载以调试。
生产部署
微前端的部署本质上是微应用独立构建,各自部署在不同的服务器或路径下,主应用通过远程地址 entry 指向微应用的入口 HTML(或 JS 资源)。需要确保跨域配置在生产环境依然有效,一般是 Nginx 配置:
location /app-react {
add_header Access-Control-Allow-Origin *;
try_files $uri $uri/ /index.html;
}
qiankun 在 React 项目中的落地,核心在于微应用的改造标准(独立运行时与微前端模式兼容)以及公共设施的补充(状态通信、样式隔离、路径管理)。一旦建立模板,后续添加新子应用的成本极低,适合大型团队跨业务线并行开发。