一篇文章搞懂 qiankun:是什么、为什么、怎么用、什么时候用
📚 目录
- 一、什么是微前端
- [二、什么是 qiankun](#二、什么是 qiankun "#%E4%BA%8C%E4%BB%80%E4%B9%88%E6%98%AF-qiankun")
- [三、为什么要用 qiankun](#三、为什么要用 qiankun "#%E4%B8%89%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%94%A8-qiankun")
- [四、qiankun 核心概念](#四、qiankun 核心概念 "#%E5%9B%9Bqiankun-%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5")
- [五、快速上手:10 分钟搭建第一个微前端应用](#五、快速上手:10 分钟搭建第一个微前端应用 "#%E4%BA%94%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B10-%E5%88%86%E9%92%9F%E6%90%AD%E5%BB%BA%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%BE%AE%E5%89%8D%E7%AB%AF%E5%BA%94%E7%94%A8")
- 六、技术栈兼容性
- 七、进阶知识
- [八、什么时候该用 qiankun](#八、什么时候该用 qiankun "#%E5%85%AB%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E8%AF%A5%E7%94%A8-qiankun")
- 九、常见问题和解决方案
- 十、学习路线图
一、什么是微前端
🤔 先从问题说起
想象你在开发一个大型电商网站:
- 首页(营销团队负责)
- 商品页(商品团队负责)
- 购物车(订单团队负责)
- 用户中心(用户团队负责)
传统做法:所有代码在一个项目里
perl
my-ecommerce/
├── src/
│ ├── pages/
│ │ ├── home/ # 首页(营销团队)
│ │ ├── product/ # 商品页(商品团队)
│ │ ├── cart/ # 购物车(订单团队)
│ │ └── user/ # 用户中心(用户团队)
│ └── ...
└── package.json
会遇到的问题:
-
协作困难 😫
- 4 个团队改同一个代码仓库
- Git 冲突不断
- 一个人改的代码可能影响到别人
-
部署困难 😰
- 营销团队想更新首页,必须重新部署整个应用
- 其他团队的代码也被迫重新部署
- 一旦有 bug,整个网站都挂了
-
技术栈固化 😓
- 整个项目都得用 React,想用 Vue 不行
- 想升级 React 版本,所有代码都得测一遍
-
编译越来越慢 🐌
- 代码越来越多,打包要 10 分钟
- 改一行代码,等 10 分钟才能看到效果
💡 微前端的解决方案
把一个大应用拆分成多个小应用,每个小应用独立运行
主应用(基座)
├── 首页子应用(独立项目)
├── 商品子应用(独立项目)
├── 购物车子应用(独立项目)
└── 用户中心子应用(独立项目)
就像:
- 传统应用:一个巨大的 Word 文档,所有内容都在里面
- 微前端:一个文件夹,里面有多个独立的 Word 文档,需要时打开相应的文档
🎯 微前端的核心思想
"将前端应用拆解为一些更小、更简单的能够独立开发、测试、部署的小应用,然后再由主应用来加载这些小应用"
二、什么是 qiankun
🏛️ qiankun 简介
qiankun(乾坤) 是阿里巴巴开源的微前端框架,基于 single-spa 封装。
- 官网 :qiankun.umijs.org/
- GitHub :github.com/umijs/qiank...
- 开源时间:2019 年
- 维护团队:蚂蚁金服(阿里)
- 使用公司:阿里巴巴、字节跳动、腾讯、京东、滴滴等
🎭 形象比喻
把 qiankun 想象成一个智能剧院:
css
┌─────────────────────────────────────────┐
│ qiankun 剧院(主应用) │
│ ┌────────────────────────────────┐ │
│ │ 舞台(容器 div) │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ 正在表演的剧目 │ │ │
│ │ │ (当前激活的子应用) │ │ │
│ │ └──────────────────────┘ │ │
│ └────────────────────────────────┘ │
│ │
│ 剧目清单: │
│ ☐ 话剧(React 应用) │
│ ☑ 歌剧(Vue 应用) ← 正在播放 │
│ ☐ 舞剧(Angular 应用) │
│ ☐ 杂技(原生 JS 应用) │
└─────────────────────────────────────────┘
- 主应用 = 剧院本身(提供舞台、灯光、座位)
- 子应用 = 不同的演出剧目(独立制作、独立演出)
- qiankun = 剧院的管理系统(决定什么时候演什么剧)
🔧 qiankun 的核心能力
- 应用加载 - 能加载各种前端应用
- 应用隔离 - 保证应用之间不互相干扰
- 应用通信 - 让应用之间能交流
- 生命周期管理 - 控制应用的启动、运行、卸载
三、为什么要用 qiankun
✅ 解决的核心问题
1. 团队协作问题
没有 qiankun 之前:
css
团队 A: "我要改首页"
团队 B: "我也要改首页相关的代码"
结果:Git 冲突,互相等待,效率低下
有了 qiankun 之后:
yaml
团队 A: 改自己的子应用项目
团队 B: 改自己的子应用项目
结果:互不干扰,并行开发
2. 部署问题
没有 qiankun 之前:
营销团队:我只改了首页一个按钮颜色
结果:整个应用重新部署,所有用户重新下载 10MB 的 JS
有了 qiankun 之后:
营销团队:只部署首页子应用
结果:只有访问首页的用户重新下载 1MB 的 JS,其他页面不受影响
3. 技术栈问题
没有 qiankun 之前:
老项目用 Vue 2 写的,想用 React 写新功能?
答:不行,全部重构吧
有了 qiankun 之后:
老项目用 Vue 2(作为子应用)
新功能用 React(另一个子应用)
答:可以!它们可以共存
4. 代码体积问题
没有 qiankun 之前:
diff
用户访问首页,加载了:
- 首页代码(1MB)
- 商品页代码(2MB)
- 购物车代码(1MB)
- 用户中心代码(1MB)
总计:5MB
用户:我只想看首页啊!为什么要下载这么多?
有了 qiankun 之后:
diff
用户访问首页,只加载:
- 主应用框架(200KB)
- 首页子应用(1MB)
总计:1.2MB
用户访问商品页时,才加载商品页子应用
📊 对比表格
| 维度 | 单体应用 | qiankun 微前端 |
|---|---|---|
| 团队协作 | 多人改一个项目,冲突多 | 每个团队独立项目,无冲突 |
| 部署效率 | 改一处,全部署 | 改哪个部署哪个 |
| 技术栈 | 必须统一 | 可以不同 |
| 加载速度 | 一次加载所有代码 | 按需加载 |
| 风险控制 | 一处 bug 全挂 | 子应用 bug 不影响其他 |
| 学习成本 | 低 | 中等 |
| 架构复杂度 | 低 | 中高 |
四、qiankun 核心概念
🏗️ 架构图
css
┌────────────────────────────────────────────────┐
│ 浏览器窗口 │
│ ┌──────────────────────────────────────────┐ │
│ │ 主应用(Main App) │ │
│ │ ┌────────────────────────────────────┐ │ │
│ │ │ 导航栏 Header │ │ │
│ │ ├─────────┬──────────────────────────┤ │ │
│ │ │ 侧边栏 │ <div id="container"> │ │ │
│ │ │ Sidebar │ 子应用挂载容器 │ │ │
│ │ │ │ ┌──────────────────┐ │ │ │
│ │ │ - 首页 │ │ │ │ │ │
│ │ │ - 商品 │ │ 当前激活的 │ │ │ │
│ │ │ - 购物车│ │ 子应用内容 │ │ │ │
│ │ │ - 用户 │ │ │ │ │ │
│ │ │ │ └──────────────────┘ │ │ │
│ │ └─────────┴──────────────────────────┘ │ │
│ │ Footer 底部栏 │ │
│ └──────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
🎯 核心概念
1. 主应用(Main App / 基座)
职责:
- 提供页面框架(Header、Sidebar、Footer)
- 注册所有子应用
- 监听路由变化
- 加载和卸载子应用
特点:
- 通常代码量很少
- 不包含具体业务逻辑
- 就像一个空房子,提供水电和框架
2. 子应用(Micro App)
职责:
- 实现具体的业务功能
- 导出生命周期函数
- 可以独立运行(独立访问)
特点:
- 是完整的前端应用
- 有自己的路由、状态管理
- 像房子里的租客,有独立的生活
3. 容器(Container)
就是一个普通的 div:
html
<div id="container"></div>
子应用会被渲染到这个 div 里
4. 激活规则(activeRule)
决定什么时候显示哪个子应用:
javascript
{
name: 'app-home',
activeRule: '/home', // 当 URL 是 /home 时,激活这个应用
}
就像:
bash
用户访问 www.example.com/home → 显示首页子应用
用户访问 www.example.com/product → 显示商品子应用
五、快速上手:10 分钟搭建第一个微前端应用
🎬 实战教程
我们来做一个简单的例子:主应用 + 2 个 React 子应用
第一步:创建主应用
bash
# 创建主应用目录
mkdir qiankun-demo
cd qiankun-demo
mkdir main-app
cd main-app
# 初始化项目
npm init -y
npm install qiankun react react-dom
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin babel-loader @babel/core @babel/preset-react -D
创建 main-app/index.html:
html
<!DOCTYPE html>
<html>
<head>
<title>qiankun 主应用</title>
<style>
body { margin: 0; font-family: Arial; }
.header { background: #1890ff; color: white; padding: 20px; }
.nav { background: #f0f0f0; padding: 10px; }
.nav a { margin-right: 20px; color: #1890ff; text-decoration: none; }
#container { padding: 20px; }
</style>
</head>
<body>
<div class="header">
<h1>🎯 qiankun 微前端示例</h1>
</div>
<div class="nav">
<a href="#/home">首页</a>
<a href="#/app1">应用1</a>
<a href="#/app2">应用2</a>
</div>
<div id="container">主应用加载中...</div>
<script src="./index.js"></script>
</body>
</html>
创建 main-app/index.js:
javascript
import { registerMicroApps, start } from 'qiankun';
// 注册子应用
registerMicroApps([
{
name: 'app1', // 应用名称
entry: '//localhost:3001', // 应用地址
container: '#container', // 挂载容器
activeRule: '#/app1', // 激活规则
},
{
name: 'app2',
entry: '//localhost:3002',
container: '#container',
activeRule: '#/app2',
},
]);
// 启动 qiankun
start({
prefetch: true, // 预加载
sandbox: true, // 开启沙箱
});
console.log('✅ qiankun 主应用启动成功!');
创建 main-app/webpack.config.js:
javascript
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './index.js',
mode: 'development',
devServer: {
port: 3000,
hot: true,
},
module: {
rules: [
{
test: /\.jsx?$/,
use: 'babel-loader',
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
}),
],
};
第二步:创建子应用 1
bash
# 回到根目录
cd ..
npx create-react-app app1
cd app1
npm install react-app-rewired -D
修改 app1/src/index.js:
javascript
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// 导出生命周期函数(qiankun 需要)
export async function bootstrap() {
console.log('✅ App1 启动');
}
export async function mount(props) {
console.log('✅ App1 挂载', props);
ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root'));
}
export async function unmount(props) {
console.log('✅ App1 卸载');
ReactDOM.unmountComponentAtNode(props.container ? props.container.querySelector('#root') : document.getElementById('root'));
}
// 独立运行时(不在 qiankun 中)
if (!window.__POWERED_BY_QIANKUN__) {
mount({});
}
修改 app1/src/App.js:
javascript
import React from 'react';
function App() {
return (
<div style={{ padding: 20, background: '#e6f7ff', borderRadius: 8 }}>
<h2>🎨 这是子应用 1</h2>
<p>我是用 React 开发的独立应用</p>
<button onClick={() => alert('Hello from App1!')}>点击我</button>
</div>
);
}
export default App;
修改 app1/package.json 的 scripts:
json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build"
}
创建 app1/config-overrides.js:
javascript
module.exports = {
webpack: (config) => {
config.output.library = 'app1';
config.output.libraryTarget = 'umd';
config.output.publicPath = 'http://localhost:3001/';
return config;
},
devServer: (configFunction) => {
return (proxy, allowedHost) => {
const config = configFunction(proxy, allowedHost);
config.port = 3001;
config.headers = {
'Access-Control-Allow-Origin': '*',
};
return config;
};
},
};
第三步:创建子应用 2(同理)
bash
cd ..
npx create-react-app app2
# 按照 app1 的方式配置,只需要把端口改成 3002,名称改成 app2
第四步:启动所有应用
bash
# 终端 1:启动主应用
cd main-app
npm start # 访问 http://localhost:3000
# 终端 2:启动子应用 1
cd app1
npm start # http://localhost:3001
# 终端 3:启动子应用 2
cd app2
npm start # http://localhost:3002
🎉 完成!
现在访问 http://localhost:3000,点击导航栏的链接,可以看到:
- 点击"应用1",加载并显示子应用 1
- 点击"应用2",加载并显示子应用 2
- Header 和导航栏始终存在(主应用提供)
- 只有中间的内容在切换(子应用)
🔍 关键代码解析
1. 主应用的核心代码
javascript
import { registerMicroApps, start } from 'qiankun';
// 第一步:注册子应用
registerMicroApps([
{
name: 'app1', // 唯一标识
entry: '//localhost:3001', // 子应用地址
container: '#container', // 挂载到哪个 DOM
activeRule: '#/app1', // URL 匹配规则
},
]);
// 第二步:启动
start();
就这么简单!主应用的核心就是这几行代码。
2. 子应用的核心代码
javascript
// 导出三个生命周期函数
export async function bootstrap() {
// 应用首次加载时调用,只会调用一次
}
export async function mount(props) {
// 应用挂载时调用,每次激活都会调用
ReactDOM.render(<App />, props.container);
}
export async function unmount(props) {
// 应用卸载时调用
ReactDOM.unmountComponentAtNode(props.container);
}
子应用需要做的就是:导出这三个生命周期函数。
3. webpack 配置关键点
javascript
config.output.library = 'app1'; // 暴露为全局变量
config.output.libraryTarget = 'umd'; // 使用 UMD 格式
config.output.publicPath = 'http://localhost:3001/'; // 资源路径
这样配置后,qiankun 才能正确加载子应用的代码。
六、技术栈兼容性
🎨 qiankun 支持的框架
qiankun 是技术栈无关的,几乎支持所有前端框架!
| 框架 | 支持情况 | 难度 | 官方示例 |
|---|---|---|---|
| React | ✅ 完美支持 | ⭐ 简单 | 有 |
| Vue 2/3 | ✅ 完美支持 | ⭐ 简单 | 有 |
| Angular | ✅ 完美支持 | ⭐⭐ 中等 | 有 |
| 原生 JS | ✅ 完美支持 | ⭐ 简单 | 有 |
| jQuery | ✅ 完美支持 | ⭐ 简单 | 可用 |
| Svelte | ✅ 支持 | ⭐⭐ 中等 | 社区有 |
| Next.js | ⚠️ 部分支持 | ⭐⭐⭐ 困难 | 需要特殊配置 |
| Nuxt.js | ⚠️ 部分支持 | ⭐⭐⭐ 困难 | 需要特殊配置 |
💡 混合使用示例
你可以这样组合:
javascript
registerMicroApps([
{
name: 'react-app', // React 应用
entry: '//localhost:3001',
activeRule: '/react',
},
{
name: 'vue-app', // Vue 应用
entry: '//localhost:3002',
activeRule: '/vue',
},
{
name: 'angular-app', // Angular 应用
entry: '//localhost:3003',
activeRule: '/angular',
},
{
name: 'jquery-app', // jQuery 应用
entry: '//localhost:3004',
activeRule: '/jquery',
},
]);
🌐 不同框架的接入方式
React 接入
javascript
// index.js
export async function mount(props) {
ReactDOM.render(<App />, props.container.querySelector('#root'));
}
Vue 2 接入
javascript
// main.js
export async function mount(props) {
new Vue({
render: h => h(App),
}).$mount(props.container.querySelector('#app'));
}
Vue 3 接入
javascript
// main.js
export async function mount(props) {
const app = createApp(App);
app.mount(props.container.querySelector('#app'));
}
Angular 接入
typescript
// main.ts
export async function mount(props) {
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
}
原生 JS 接入
javascript
// index.js
export async function mount(props) {
props.container.innerHTML = `
<h1>原生 JS 应用</h1>
<button onclick="alert('Hello')">点击我</button>
`;
}
七、进阶知识
🔐 应用隔离
qiankun 提供了两种隔离机制:
1. JavaScript 隔离(沙箱)
问题:子应用可能会污染全局变量
javascript
// 子应用 A
window.userName = 'Alice';
// 子应用 B 也使用了 window.userName
console.log(window.userName); // 冲突!
qiankun 的解决方案:
javascript
start({
sandbox: {
strictStyleIsolation: false, // CSS 严格隔离
experimentalStyleIsolation: true, // CSS 实验性隔离
},
});
qiankun 会创建一个沙箱环境,每个子应用的全局变量互不影响。
原理:使用 Proxy 拦截 window 对象的读写操作
javascript
// 简化版原理
const fakeWindow = new Proxy(window, {
get(target, key) {
// 优先从子应用的作用域获取
return sandbox[key] || target[key];
},
set(target, key, value) {
// 只修改子应用的作用域
sandbox[key] = value;
return true;
},
});
2. CSS 隔离
问题:子应用的样式可能互相影响
css
/* 子应用 A */
.title { color: red; }
/* 子应用 B 也有 .title */
.title { color: blue; }
qiankun 的解决方案:
方案 1:Shadow DOM(严格隔离)
javascript
start({
sandbox: {
strictStyleIsolation: true,
},
});
每个子应用被包裹在 Shadow DOM 中,样式完全隔离。
方案 2:Scoped CSS(推荐)
javascript
start({
sandbox: {
experimentalStyleIsolation: true,
},
});
qiankun 会给子应用的所有样式添加特殊前缀。
css
/* 原始 */
.title { color: red; }
/* 转换后 */
div[data-qiankun="app1"] .title { color: red; }
📡 应用通信
子应用之间如何通信?qiankun 提供了几种方案:
方案 1:通过 initGlobalState(官方推荐)
主应用:
javascript
import { initGlobalState } from 'qiankun';
// 初始化全局状态
const actions = initGlobalState({
user: { name: 'Alice', age: 25 },
theme: 'light',
});
// 监听状态变化
actions.onGlobalStateChange((state, prev) => {
console.log('状态改变了', state, prev);
});
// 修改状态
actions.setGlobalState({ theme: 'dark' });
子应用:
javascript
export async function mount(props) {
// 获取通信方法
props.onGlobalStateChange((state, prev) => {
console.log('子应用收到状态', state);
});
// 修改状态
props.setGlobalState({ user: { name: 'Bob' } });
}
方案 2:通过 props 传递
主应用:
javascript
registerMicroApps([
{
name: 'app1',
entry: '//localhost:3001',
container: '#container',
activeRule: '/app1',
props: {
data: { msg: 'Hello from main app' },
methods: {
sayHello: () => alert('Hello!'),
},
},
},
]);
子应用:
javascript
export async function mount(props) {
console.log(props.data.msg); // 'Hello from main app'
props.methods.sayHello(); // 调用主应用的方法
}
方案 3:通过自定义事件
javascript
// 子应用 A 发送事件
window.dispatchEvent(new CustomEvent('app-message', {
detail: { msg: 'Hello from App A' },
}));
// 子应用 B 接收事件
window.addEventListener('app-message', (e) => {
console.log(e.detail.msg);
});
🚀 性能优化
1. 预加载(Prefetch)
javascript
start({
prefetch: true, // 开启预加载
});
效果:在浏览器空闲时,预先加载其他子应用的资源。
场景:
- 用户在看首页时,偷偷加载商品页的资源
- 当用户点击商品页时,瞬间展示(已经加载好了)
2. 预加载策略
javascript
start({
prefetch: 'all', // 预加载所有子应用
// prefetch: ['app1', 'app2'], // 只预加载指定的应用
// prefetch: (apps) => apps.filter(app => app.name !== 'heavy-app'),
});
3. 手动加载
javascript
import { loadMicroApp } from 'qiankun';
// 手动加载一个子应用
const app = loadMicroApp({
name: 'manual-app',
entry: '//localhost:3001',
container: '#manual-container',
});
// 手动卸载
app.unmount();
使用场景:弹窗、抽屉中显示子应用
4. 公共依赖提取
子应用的 webpack 配置:
javascript
module.exports = {
externals: {
react: 'React',
'react-dom': 'ReactDOM',
antd: 'antd',
},
};
主应用提供依赖:
html
<script src="https://cdn.jsdelivr.net/npm/react@16/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16/umd/react-dom.production.min.js"></script>
好处:子应用不打包 React,体积更小,加载更快。
🛡️ 错误处理
javascript
import { addGlobalUncaughtErrorHandler } from 'qiankun';
// 监听全局错误
addGlobalUncaughtErrorHandler((event) => {
console.error('子应用加载出错', event);
// 显示友好的错误提示
document.querySelector('#container').innerHTML = `
<div style="padding: 20px; text-align: center;">
<h2>😢 应用加载失败</h2>
<p>请刷新页面重试</p>
</div>
`;
});
八、什么时候该用 qiankun
✅ 适合使用 qiankun 的场景
1. 大型企业应用
diff
特点:
- 多个团队(5+ 个团队)
- 功能模块多(10+ 个模块)
- 需要长期维护(3+ 年)
举例:
- 企业管理系统(ERP、CRM)
- 电商后台管理
- 大型运营平台
2. 遗留系统改造
diff
场景:
- 老系统用 jQuery 写的,想用 React 写新功能
- 不想全部重构(太贵、风险大)
- 想逐步迁移
方案:
- 老系统作为子应用
- 新功能用新技术栈开发
- 逐步替换老系统
3. 多项目整合
diff
场景:
- 公司有多个独立的系统(订单系统、库存系统、财务系统)
- 用户需要在不同系统间切换
- 想统一入口
方案:
- 创建一个主应用作为统一入口
- 各个系统作为子应用
- 一个 URL 访问所有系统
4. 技术栈迁移
diff
场景:
- 想从 Vue 2 升级到 Vue 3
- 又不想一次性改完(太累、风险大)
方案:
- Vue 2 项目作为子应用
- 新功能用 Vue 3 开发
- 逐步迁移
❌ 不适合使用 qiankun 的场景
1. 小型项目
diff
特点:
- 1-2 个开发人员
- 功能简单(<10 个页面)
- 代码量少(<10000 行)
原因:
- 微前端架构增加了复杂度
- 得不偿失
- 单体应用更简单
2. 初创项目
diff
特点:
- 刚开始做,不确定会做多大
- 需求变化快
- 追求快速迭代
原因:
- 过早优化
- 增加学习成本
- 先做起来再说
3. 性能要求极高的应用
diff
特点:
- 追求极致性能(如游戏)
- 需要毫秒级响应
原因:
- 微前端会增加一些开销
- 应用加载、切换需要时间
- 单体应用性能更好
4. 纯展示型网站
diff
特点:
- 官网、博客、文档站
- 没有复杂的交互
- 内容为主
原因:
- 不需要复杂架构
- 静态生成(Next.js、Gatsby)更合适
- SEO 也更好
📊 决策树
markdown
是否使用 qiankun?
START
↓
项目有 5+ 个团队?
├─ 是 → 考虑使用 ✅
└─ 否
↓
有遗留系统需要改造?
├─ 是 → 考虑使用 ✅
└─ 否
↓
需要整合多个独立系统?
├─ 是 → 考虑使用 ✅
└─ 否
↓
项目代码量 > 50000 行?
├─ 是 → 考虑使用 ✅
└─ 否 → 不建议使用 ❌
九、常见问题和解决方案
❓ FAQ
Q1: 子应用加载不出来?
可能原因:
- 跨域问题
- webpack 配置不对
- 生命周期函数没导出
解决方案:
检查 1:子应用是否允许跨域
javascript
// webpack.config.js
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
}
检查 2:webpack 配置
javascript
output: {
library: 'appName', // ✅ 必须设置
libraryTarget: 'umd', // ✅ 必须设置
publicPath: 'http://localhost:3001/', // ✅ 必须设置
}
检查 3:生命周期函数
javascript
// ✅ 正确:使用 export
export async function mount() {}
// ❌ 错误:没有 export
async function mount() {}
Q2: 样式相互影响怎么办?
解决方案 1:开启 CSS 隔离
javascript
start({
sandbox: {
experimentalStyleIsolation: true,
},
});
解决方案 2:使用 CSS Modules
javascript
// App.module.css
.title { color: red; }
// App.js
import styles from './App.module.css';
<div className={styles.title}>标题</div>
解决方案 3:使用 CSS-in-JS
javascript
import styled from 'styled-components';
const Title = styled.h1`
color: red;
`;
Q3: 子应用能独立访问吗?
可以!
javascript
// 子应用的 index.js
if (!window.__POWERED_BY_QIANKUN__) {
// 不在 qiankun 环境中,独立运行
mount({});
}
这样配置后:
- 在 qiankun 中:作为子应用运行
- 单独访问:作为独立应用运行
Q4: 如何调试?
方法 1:Chrome DevTools
javascript
// 主应用
console.log('主应用加载子应用', appName);
// 子应用
export async function mount(props) {
console.log('子应用被挂载', props);
}
方法 2:使用 qiankun 的监听钩子
javascript
registerMicroApps(apps, {
beforeLoad: (app) => console.log('加载前', app),
beforeMount: (app) => console.log('挂载前', app),
afterMount: (app) => console.log('挂载后', app),
beforeUnmount: (app) => console.log('卸载前', app),
afterUnmount: (app) => console.log('卸载后', app),
});
方法 3:使用 React DevTools / Vue DevTools
每个子应用可以单独使用自己框架的开发工具。
Q5: 性能怎么样?
对比:
| 指标 | 单体应用 | qiankun 微前端 |
|---|---|---|
| 首次加载 | 慢(加载所有代码) | 快(只加载主应用) |
| 切换页面 | 快(已加载) | 中等(首次需加载子应用) |
| 内存占用 | 高(所有代码在内存) | 低(按需加载) |
| 开发构建 | 慢(项目大) | 快(项目拆分了) |
优化建议:
- 开启预加载
- 提取公共依赖
- 使用 CDN
Q6: 子应用之间能跳转吗?
可以!
方法 1:使用 history API
javascript
// 在子应用 A 中跳转到子应用 B
history.push('/app-b/home');
方法 2:使用主应用提供的方法
javascript
// 主应用
const props = {
navigate: (path) => history.push(path),
};
// 子应用
export async function mount(props) {
props.navigate('/app-b/home');
}
十、学习路线图
🎯 入门阶段(1-2 周)
第一步:理解概念
- 什么是微前端
- 为什么需要微前端
- qiankun 的基本原理
第二步:动手实践
- 跟着官方文档走一遍
- 创建一个主应用 + 2 个子应用
- 实现路由切换
第三步:理解配置
- webpack 配置(library、libraryTarget)
- 生命周期函数(bootstrap、mount、unmount)
- 激活规则(activeRule)
推荐资源:
🚀 进阶阶段(2-4 周)
第一步:深入特性
- 应用隔离(JS 沙箱、CSS 隔离)
- 应用通信(initGlobalState)
- 预加载(prefetch)
第二步:接入不同框架
- React 应用接入
- Vue 应用接入
- Angular 应用接入
第三步:解决实际问题
- 解决跨域问题
- 解决样式冲突
- 优化加载性能
推荐资源:
🏆 高级阶段(1-2 个月)
第一步:深入源码
- 阅读 qiankun 源码
- 理解沙箱实现原理
- 理解应用加载机制
第二步:生产环境实践
- 部署策略
- 监控和错误处理
- 性能优化
第三步:架构设计
- 设计合理的应用拆分
- 设计统一的规范
- 设计通信机制
推荐资源:
📚 推荐阅读
文章:
视频:
- B 站搜索:"qiankun 微前端教程"
- YouTube 搜索:"qiankun micro frontend"
源码:
🎓 总结
核心要点回顾
1. qiankun 是什么?
- 阿里开源的微前端框架
- 用于将大应用拆分成多个小应用
- 技术栈无关,支持 React、Vue、Angular 等
2. 为什么用 qiankun?
- 团队协作更容易(独立开发、独立部署)
- 技术栈更灵活(可以混用)
- 风险更可控(一个应用挂了不影响其他)
- 性能更好(按需加载)
3. 怎么用 qiankun?
javascript
// 主应用
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([{ name, entry, container, activeRule }]);
start();
// 子应用
export async function bootstrap() {}
export async function mount(props) {}
export async function unmount(props) {}
4. 什么时候用 qiankun?
- ✅ 大型项目(多团队、多模块)
- ✅ 遗留系统改造
- ✅ 多项目整合
- ❌ 小型项目(过度设计)
- ❌ 初创项目(过早优化)
🎯 一句话总结
qiankun 就像一个剧院管理系统,让不同的剧目(子应用)可以在同一个舞台(主应用)上轮流表演,互不干扰,按需上场。
💡 最后的建议
-
不要为了微前端而微前端
- 先评估是否真的需要
- 简单场景用简单方案
-
从小做起
- 先做一个简单的 demo
- 验证可行性
- 再逐步推广
-
制定规范
- 统一的命名规范
- 统一的通信方式
- 统一的错误处理
-
持续优化
- 监控性能
- 收集反馈
- 不断改进
🚀 下一步
现在就开始:
bash
# 1. 创建你的第一个微前端应用
mkdir my-first-qiankun
cd my-first-qiankun
# 2. 阅读官方文档
open https://qiankun.umijs.org/
# 3. 查看示例代码
git clone https://github.com/umijs/qiankun.git
cd qiankun/examples
# 4. 动手实践
npm install
npm start
记住:
- 💪 学习最好的方式是动手实践
- 🤔 遇到问题多思考、多查文档
- 📖 多看优秀的开源项目
- 🔄 持续迭代、不断优化
祝你学习愉快!加油!🎉
有任何问题,欢迎:
- 查看 qiankun 官方文档
- 提 GitHub Issue
- 在评论区提问