微前端 Micro-App 实践

微前端 出现的历史背景?

微前端的诞生,源于现代前端开发在应对大型、复杂、长周期项目时,传统单体前端架构暴露出的一系列系统性痛点。

  • 代码冲突频繁:多个团队在同一个 Git 仓库中修改代码,合并冲突家常便饭,解冲突消耗大量时间。
  • 发布排队与相互阻塞:团队 A 的功能需要发布,但团队 B 的代码正在集成测试,导致发布窗口互相等待,无法独立上线。
  • 沟通成本高:一次不小心改动可能影响其他团队的业务,导致需要全局回归测试,任何变更都需要跨团队沟通。
  • 构建时间过长:每次开发启动、代码编译、热更新、生产打包都需要处理整个应用,耗时可能从几分钟到半小时,严重降低开发效率。
  • 代码耦合严重:公用组件、工具函数在长期迭代中形成错综复杂的依赖,改一处可能影响多处,技术债务堆积,新人上手困难。
  • 无法渐进式重构:想要升级底层框架(如从 Vue 2 到 Vue 3)或替换构建工具(Webpack 到 Vite),面对整个巨大应用,几乎不可能一次性完成。

微前端(Micro Frontends)

微前端(Micro Frontends)是一种前端架构风格 ,它将一个庞大、复杂的前端应用,按照业务边界或功能域,拆分成多个更小、独立开发、独立部署、独立运行 的子应用。这些子应用可以由不同的团队使用相同或不同的技术栈构建,并通过一个"基座"应用(或称容器、主应用)将它们无缝地组合成一个统一的用户界面。

目前主流的微前端架构,大致可以分为运行时框架构建时方案基础技术三大流派。

运行时框架

  1. qiankun, 基于 single-spa 封装,采用沙箱与动态注入
  2. Micro-App, 基于 Web Components 封装,以标签形式加载
  3. Wujie (无界), Web Components + iframe 增强,利用 iframe 实现 JS 沙箱
  4. Single-SPA, 纯粹的路由级生命周期调度器

构建时方案

  1. Module Federation, Webpack 5 插件,实现运行时模块共享

基础技术

  1. iframe, 浏览器原生机制,创建独立上下文
  2. Web Components, 浏览器原生组件化方案

Micro-App 实现微前端

Micro-App 基于 Web Components 封装,以标签形式加载子应用,原生支持 vite。

类 Web Component

  • 自定义元素 :将子应用的生命周期(加载、渲染、卸载)封装在 micro-app 自定义元素中,用户只需像使用普通 HTML 标签一样声明即可。
  • 虚拟路由系统micro-app 为每个子应用创建独立的路由系统,并与主应用的路由进行隔离。主应用可通过 API 控制子应用跳转,同时子应用的路由信息也会同步到浏览器地址栏,解决了多应用同屏时的路由冲突问题。
  • HTML Entry 机制:基于 HTML 入口进行资源加载,而非 JS 入口。这种机制使子应用的接入成本极低,几乎不需要修改代码,并能保证子应用独立运行与在微前端中表现一致。

基座项目 React19 + vite8

node v26.0.0

bash 复制代码
# 创建基座项目
yarn create vite

# 安装micro-app
yarn add -D @micro-zoe/micro-app

在入口文件修改配置 microapp-base/src/main.tsx

初始化 micro-app

js 复制代码
import microapp from '@micro-zoe/micro-app'
microapp.start()

添加路由 microapp-base/src/App.tsx

js 复制代码
import { useState } from "react";
import "./App.css";
import MyPage from "./pages/SubReact.tsx";
import MyPageVue from "./pages/SubVue.tsx";
import { BrowserRouter, Routes, Route, Link, Outlet } from "react-router-dom";

function App() {
  const [count, setCount] = useState(0);
  return (
    <>
      <BrowserRouter>
        <Routes>
          <Route
            path="/"
            element={
              <div>
                <p>Click me times: {count}</p>
                <Link to="/app1">Click me app 1</Link>
                <button
                  onClick={() => {
                    setCount(count + 1);
                  }}
                >
                  Click me times
                </button>
                <Link to="/app2">Click me app2 </Link>
                <Outlet />
              </div>
            }
          >
            <Route path="/app1/*" element={<MyPage />} />
            <Route path="/app2/*" element={<MyPageVue />} />
          </Route>
        </Routes>
      </BrowserRouter>
    </>
  );
}

export default App;

子应用1(React19 + vite8 )

micro-app通过自定义元素<micro-app>加载子应用

