前端面试提问:常见的微应用实现方式有哪些?
字节三面面试官问到公司项目,我讲了下公司项目使用了qiankun集成vue2和vue3新老框架,带来的一系列问题,以及后续如何重构优化的。
面试官接着问,你还知道哪些框架?与qiankun有什么不同?我提到了wujie,就简单讲了讲。掘金有本前端小册专门讲微应用的原理,可惜我买了只看了三分之一,所以这个问题回答的不够深。现在简单总结下。
一、iframe 嵌套
原理 :利用 <iframe>
标签加载子应用页面,通过原生浏览器隔离特性实现沙箱环境。
优点 :
• 天然隔离性:样式和 JavaScript 完全隔离,避免全局污染。
• 技术栈无关:子应用可独立使用任何技术栈。
缺点 :
• 通信困难:需通过 postMessage
或 URL 参数传递数据,跨域处理复杂。
• 用户体验差:页面刷新导致状态丢失,加载性能较低。
适用场景:简单嵌入独立子页面,对交互要求低的场景(如报表展示)。
示例代码:
- 主应用加载子应用
html
<iframe id="subApp" src="http://child-app.com"></iframe>
- 跨iframe通信
javascript
// 主应用发送消息
document.getElementById('subApp').contentWindow.postMessage({ type: 'UPDATE_DATA' }, '*');
// 子应用接收消息
window.addEventListener('message', (event) => {
if (event.data.type === 'UPDATE_DATA') {
// 处理数据
}
});
二、Web Components 技术
原理 :基于浏览器原生支持的 CustomElement
和 Shadow DOM
,将子应用封装为独立组件。
优点 :
• 原生隔离:通过 Shadow DOM 实现样式和 DOM 隔离。
• 标准化:无需依赖框架,浏览器原生支持。
缺点 :
• 生态不足:社区工具链较少,复杂功能需自行实现。
• 兼容性:部分旧浏览器不支持。
适用场景:轻量级跨技术栈集成(如 Vue + React 混合项目)。
示例代码:
- 定义自定义元素
javascript
class MicroApp extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `<style>:host { display: block; }</style>
<div>子应用内容</div>`;
}
}
customElements.define('micro-app', MicroApp);
- 主应用中使用
html
<micro-app></micro-app>
三、路由分发式(Nginx 反向代理/前端路由)
原理 :通过服务端路由(Nginx)或前端路由将不同路径映射到独立子应用。
优点:
- 简单易用:无需复杂配置,子应用完全独立。
- 独立部署:每个子应用可单独发布。
- 可以轻松添加或移除子应用,适应业务的快速变化。
缺点:
- 状态管理难:页面跳转导致全局状态丢失。
- 重复加载:公共依赖无法共享,资源浪费。
- 部署复杂:涉及到多个服务器和路由配置,增加了部署的复杂性。
- 跨域问题:如果子应用与主应用不在同一个服务器上,需要处理跨域请求。
适用场景:多团队维护的简单项目,技术栈统一(如全 Vue应用)。
示例代码:
- Nginx配置反向代理
nginx
# 子应用1路由配置
location /app1 {
proxy_pass http://app1-server;
}
# 子应用2路由配置
location /app2 {
proxy_pass http://app2-server;
}
- 前端路由动态加载(Vue示例)
javascript
import Vue from 'vue';
import VueRouter from 'vue-router';
import Layout from '../views/Layout.vue'; // 主应用的布局组件
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'home',
component: HomeView,
},
{
path: '/subapp',
name: 'subapp',
component: Layout,
children: [
{
path: 'app1',
name: 'app1',
component: () => import('http://subapp-server-url/subapp/app1.vue'), // 子应用的组件
},
{
path: 'app2',
name: 'app2',
component: () => import('http://subapp-server-url/subapp/app2.vue'), // 子应用的组件
},
],
},
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
export default router;
四、框架化方案(Single-SPA/Qiankun/Garfish)
Single-SPA
原理 :通过路由劫持动态加载子应用,提供生命周期管理。
优点 :
• 技术栈自由:支持 React、Vue、Angular 混合开发。
• 生态丰富:插件支持状态管理、依赖共享等。
缺点:配置复杂,需手动处理沙箱和样式隔离。
示例代码
- 主应用配置
javascript
// 主应用入口文件
import { registerApplication, start } from 'single-spa';
// 注册子应用(React 示例)
registerApplication({
name: 'react-app',
app: () => System.import('react-app'), // 加载子应用入口
activeWhen: '/react', // 路由匹配
customProps: { user: 'admin' } // 传递参数
});
start();
- 子应用配置(React 示例)
javascript
// 子应用入口文件
import singleSpaReact from 'single-spa-react';
import React from 'react';
import App from './App';
const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: App,
domElementGetter: () => document.getElementById('react-app')
});
export const { bootstrap, mount, unmount } = lifecycles;
Qiankun
原理 :基于 Single-SPA 封装,内置沙箱和样式隔离。
优点 :
• 开箱即用:简化配置,支持自动沙箱隔离。
• 企业级支持:阿里生态成熟,适合复杂项目。
缺点:依赖冲突需手动解决(如多版本 React)。
示例代码
- 主应用配置(Vue 示例)
javascript
// src/main.js(主应用)
import { createApp } from 'vue';
import { registerMicroApps, start } from 'qiankun';
import App from './App.vue';
const app = createApp(App);
// 注册子应用
registerMicroApps([
{
name: 'sub-app',
entry: '//localhost:3001', // 子应用入口地址
container: '#subapp-container', // 挂载容器
activeRule: '/sub-app', // 路由匹配规则
props: { store: mainStore } // 传递主应用状态
}
]);
start(); // 启动 qiankun
app.mount('#main-app');
- 子应用配置(Vue 示例)
javascript
// src/main.js(子应用)
let router = null;
let instance = null;
function render(props = {}) {
const { container } = props;
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/sub-app' : '/',
mode: 'history',
routes
});
instance = new Vue({ router, store, render: h => h(App) })
.$mount(container ? container.querySelector('#app') : '#app');
}
// 导出生命周期
export async function bootstrap() { /* 初始化逻辑 */ }
export async function mount(props) { render(props); }
export async function unmount() { instance.$destroy(); }
- 主-子应用通信
javascript
// 主应用初始化全局状态
import { initGlobalState } from 'qiankun';
const actions = initGlobalState({ theme: 'light' });
// 子应用监听状态变化
export async function mount(props) {
props.onGlobalStateChange((state, prev) => {
console.log('主应用状态变更:', state);
});
}
Garfish
原理 :字节跳动推出的轻量级框架,支持零配置接入。
优点 :
• 高性能:资源加载优化,首屏速度快。
• 低侵入性:子应用无需改造。
适用场景:快速集成多团队子应用(如中后台系统)。
示例代码:
- 主应用配置
javascript
// 主应用入口文件
import Garfish from '@garfish/core';
Garfish.run({
apps: [
{
name: 'vue-app',
entry: '//localhost:8081', // 子应用入口
activeRule: '/vue-app', // 路由规则
props: { token: 'xxx' } // 传递参数
}
],
sandbox: { strictIsolation: true } // 沙箱隔离
});
- 子应用配置(Vue 示例)
javascript
// 子应用入口文件
import { bootstrap, mount, unmount } from '@garfish/runtime-vue';
import App from './App.vue';
bootstrap(App).then(() => {
mount(App, { dom: '#vue-app' });
});
// 导出生命周期
window.unmount = unmount;
五、EMP(基于 Module Federation 优化)
原理 :对 Webpack 5 Module Federation 二次封装,优化 ESM 模块支持。
优点 :
• 性能更优:减少模块解析开销,动态加载更快。
• 配置简化:提供预设规则,降低使用门槛。
缺点 :依赖 Webpack 5,技术栈受限。
适用场景:需高频共享模块的大型项目(如电商平台)。
示例代码:
- 子应用暴露模块(webpack配置)
javascript
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: { './Button': './src/Button.js' },
shared: ['react', 'react-dom']
});
- 主应用消费模块
javascript
const RemoteButton = React.lazy(() => import('app1/Button'));
function App() {
return (
<React.Suspense fallback="Loading...">
<RemoteButton />
</React.Suspense>
);
}
六、无界(腾讯方案)
原理 :通过 iframe 沙箱 + 代理机制实现子应用隔离。
优点 :
• 极致隔离:安全性高,适合金融、政务场景。
• 多团队协作:支持独立开发部署。
缺点:通信效率较低,需通过代理层中转数据。
示例代码:
- 主应用配置
javascript
import Wujie from 'wujie';
new Wujie({
container: '#app',
apps: [
{ name: 'app1', entry: '//localhost:3001', activeRule: '/app1' }
]
});
- 子应用适配
javascript
if (window.__WUJIE__) {
window.__WUJIE_MOUNT = () => {
Vue.createApp(App).mount('#app');
};
window.__WUJIE_UNMOUNT = () => {
app.unmount();
};
}
总结与选型建议
方案 | 技术栈 | 隔离性 | 适用规模 | 典型场景 |
---|---|---|---|---|
iframe | 任意 | 高 | 小型 | 独立页面嵌入 |
Web Components | 原生 | 中 | 中小型 | 跨框架组件集成 |
Qiankun | 主流框架 | 中高 | 中大型 | 企业级复杂系统 |
Module Federation | Webpack 5 | 低 | 大型 | 模块共享密集型项目 |
Garfish | 主流框架 | 中 | 中小型 | 快速集成多团队应用 |
Nginx反向代理 | Nginx+任意前端框架 | 低 | 中大型 | 企业级应用、统一入口管理、跨域问题解决 |