微前端架构落地实战:qiankun与Module Federation方案对比与选型

微前端架构将大型前端应用拆分为多个独立子应用,各子应用可独立开发、部署和运行。在业务复杂度持续增长的场景下,微前端解决了单页应用体积膈胀、团队协作冲突、技术栈锁定等问题。目前主流方案有基于路由的qiankun和基于Webpack 5 Module Federation两大路线,二者在隔离机制、通信方式、构建工具依赖上各有差异。

微前端架构模式与隔离机制对比

qiankun基于single-spa,通过HTML entry方式加载子应用,运行时将子应用的JS/CSS注入主应用。其核心隔离机制是JS沙箱和CSS隔离:

class ProxySandbox {
    constructor() {
        const fakeWindow = Object.create(null);
        this.proxy = new Proxy(fakeWindow, {
            get(target, key) {
                if (target[key]) return target[key];
                const value = window[key];
                if (typeof value === 'function') {
                    return value.bind(window);
                }
                return value;
            },
            set(target, key, value) {
                target[key] = value;
                return true;
            }
        });
    }
}

Module Federation是Webpack 5原生功能,编译时将模块暴露为远程入口,运行时动态加载远程模块。不依赖额外框架,但要求所有子应用使用Webpack 5。

qiankun主应用与子应用集成

主应用注册子应用:

import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
    {
        name: 'app-vue',
        entry: '//localhost:7101',
        container: '#sub-app-container',
        activeRule: '/vue-app',
        props: { routerBase: '/vue-app', mainStore: window.mainStore }
    },
    {
        name: 'app-react',
        entry: '//localhost:7102',
        container: '#sub-app-container',
        activeRule: '/react-app'
    }
]);

start({ prefetch: true, sandbox: { experimentalStyleIsolation: true } });

Vue 3子应用接入qiankun:

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

let app = null;

function render(props = {}) {
    const { container } = props;
    app = createApp(App);
    app.use(router);
    app.mount(container ? container.querySelector('#app') : '#app');
}

export async function bootstrap() {}
export async function mount(props) { render(props); }
export async function unmount(props) { app.unmount(); app = null; }

if (!window.__POWERED_BY_QIANKUN__) { render(); }

Module Federation远程模块加载

宿主应用配置(Host):

const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
    plugins: [
        new ModuleFederationPlugin({
            name: 'host',
            remotes: {
                remoteVue: 'remoteVue@http://localhost:7102/remoteEntry.js',
                remoteReact: 'remoteReact@http://localhost:7103/remoteEntry.js'
            },
            shared: { vue: { singleton: true }, react: { singleton: true } }
        })
    ]
}

远程应用配置(Remote),暴露组件:

new ModuleFederationPlugin({
    name: 'remoteVue',
    filename: 'remoteEntry.js',
    exposes: {
        './Button': './src/components/Button.vue',
        './Dashboard': './src/views/Dashboard.vue'
    },
    shared: { vue: { singleton: true, eager: false } }
})

在宿主应用中动态加载远程组件:

import { defineAsyncComponent } from 'vue';
const RemoteButton = defineAsyncComponent(() => import('remoteVue/Button'));
const RemoteDashboard = defineAsyncComponent(() => import('remoteVue/Dashboard'));

跨应用通信与状态共享

qiankun使用自定义事件通信:

import { initGlobalState } from 'qiankun';
const actions = initGlobalState({ user: null, theme: 'light' });
actions.onGlobalStateChange((state) => { console.log('收到', state); });
actions.setGlobalState({ user: { name: 'admin', role: 'super' } });

// 子应用接收
export async function mount(props) {
    props.onGlobalStateChange((state) => { console.log(state); });
    props.setGlobalState({ theme: 'dark' });
}

方案选型决策矩阵

维度 qiankun Module Federation
隔离机制 JS沙箱+CSS隔离 共享依赖,无JS沙箱
技术栈 任意技术栈 需Webpack 5+
通信 globalState API 共享模块/事件总线
部署 子应用独立部署 需暴露remoteEntry
调试 子应用独立运行 依赖宿主容器
体积 重复加载依赖 共享依赖减包体

选型建议:技术栈异构(如Vue+React+Angular混用)选qiankun,其JS沙箱和CSS隔离能避免子应用互相污染。技术栈统一且使用Webpack 5的团队选Module Federation,共享依赖减少重复打包体积,编译时类型检查更安全。已有single-spa基础设施的团队迁移qiankun成本低,全新项目可优先考虑Module Federation的原生集成体验。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/wei-qian-duan-jia-gou-luo-di-shi-zhan-qiankun-yu/

(0)
小编小编
上一篇 1小时前
下一篇 1小时前

相关推荐