微前端架构
概述
微前端将大型前端应用拆分为独立可部署的小应用。
一、方案对比
| 方案 | 实现 | 隔离 | 通信 | 复杂度 |
|---|---|---|---|---|
| iframe | 原生 | 完全 | postMessage | 低 |
| qiankun | single-spa | Sandbox | Actions | 中 |
| Module Federation | Webpack 5 | 无 | 共享模块 | 中 |
| Web Components | 原生 | Shadow DOM | Events | 低 |
二、qiankun
主应用
javascript
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'app1',
entry: '//localhost:3001',
container: '#container',
activeRule: '/app1',
props: { token: 'xxx' }
}
]);
start({ sandbox: { strictStyleIsolation: true } });子应用
javascript
export async function bootstrap() {}
export async function mount(props) {
render(props);
}
export async function unmount() {
destroy();
}
// 独立运行
if (!window.__POWERED_BY_QIANKUN__) {
render();
}沙箱原理
javascript
// Proxy 沙箱 (单例)
class ProxySandbox {
constructor() {
this.modifiedPropsMap = new Map();
this.proxy = new Proxy(window, {
get: (target, key) => {
return this.modifiedPropsMap.get(key) ?? target[key];
},
set: (target, key, value) => {
this.modifiedPropsMap.set(key, value);
return true;
}
});
}
}三、Module Federation
javascript
// host webpack.config.js
new ModuleFederationPlugin({
name: 'host',
remotes: {
app1: 'app1@http://localhost:3001/remoteEntry.js'
}
});
// app1 webpack.config.js
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/Button'
},
shared: ['react', 'react-dom']
});
// 使用
const Button = React.lazy(() => import('app1/Button'));四、通信
javascript
// qiankun Actions
import { initGlobalState } from 'qiankun';
const actions = initGlobalState({ user: null });
actions.onGlobalStateChange((state) => console.log(state));
actions.setGlobalState({ user: { name: 'test' } });
// Custom Event
window.dispatchEvent(new CustomEvent('micro-event', { detail: {} }));
window.addEventListener('micro-event', (e) => console.log(e.detail));面试高频题
Q1: 微前端适用场景?
遗留系统改造、多团队协作、技术栈多样化。
Q2: qiankun 沙箱原理?
Proxy 代理 window,记录修改,卸载时恢复。
Q3: 样式隔离方案?
Shadow DOM、CSS Modules、命名空间、动态样式表切换。