跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScriptNode.js大前端

前端微前端架构:告别巨石应用

大型单体前端应用面临的构建慢、维护难等问题,介绍了三种主流的微前端解决方案。通过对比 Module Federation、Single-SPA 和 Qiankun 的实现方式,展示了如何将巨石应用拆分为独立微应用,以提升团队协作效率和构建速度。方案涵盖 Webpack 配置及主从应用注册流程,帮助开发者避免应用膨胀。

监控大屏发布于 2026/4/5更新于 2026/10/2596 浏览

引言

问题背景

这应用做得跟巨石似的,想改个功能都得动全身。

本文探讨前端微前端架构。维护一个巨大的单体应用,就像在没有分区的大房子里生活——能住,但乱得要命。

微前端必要性

最近看到一个项目,代码量超过 100 万行,构建时间超过 10 分钟,团队协作困难。在大型项目中,单体架构往往导致开发效率低下。

单体应用弊端
// App.jsx
import React from 'react';
import Header from './components/Header';
import Sidebar from './components/Sidebar';
import Dashboard from './components/Dashboard';
import Users from './components/Users';
import Products from './components/Products';
import Orders from './components/Orders';
import Settings from './components/Settings';

function App() {
  return (
    <div>
      <Header />
      <div>
        <Sidebar />
        
          
          
          
          
          
        
      
    
  );
}

  ;
<main>
<Dashboard />
<Users />
<Products />
<Orders />
<Settings />
</main>
</div>
</div>
export
default
App

点评:这种将所有组件塞进一个大文件的方式,不利于维护和扩展。

主流解决方案

1. Module Federation
// webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      remotes: {
        dashboard: 'dashboard@http://localhost:3001/remoteEntry.js',
        users: 'users@http://localhost:3002/remoteEntry.js',
        products: 'products@http://localhost:3003/remoteEntry.js',
        orders: 'orders@http://localhost:3004/remoteEntry.js',
        settings: 'settings@http://localhost:3005/remoteEntry.js',
      },
      shared: {
        react: {
          singleton: true,
          requiredVersion: '^18.2.0',
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '^18.2.0',
        },
      },
    }),
  ],
};

远程应用配置示例:

// dashboard/webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'dashboard',
      filename: 'remoteEntry.js',
      exposes: {
        './Dashboard': './src/Dashboard',
      },
      shared: {
        react: {
          singleton: true,
          requiredVersion: '^18.2.0',
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '^18.2.0',
        },
      },
    }),
  ],
};

主机应用加载:

// App.jsx
import React, { lazy, Suspense } from 'react';
import Header from './components/Header';
import Sidebar from './components/Sidebar';

const Dashboard = lazy(() => import('dashboard/Dashboard'));
const Users = lazy(() => import('users/Users'));
const Products = lazy(() => import('products/Products'));
const Orders = lazy(() => import('orders/Orders'));
const Settings = lazy(() => import('settings/Settings'));

function App() {
  return (
    <div>
      <Header />
      <div>
        <Sidebar />
        <main>
          <Suspense fallback={<div>加载中...</div>}>
            <Dashboard />
            <Users />
            <Products />
            <Orders />
            <Settings />
          </Suspense>
        </main>
      </div>
    </div>
  );
}

export default App;
2. Single-SPA
// src/registerApplications.js
import { registerApplication, start } from 'single-spa';

registerApplication({
  name: '@my-org/dashboard',
  app: () => import('@my-org/dashboard'),
  activeWhen: (location) => location.pathname.startsWith('/dashboard'),
});

registerApplication({
  name: '@my-org/users',
  app: () => import('@my-org/users'),
  activeWhen: (location) => location.pathname.startsWith('/users'),
});

start();

微应用配置:

// packages/dashboard/src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import singleSpaReact from 'single-spa-react';
import Dashboard from './Dashboard';

const lifecycles = singleSpaReact({
  React,
  ReactDOM,
  rootComponent: Dashboard,
  errorBoundary(err, info, props) {
    return <div>应用出错了</div>;
  },
});

export const bootstrap = lifecycles.bootstrap;
export const mount = lifecycles.mount;
export const unmount = lifecycles.unmount;
3. Qiankun
// src/main.js
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'dashboard',
    entry: '//localhost:3001',
    container: '#micro-app-container',
    activeRule: '/dashboard',
  },
  {
    name: 'users',
    entry: '//localhost:3002',
    container: '#micro-app-container',
    activeRule: '/users',
  },
]);

start();

主应用路由:

// src/App.jsx
import React from 'react';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';

function App() {
  return (
    <Router>
      <div>
        <nav>
          <Link to="/dashboard">仪表盘</Link>
          <Link to="/users">用户</Link>
        </nav>
        <div id="micro-app-container"></div>
      </div>
    </Router>
  );
}

export default App;

微应用生命周期:

// packages/dashboard/src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

let instance = null;

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

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

export async function bootstrap() {
  console.log('dashboard bootstraped');
}

export async function mount(props) {
  console.log('dashboard mounted', props);
  render(props);
}

export async function unmount() {
  console.log('dashboard unmounted');
  instance.unmount();
  instance = null;
}

总结:将应用拆分成多个独立的微应用,团队协作更高效,构建时间更短,有效解决巨石应用的问题。

目录

  1. 引言
  2. 问题背景
  3. 微前端必要性
  4. 单体应用弊端
  5. 主流解决方案
  6. 1. Module Federation
  7. 2. Single-SPA
  8. 3. Qiankun

更多推荐文章

查看全部
  • C++ 基础概念
  • MySQL 数据库基础:概念、架构与核心使用指南
  • Spring Boot 集成 LangChain4j 实战指南
  • Java volatile 关键字解析:底层原理与最佳实践
  • GitOps 核心概念、工作流与工具链详解
  • Dify 接入企业微信群聊机器人配置与集成指南
  • 本地多模态 AI 搜索工具 XiaoyaoSearch 开源实践
  • 钉钉 Webhook 完全指南
  • STL 红黑树(RB-tree)原理与插入操作实现详解
  • Python 转行程序员:决策逻辑与学习路径指南
  • Springer Nature 高影响力图书合集:专业应用计算与计算机科学
  • 红黑树的平衡规则与旋转调整技巧
  • Llama-Factory与PyTorch版本兼容性问题排查手册
  • 基于 MCP 协议的 Claude 智能体天气服务落地示例
  • 归并排序时间复杂度 O(nlogn) 解析:排序链表实现
  • 970. Powerful Integers 题解:C 语言实现
  • OpenClaw 部署方式对比:云端、WSL、Mac 及 Ubuntu 虚拟机
  • HTML 前端游戏项目合集
  • OpenClaw 自定义 Skill 开发实战:实现 Excel 数据批量处理
  • 内网环境下搭建大模型微调平台实战指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online