js 复制代码
import React, { useEffect } from "react";
import microApp from "@micro-zoe/micro-app";
export function MyPage() {
  useEffect(() => {
    microApp.setData("app1", {
      user: {
        name: "lili",
      },
    });
  }, []);
  // const ele = React.createElement("micro-app", {
  //   name: "app1",
  //   iframe: true,
  //   url: "http://localhost:5177/react19-vite-app/",
  //   data: {
  //     user: {
  //       name: "lili",
  //     },
  //   },
  // });
  return (
    <div>
      <micro-app
        name="app1"
        iframe
        // 这里的路径后面有 /react19-vite-app,是因为子应用 路由配置了 basename
        url="http://localhost:5177/react19-vite-app/"
        data={{
          user: {
            name: "lili",
          },
        }}
      />
    </div>
  );
}

export default MyPage;

子应用2 (vue3 + vite8)

js 复制代码
import React from "react";

export function MyPage() {
  const ele = React.createElement("micro-app", {
    name: "app1",
    iframe: true,
    url: "http://localhost:5174/yo/",
  });
  return <div>{ele}</div>;
}

export default MyPage;

子应用1 (React19 + vite8 )

js 复制代码
yarn add -D @micro-zoe/micro-app

vite.config.ts 文件配置

micro-app 从主应用通过 fetch 加载子应用的静态资源,由于主应用与子应用的域名不一定相同,所以子应用需要支持跨域。

js 复制代码
server: {
    port: "5177",
    header: {
        "Access-Control-Allow-Origin: "*"
    }
}

初始化

react19-vite-app/src/main.tsx

js 复制代码
import microApp, { EventCenterForMicroApp } from "@micro-zoe/micro-app";

declare global {
  interface Window {
    microApp?: EventCenterForMicroApp;
  }
}
// 启动 micro-app
microApp.start();

子应用1 路由配置了 basename

子应用2 (vue3 + vite6)

js 复制代码
npm i -D @micro-zoe/micro-app --save-dev

vite.config.ts文件配置

js 复制代码
server: {
    port: "5174",
    header: {
       "Access-Control-Allow-Origin: "*"
    }
}

主应用与子应用间的通信

示例 主应用发送数据,子应用接收数据

主应用

js 复制代码
import microApp from "@micro-zoe/micro-app";

<button
  onClick={() => {
    // 给app1发送数据数据
    microApp.setData("app1", {
      user: "xxxlili",
    });
  }}
>
  Set data
</button>

子应用 app1

js 复制代码
  <Button
    onClick={() => {
    console.log('xxxwww', window?.microApp?.getData());
    }}
  >
    测试
  </Button>
js 复制代码
import { EventCenterForMicroApp } from "@micro-zoe/micro-app";

declare global {
  interface Window {
    microApp?: EventCenterForMicroApp;
  }
}
js 复制代码
console.log("window.microApp", window?.microApp);

示例 子应用发送数据,主应用接收数据

子应用 app1

js 复制代码
  <Button
    onClick={() => {
      window?.microApp?.dispatch({
        type: "test",
        data: {
          name: "team",
        },
      });
    }}
  >
    发送数据
  </Button>

主应用

js 复制代码
import microApp from "@micro-zoe/micro-app";

<button
  onClick={() => {
    // 给app1发送数据数据
    const data = microApp.getData("app1");
    console.log("收到来自子应用app1的data", data);
  }}
>
  get data
</button>

样式隔离

micro-app 的样式隔离核心机制是 Scoped CSS ,即通过为子应用的每个样式规则 动态添加带有应用特定 name 属性的前缀 ,来将其作用域限制在对应的 <micro-app> 标签内。

工作原理 :当一个子应用被加载和渲染时,micro-app 会拦截其注入页面的所有 <style> 标签,并执行"CSS 规则重写"。系统会重写每条CSS规则的选择器,为它们加上一个前缀。

示例 指定子应用禁用样式隔离

设置 disableScopecss='

js 复制代码
  <micro-app
    name="app1"
    iframe
    disableScopecss
    url="http://localhost:5177/react19-vite-app/"
    data={{
      user: {
        name: "lili",
      },
    }}
  />

最后

  1. Micro-App
相关推荐
Devin~Y2 小时前
从Spring Boot到AI Agent:大厂Java微服务面试三轮实战问答解析
java·spring boot·redis·spring cloud·微服务·ai·kafka
牧羊狼的狼3 小时前
基于阿里云落地SpringCloudAlibaba云原生微服务:从部署、CI/CD到性能调优、线上排障全体系实战
阿里云·微服务·云原生
weelinking12 小时前
【产品】12_接入数据库——让数据永久保存
jvm·数据库·python·react.js·数据挖掘·前端框架·产品经理
weixin_3975740918 小时前
AgentRAG与ReAct推理链:从检索增强到推理增强
前端·react.js·前端框架
阿里云云原生19 小时前
阿里云微服务引擎 MSE 及 API 网关 2026 年 5 月产品动态
微服务
初心丨哈士奇1 天前
用 AI 自动生成前端代码影响范围报告:从 CI 到测试用例
ci/cd·aigc·前端工程化
WebInfra1 天前
TanStack Start 框架正式支持 Rsbuild
前端·javascript·前端框架