qiankun 微前端完全入门指南 - 从零到精通

一篇文章搞懂 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

会遇到的问题

  1. 协作困难 😫

    • 4 个团队改同一个代码仓库
    • Git 冲突不断
    • 一个人改的代码可能影响到别人
  2. 部署困难 😰

    • 营销团队想更新首页,必须重新部署整个应用
    • 其他团队的代码也被迫重新部署
    • 一旦有 bug,整个网站都挂了
  3. 技术栈固化 😓

    • 整个项目都得用 React,想用 Vue 不行
    • 想升级 React 版本,所有代码都得测一遍
  4. 编译越来越慢 🐌

    • 代码越来越多,打包要 10 分钟
    • 改一行代码,等 10 分钟才能看到效果

💡 微前端的解决方案

把一个大应用拆分成多个小应用,每个小应用独立运行

复制代码
主应用(基座)
├── 首页子应用(独立项目)
├── 商品子应用(独立项目)
├── 购物车子应用(独立项目)
└── 用户中心子应用(独立项目)

就像:

  • 传统应用:一个巨大的 Word 文档,所有内容都在里面
  • 微前端:一个文件夹,里面有多个独立的 Word 文档,需要时打开相应的文档

🎯 微前端的核心思想

"将前端应用拆解为一些更小、更简单的能够独立开发、测试、部署的小应用,然后再由主应用来加载这些小应用"

二、什么是 qiankun

🏛️ qiankun 简介

qiankun(乾坤) 是阿里巴巴开源的微前端框架,基于 single-spa 封装。

🎭 形象比喻

把 qiankun 想象成一个智能剧院

css 复制代码
┌─────────────────────────────────────────┐
│          qiankun 剧院(主应用)           │
│  ┌────────────────────────────────┐    │
│  │      舞台(容器 div)            │    │
│  │  ┌──────────────────────┐      │    │
│  │  │  正在表演的剧目        │      │    │
│  │  │  (当前激活的子应用)   │      │    │
│  │  └──────────────────────┘      │    │
│  └────────────────────────────────┘    │
│                                         │
│  剧目清单:                              │
│  ☐ 话剧(React 应用)                    │
│  ☑ 歌剧(Vue 应用) ← 正在播放           │
│  ☐ 舞剧(Angular 应用)                  │
│  ☐ 杂技(原生 JS 应用)                  │
└─────────────────────────────────────────┘
  • 主应用 = 剧院本身(提供舞台、灯光、座位)
  • 子应用 = 不同的演出剧目(独立制作、独立演出)
  • qiankun = 剧院的管理系统(决定什么时候演什么剧)

🔧 qiankun 的核心能力

  1. 应用加载 - 能加载各种前端应用
  2. 应用隔离 - 保证应用之间不互相干扰
  3. 应用通信 - 让应用之间能交流
  4. 生命周期管理 - 控制应用的启动、运行、卸载

三、为什么要用 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: 子应用加载不出来?

可能原因

  1. 跨域问题
  2. webpack 配置不对
  3. 生命周期函数没导出

解决方案

检查 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 就像一个剧院管理系统,让不同的剧目(子应用)可以在同一个舞台(主应用)上轮流表演,互不干扰,按需上场。

💡 最后的建议

  1. 不要为了微前端而微前端

    • 先评估是否真的需要
    • 简单场景用简单方案
  2. 从小做起

    • 先做一个简单的 demo
    • 验证可行性
    • 再逐步推广
  3. 制定规范

    • 统一的命名规范
    • 统一的通信方式
    • 统一的错误处理
  4. 持续优化

    • 监控性能
    • 收集反馈
    • 不断改进

🚀 下一步

现在就开始

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

记住

  • 💪 学习最好的方式是动手实践
  • 🤔 遇到问题多思考、多查文档
  • 📖 多看优秀的开源项目
  • 🔄 持续迭代、不断优化

祝你学习愉快!加油!🎉

有任何问题,欢迎:

相关推荐
HuangYongbiao6 小时前
Rspack Tree-Shaking 原理:Rust 让 Tree-Shaking 更彻底?
前端
Boale_H6 小时前
前端流水线连接npm私有仓库
前端·npm·node.js
yoyoma6 小时前
一文搞懂浏览器垃圾回收机制:从原理到面试答题全攻略
前端·javascript
HuWentao6 小时前
如何创建自我更新的通用项目脚本
前端·flutter
不一样的少年_6 小时前
女朋友被链接折磨疯了,我写了个工具一键解救
前端·javascript·浏览器
Zyx20076 小时前
CSS 超级武器:Stylus 与 Flexbox 强强联手,打造极致响应式动画界面(上篇)
前端·css
烛阴6 小时前
超越面向对象:用函数式思维重塑你的Lua代码
前端·lua
微知语7 小时前
Cell 与 RefCell:Rust 内部可变性的双生子解析
java·前端·rust
雨过天晴而后无语7 小时前
Windchill10+html使用Lightbox轻量化wizard的配置
java·前端·html