无界微前端源码解析:项目介绍与环境搭建
无界是腾讯开源的微前端框架,基于 Web Components + iframe 实现原生隔离。本系列将深入源码,揭秘其设计思想。
无界是什么
无界(wujie)是一款基于 Web Components + iframe 的微前端框架,具备:
- 成本低:主应用和子应用适配成本低
- 速度快:子应用首屏和运行速度快
- 原生隔离:CSS 通过 Shadow DOM 隔离,JS 通过 iframe 隔离
- 功能强大:支持保活、嵌套、多应用激活、vite 等
为什么选择 iframe + Web Components
传统方案的问题
| 方案 | CSS 隔离 | JS 隔离 | 问题 |
|---|---|---|---|
| qiankun | 动态样式 | Proxy 沙箱 | 样式泄漏、沙箱逃逸 |
| micro-app | Shadow DOM | Proxy 沙箱 | 沙箱不完整 |
| iframe | 原生隔离 | 原生隔离 | 路由同步、通信困难 |
无界的方案
┌─────────────────────────────────────────────────┐
│ 主应用 │
│ ┌───────────────────────────────────────────┐ │
│ │ Web Component (wujie-app) │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ Shadow DOM (CSS 隔离) │ │ │
│ │ │ │ │ │
│ │ │ 子应用 HTML/CSS 渲染在这里 │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────┐ │
│ │ 隐藏的 iframe (JS 隔离) │ │
│ │ │ │
│ │ 子应用 JS 运行在这里 │ │
│ │ 拥有独立的 window、document、location │ │
│ │ │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
核心思路:
- CSS 隔离:子应用 DOM 渲染在 Shadow DOM 中
- JS 隔离:子应用 JS 运行在 iframe 中
- DOM 代理:iframe 中的 document 操作代理到 Shadow DOM
源码仓库
git clone https://github.com/Tencent/wujie.git
cd wujie
pnpm install
npm run start
项目结构
wujie/
├── packages/
│ ├── wujie-core/ # 核心包
│ │ └── src/
│ │ ├── index.ts # 入口,startApp、preloadApp
│ │ ├── sandbox.ts # 沙箱类 WuJie
│ │ ├── iframe.ts # iframe 创建和 patch
│ │ ├── shadow.ts # Shadow DOM 处理
│ │ ├── proxy.ts # window/document/location 代理
│ │ ├── entry.ts # HTML 解析和资源加载
│ │ ├── sync.ts # 路由同步
│ │ ├── plugin.ts # 插件系统
│ │ └── event.ts # 事件总线
│ │
│ ├── wujie-vue2/ # Vue2 组件
│ ├── wujie-vue3/ # Vue3 组件
│ └── wujie-react/ # React 组件
│
├── examples/ # 示例项目
│ ├── main-vue/ # Vue 主应用
│ ├── main-react/ # React 主应用
│ ├── vue2/ # Vue2 子应用
│ ├── vue3/ # Vue3 子应用
│ └── react17/ # React 子应用
│
└── docs/ # 文档
核心 API
startApp
启动子应用:
import { startApp } from 'wujie';
startApp({
name: 'vue3', // 唯一标识
url: 'http://localhost:7300/', // 子应用地址
el: '#container', // 挂载容器
sync: true, // 路由同步
alive: true, // 保活模式
props: { data: 'hello' }, // 传递给子应用的数据
// 生命周期
beforeLoad: (appWindow) => {},
beforeMount: (appWindow) => {},
afterMount: (appWindow) => {},
beforeUnmount: (appWindow) => {},
afterUnmount: (appWindow) => {},
});
preloadApp
预加载子应用:
import { preloadApp } from 'wujie';
preloadApp({
name: 'vue3',
url: 'http://localhost:7300/',
exec: true, // 是否预执行
});
bus
事件总线:
import { bus } from 'wujie';
// 主应用
bus.$on('event', (data) => console.log(data));
// 子应用
window.$wujie.bus.$emit('event', { msg: 'hello' });
子应用改造
子应用几乎不需要改造,只需导出生命周期函数:
// main.ts
if (window.__POWERED_BY_WUJIE__) {
let instance;
window.__WUJIE_MOUNT = () => {
instance = createApp(App).mount('#app');
};
window.__WUJIE_UNMOUNT = () => {
instance.unmount();
};
} else {
createApp(App).mount('#app');
}
系列文章
本系列将深入分析无界源码:
- 项目介绍(本文)- 了解项目结构和核心概念
- 架构总览 - startApp 启动流程
- 沙箱机制 - iframe 沙箱的创建和 patch
- CSS 隔离 - Shadow DOM 和样式处理
- JS 隔离 - Proxy 代理和作用域隔离
- 路由同步 - 主子应用路由同步机制
- 通信机制 - EventBus 和 props 传递
- 插件系统 - loader 和 hook 机制
调试技巧
1. 启动示例项目
npm run start
会同时启动主应用和多个子应用。
2. 关键断点位置
| 场景 | 文件 | 函数 |
|---|---|---|
| 启动应用 | index.ts | startApp |
| 创建沙箱 | sandbox.ts | constructor |
| 创建 iframe | iframe.ts | iframeGenerator |
| 代理 window | proxy.ts | proxyGenerator |
| 渲染 DOM | shadow.ts | renderTemplateToShadowRoot |
下一步
环境准备好了,下一篇我们将分析 startApp 的完整流程。
📦 源码地址:github.com/Tencent/wuj…
下一篇:无界架构总览