摘要
- Qiankun 是基于 single-spa 封装的微前端框架,解决子应用的加载/卸载、样式与 JS 隔离、应用通信等问题,适合多团队、大型项目的平滑拆分。
- 核心实现要点:HTML Entry(import-html-entry)解析资源并注入;JS 沙箱(Proxy / 快照)避免全局污染;样式隔离(Shadow DOM / 运行时重写)保证 CSS 不互相影响。
- 落地建议:用
prefetchApps做智能预加载,基座统一 external 公共依赖或使用 Module Federation 做共享,Vite 集成需用专门插件。
一、为什么要选 Qiankun?(场景与价值)
微前端不是为“技术玩具”而生,而是为以下工程问题服务:
- 大型前端单体仓库导致 多人协作冲突、构建链臃肿。
- 需要对老项目做 渐进式重构/迭代(不同技术栈并存)。
- 要实现 子应用独立部署/灰度/回滚,降低整体风险。
Qiankun 把这些问题工程化:子应用独立构建,基座负责调度与聚合。其成熟生态、丰富 API 和生命周期使其成为企业级微前端的首选之一。
二、核心机制拆解(带底层实现思路)
1) HTML Entry:把子应用当“页面”来加载
Qiankun 的加载入口不是一个 JS 文件拼接,而是抓取子应用的 index.html,解析其中的 <link>、<script> 等资源,再动态注入到基座页面中。这个工作由 import-html-entry 完成。
优点:子应用能像独立页面那样工作;
缺点:需要处理跨域、资源基址等问题。
2) JS 沙箱:如何保证全局不污染?
- Proxy 沙箱:对
window的读写通过 Proxy 重定向到子应用私有对象,避免污染宿主全局。 - 快照沙箱:进入子应用前保存全局状态,退出后恢复。
两者结合,既保证兼容性,也兼顾性能。
3) 样式隔离:Shadow DOM 与运行时重写
- Strict 样式隔离:基于 Shadow DOM,浏览器原生隔离。
- 运行时重写(experimentalStyleIsolation):运行时给 CSS 选择器加作用域前缀。
4) 生命周期:bootstrap / mount / unmount / update
子应用需暴露一组生命周期函数,基座在适当时机调用。这个设计借鉴 single-spa,并扩展了通信能力(props、initGlobalState 等)。
三、实战:Vite + Qiankun(最小可运行模版)
基座(主应用)示例
// base/src/main.tsx
import { registerMicroApps, start, prefetchApps, initGlobalState } from 'qiankun';
import { createRoot } from 'react-dom/client';
import App from './App';
registerMicroApps([
{
name: 'sub-vite-app',
entry: 'http://localhost:7300',
container: '#subapp-container',
activeRule: '/sub-vite',
},
]);
prefetchApps([{ name: 'sub-vite-app', entry: 'http://localhost:7300' }]);
const state = initGlobalState({ user: null });
start();
createRoot(document.getElementById('root')!).render(<App />);
(基座 HTML 里,如果子应用做了 external 化,需要注入 React/ReactDOM 的 CDN UMD 脚本。)
Vite 子应用(最小入口)示例
// sub-vite-app/src/main.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
let root: ReturnType<typeof createRoot> | null = null;
function render(container?: HTMLElement) {
const el = container ? container.querySelector('#root') : document.getElementById('root');
root = createRoot(el!);
root.render(<App />);
}
if (!(window as any).__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {}
export async function mount(props: any) {
render(props.container);
}
export async function unmount() {
root?.unmount();
}
Vite 子应用打包配置(external 化 React 示例)
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
base: './',
build: {
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: { react: 'React', 'react-dom': 'ReactDOM' },
format: 'umd' // 根据接入方式,可选 iife/umd;若保留 ESM,需要搭配特定 plugin
}
}
},
server: { port: 7300, cors: true }
});
提示:如果你不想改动很多 build 配置,使用 vite-plugin-qiankun 可以简化接入流程。
四、性能优化与资源共享(实战策略)
1) 预加载(prefetch / prefetchApps)
基座可以提前拉取常访问的子应用资源,缩短用户点击后的等待时间。prefetchApps 是 qiankun 提供的开箱即用策略,也可以配合流量埋点做智能预加载(按用户习惯预加载)
// 例:只预加载高频访问子应用
prefetchApps([
{ name: 'sub-vite-app', entry: 'http://localhost:7300' }
]);
2) 依赖 external 化(或 Module Federation)
- External 化:在子应用 build 时把 React/Vue 等框架标为外部依赖,由基座统一通过 CDN/基座打包注入。好处是节省重复下载、减小子应用包体。风险是需要强制保证版本一致。npm
- Module Federation(Webpack 5) :更灵活的共享机制,支持运行时共享与版本协商,适合统一使用 webpack 的团队。若项目里同时使用 webpack 与 Rspack,Module Federation 是优先级较高的共享方案。
3) 静态资源缓存与 CDN
- 子应用静态资源放 CDN,配合合理 Cache-Control;对经常访问的资源可以设置更长 cache 或者使用 service worker 做离线缓存。
五、常见坑、调试与落地建议
常见坑与解决
- 资源路径与跨域:子应用 ESM 模式下资源请求的 origin 可能会被基座劫持,导致静态资源 404。解决:给子应用正确的
base,或让import-html-entry能正确处理资源基址。Stack Overflow - 样式隔离未生效:
strictStyleIsolation与experimentalStyleIsolation有差别,部分插件/版本下有已知问题,务必在目标浏览器与业务场景下充分验证。qiankun.umijs.org+1 - Vite HMR 与基座冲突:本地开发时子应用 dev server 端口、CORS、HMR 配置需要手动调优或使用社区插件以保证调试体验。npmGitHub
- 多版本 React/Vue 报错(尤其 hooks 报错) :务必统一 runtime 依赖版本或做严格隔离(external / Module Federation)。webpack
调试技巧
- 在子应用的
mount/unmount中加入日志与指标上报,验证加载/卸载是否执行并且资源被释放。 - 使用浏览器 DevTools 的全局搜索来确认
window下的全局变量是否被正确隔离或还原。 - 在基座开启
addGlobalUncaughtErrorHandler捕获和定位子应用错误。
六、参考资料(延伸阅读)
- Qiankun 官方网站与文档。qiankun.umijs.org
- Qiankun GitHub 仓库(实现、Issue、PR 可看源码与设计演进)。GitHub
import-html-entry(解析 HTML Entry 的实现包)。npm- Qiankun 教程(prefetch、生命周期、路由选择等)。qiankun.umijs.org
- Vite 社区的 vite-plugin-qiankun / 兼容插件(调试与 build 辅助)。npmGitHub
- Webpack Module Federation(作为依赖共享的对比方案)