從0到1落地微前端架構 001【學習筆記】

微前端

js 隔離
css 隔離
元素隔離
生命週期
預加載
數據通信
應用跳轉
多層嵌套


說明

  • 使用的是 Mermaid 的 flowchart 語法,Markdown 渲染器如 Typora、VitePress、一些 Git 平臺都支持。
  • 保留了:
  • 基座應用 main-vue3
  • 各子應用:child-nuxt2-homechild-vue2-jobchild-vue3-enterprisechild-react18-about
  • 框架的核心邏輯,如 JS 隔離、樣式隔離、生命週期、應用通信、虛擬路由等
  • 右側的初始化流程

◆ 多種前沿技術棧
◆ 多項目實操,一人分飾幾角
◆ 微前端應用場景、落地方案
◆ 巨石應用開發流程
◆ 架構思維、架構能力
◆ 打造企業級微前端應用

兩個問題

  • 什麼是微前端
  • 背景 屎山代碼(開發、運行、打包,但又不能將其廢掉,還要把需求增量到項目中)【巨石應用】
  • 基本概念 最早出現在 2016 年(借鑑了微服務的架構)
  • 核心思想 容器應用(主應用)子應用(微應用)
  • 使用場景
    • 增量升級 減少衝突 提高效率
    • 靈活性,(技術棧無關)可以使用不同的構建工具
    • 穩定性 各微應用各司其職,聚合平臺
    • 獨立性 獨立開發、測試、部署
  • iframe single-spa qiankun micro-app
    • <iframe src="https://www.example.com" sandbox></iframe> 簡單易用,天然沙箱(完全隔離),隔離太完美,刷新即丟失(白屏時間長加載速度慢)
  • single-spa 是最早的微前端框架(單頁面微前端模式),在基座上維護一個基座路由表,微前端框架鼻祖,改造成本大,沙箱不完美,應用通信能力差(單頁面),不支持 esmodule,所以也不支持 vite

    ```js
    // 1. 註冊
    // 2. 加載
    import { registerApplication } from 'single-spa';

    registerApplication({
    name: 'app',
    app: () => {
    loadScripts('./chunk-a.js');
    loadScripts('./chunk-b.js');
    return loadScripts('./entry.js');
    },
    });

    singleSpa.start();
    ```

  • Qiankun 基本 single-spa 也有提升

    • 它是通過 html entry
    • 更完備的沙箱方案
    • 適配成本高,同樣對基座和子應用做一些改動,不支持 vite
  • Micro-app 京東技術團隊

    • 低侵入性(適配成本低),開箱即用
    • 文檔易讀
    • 更好的兼容性(支持 webpack,vite)
  • 爲什麼要學習

現代微前端架構理論

之前通過 nginx 配置不同的入口來實現

  1. 團隊自治 跨多團隊合作開發困難
  2. 核心思想 開發、部署成本
  3. 場景落地 系統的漸進性、動態性
graph LR
  主分支[主分支] -->|git倉庫| 分支1
  主分支 --> 分支2
  主分支 --> 分支3
  主分支 --> 分支4

  分支1 --> 團隊1
  團隊1 -->|commit| 趙 --> 錢 --> 孫

  分支2 --> 團隊2
  團隊2 -->|commit| 李 --> 周 --> 吳

  分支3 --> 團隊3
  團隊3 -->|commit| 鄭 --> 王 --> 馮

  分支4 --> 團隊4
  團隊4 -->|commit| 陳 --> 褚 --> 衛

每個倉庫都會進行獨立的部署

graph LR
  主分支[主分支] -->|git倉庫| 團隊1倉庫
  主分支 --> 團隊2倉庫
  主分支 --> 團隊3倉庫
  主分支 --> 團隊4倉庫

  團隊1倉庫 -->|commit| 趙 --> 錢 --> 孫
  團隊2倉庫 -->|commit| 李 --> 周 --> 吳
  團隊3倉庫 -->|commit| 鄭 --> 王 --> 馮
  團隊4倉庫 -->|commit| 陳 --> 褚 --> 衛

獨立開發(每個應用都是一個獨立的應用)

技術選型

微前端框架技術框架無關,我們可以選擇任何前端的技術框架

微前端應用 = 微前端框架 + JS 框架 + UI 框架 + 構建工具

  • 微前端框架:Micro-app
  • JS 框架:Vue3、Vue2、Nuxt2、React18
  • UI 框架:Element-ui、Element-plus
  • 構建工具:Webpack5、Vite4、Vue-cli5

整體架構思路爲 CustomElement + HTMLEntry:

  • micro-app 標籤:上可以設置各種配置,比如開啓 iframe 沙箱、開啓 SSR 模式、開啓 keep-alive 模式、關閉沙箱、數據通信。
  • HTMLEntry:就是以 HTML 文件作爲入口地址進行渲染。

主要功能:

生命週期、環境變量、虛擬路由、js 沙箱、樣式隔離、元素隔離、數據通信等等

生命週期

  • created<micro-app> 標籤初始化後,加載資源前觸發。
  • beforemount:加載資源完成後,開始渲染之前觸發。
  • mounted:子應用渲染結束後觸發。
  • unmount:子應用卸載時觸發。

環境變量

  • __MICRO_APP_PUBLIC_PATH__
  • __MICRO_APP_BASE_ROUTE__

虛擬路由系統

通過虛擬路由系統,我們可以方便地進行導航守衛、跨應用的跳轉,提升開發效率,並且子應用運行在這套虛擬路由系統中,和主應用的路由進行隔離,避免相互影響,如:

  • 主應用控制子應用跳轉
  • 子應用控制主應用跳轉
  • 子應用控制其它子應用跳轉

js 沙箱

確保子應用之間 全局變量/事件不衝突

樣式隔離

確保子應用之間樣式互相不乾擾

.test {
  color: red;
}

/* 轉換爲 */
micro-app[name='xxx'] .test {
  color: red;
}

元素隔離

元素隔離的概念來自 ShadowDom,即 ShadowDom 中的元素可以和外部的元素重複但不會衝突。micro-app 模擬實現了類似 ShadowDom 的功能:

  • 元素不會逃離 <micro-app> 元素邊界。
  • 子應用只能對自身的元素進行增、刪、改、查的操作。

通信

主子通信
子應用全局通信

其它能力

預加載,緩存等

系統架構

graph TD
    A[基座應用 main-vue3] -->|登錄| B[micro-app 框架邏輯]
    B --> C[JS 隔離]
    B --> D[樣式隔離]
    B --> E[元素隔離]
    B --> F[生命週期]
    B --> G[應用通信]
    B --> H[虛擬路由系統]
    B --> I[預加載]
    B --> J[資源地址補全]
    B --> K[...]

    B --> L[子應用 child-nuxt2-home]
    B --> M[子應用 child-vue2-job]
    B --> N[子應用 child-vue3-enterprise]
    B --> O[子應用 child-react18-about]

    P[初始化 micro-app] --> Q[嵌入子應用]
    Q --> R[通用組件]
    R --> S[統一鑑權]

1-1.png

4 個子應用和 1 個主應用

nvm 對 nodejs 版本管理

什麼是 nvm

nvm 是 node 的包管理工具,它可以幫助我們在不同的項目環境中使用不同的 node 版本,所以在啓用不同項目時,可能遇到報錯。

例如:如果我們本次教程的所使用到的 nuxt3 和 vite 搭建不同的項目,就是依賴於不同的 node 環境。

  • nuxt3 依賴的 node 版本 >= v14.16.0
  • vite >= 12.0.0

所以我們的電腦裏需要配置兩種 node,在我們當前的項目中使用對應的 node 環境,如何使得不同版本的 node 共存系統呢,請看下文。

nvm 的安裝

下載

下載,選擇某一個版本的 nvm,安裝 nvm-setup.zip。

主子應用的功能分配

主應用:基座(main-vue3)

功能:拿到 token 然後派發到各個子應用

  • 登錄 /api/auth/login POST
  • 登出 /api/auth/logout POST

接口說明:

  • 登錄:傳入賬號和密碼,返回 token。
  • 登出:清除 token。
// POST /api/auth/login
{
  "username": "test",
  "password": "123456"
}
// 返回
{
  "token": "mocked-token-123"
}

子應用:首頁(child-nuxt2-home)

功能:

  • 首頁列表 /api/home/list GET

mock 示例:

// GET /api/home/list
[
  { "id": 1, "title": "首頁內容一" },
  { "id": 2, "title": "首頁內容二" }
]

子應用:找工作(child-vue2-job)

功能:

  • 職位列表 /api/job/list GET
  • 職位詳情 /api/job/detail/:id GET

mock 示例

// GET /api/job/list
[
  { "id": 101, "title": "前端開發", "company": "阿里巴巴" },
  { "id": 102, "title": "後端開發", "company": "騰訊" }
]

// GET /api/job/detail/101
{
  "id": 101,
  "title": "前端開發",
  "description": "負責前端頁面開發",
  "company": "阿里巴巴"
}

子應用:找企業(child-vue3-job)

功能:

  • 企業列表 /api/company/list GET
  • 企業詳情 /api/company/detail/:id GET

mock 示例:

// GET /api/company/list
[
  { "id": 201, "name": "字節跳動", "industry": "互聯網" },
  { "id": 202, "name": "百度", "industry": "AI" }
]

// GET /api/company/detail/201
{
  "id": 201,
  "name": "字節跳動",
  "industry": "互聯網",
  "location": "北京"
}

子應用:關於我們(child-react18-about)

功能:

  • 關於我們 /api/about/info GET

mock 示例:

// GET /api/about/info
{
  "company": "微前端平臺",
  "description": "一個多技術棧集成的企業級系統"
}
  1. Mock Server 工具推薦:
  2. 使用 Mock Service Worker (MSW)(適用於 Vue/React/Nuxt 等)
  3. 或者本地 node server + json-server/mockjs
  4. 接口統一管理:
  5. 每個子應用維護自己的接口配置
  6. 主應用統一配置公共接口(如認證相關)
  7. 前後端聯調方式:
  8. 使用 axios 攔截器統一處理 token
  9. 子應用通過環境變量控制是否啓用 mock

實現基座應用

目前使用 node(v18.20.6)

pnpm create vue@latest
# ts
# pina
# vue-router
cd micro-main-vue3
pnpm install
pnpm dev
# 安裝相關依賴 router
# /router目錄下放置路由
# /views目錄下放視圖
# /views/child目錄下放子應用路由
# /views/main目錄下放基座應用的視圖
# 安裝element plus
  1. 基座應用上集成 microapp
@micro-zoe/micro-app
  1. 項目的 main.js 中引入它並且初始它,具體實現看去 github 上看
import microApp from '@micro-zoe/micro-app';

microApp.start();

使用 nust2 實現首頁應用(child-nuxt3-home)

它是基於 vue3 的服務端渲染項目(我學習的版本使用的是 vue3 我用的也是 nuxt3)

pnpm create nuxt-app child-nuxt3-home

功能開發完成後,集成到基座應用中,使用<micro-app name="child-app" url="http://localhost:3000/child-home"></micro-app>, 但它會提示跨域問題,我們可以在 chrome 中添加了一個插件來測試允許跨域,插件名:Allow CORS: Access-Control-Allow-Origin

使用 vue2 構建一個子應用找工作(micro-child-vue2-job)

micro-child-vue2-job/
├── public/
│ └── index.html
├── src/
│ ├── assets/
│ ├── components/
│ ├── views/
│ ├── App.vue
│ ├── main.js
│ └── router.js
├── .gitignore
├── babel.config.js
├── package.json
└── README.md

vue3 構建一個子應用找企業(micro-child-vue3-enterprise)

2024-04-12

接口 mock 調整及列表數據展示

功能改動

  1. 添加接口代理配置
  2. 新增 .env.development 文件配置環境變量
  3. vue.config.js 中添加代理配置,支持接口轉發
  4. 配置 mock 接口地址:http://127.0.0.1:4523/m1/6202454-5895755-default
  5. 調整職位列表樣式
  6. 移除列表容器背景色
  7. 優化職位卡片樣式
  8. 調整字體大小和顏色
  9. 添加卡片懸停效果
  10. 優化標籤樣式
  11. 完善列表數據展示
  12. 展示職位基本信息(標題、薪資)
  13. 展示公司信息(Logo、名稱、行業)
  14. 展示職位標籤(地點、經驗、學歷)
  15. 展示福利標籤
  16. 展示技能標籤
  17. 添加分頁功能

文件變更

  • 新增文件:
  • .env.development:環境配置文件
  • 修改文件:
  • src/api/findJobApi.js:添加接口調試日誌
  • src/assets/scss/findjob.scss:調整樣式
  • src/utils/request.js:調整請求配置
  • src/views/FindJob.vue:完善列表展示
  • vue.config.js:添加代理配置

接口數據結構

{
  "code": 200,
  "message": "success",
  "data": {
    "list": [
      {
        "jobId": "job-100",
        "jobTitle": "產品經理",
        "enterpriseName": "騰訊科技",
        "enterpriseLogo": "https://logo.clearbit.com/mi.com",
        "industry": "人工智能",
        "jobType": "全職",
        "education": "本科",
        "workCity": "北京市",
        "workExperience": "1年",
        "salaryMin": 10642,
        "salaryMax": 17846,
        "salaryRange": "10642-17846元/月",
        "salaryUnit": "月",
        "welfareTags": ["五險一金", "交通補貼", "加班補助"],
        "skillTags": ["Python", "TensorFlow", "PyTorch"],
        "refreshTimeStr": "2024年4月12日"
      }
    ],
    "total": 25
  }
}

樣式規範

  • 主色調:#4e6ef2
  • 標題文字:16px, #333
  • 薪資文字:16px, #ff6b6b
  • 普通文字:13px, #666
  • 次要文字:12px, #999
  • 標籤樣式:
  • 背景色:#f8f9fc
  • 文字顏色:#666
  • 圓角:2px
  • 卡片樣式:
  • 背景色:#fff
  • 內邊距:24px
  • 圓角:4px
  • 陰影:0 1px 3px rgba(0, 0, 0, 0.02)

創建 react 應用

 npx create-react-app micro-child-react18-about

基於 React 18 的微前端子應用,支持獨立運行和作爲子應用運行。

項目結構

micro-child-react18-about/
├── public/                 # 靜態資源目錄
├── src/                    # 源代碼目錄
│   ├── components/         # 公共組件
│   │   └── Layout/        # 佈局組件
│   ├── pages/             # 頁面組件
│   │   └── About/         # 關於頁面
│   ├── styles/            # 樣式文件
│   │   └── global.scss    # 全局樣式
│   ├── utils/             # 工具函數
│   │   └── request.js     # 請求封裝
│   ├── App.js             # 應用入口組件
│   ├── index.js           # 應用入口文件
│   └── public-path.js     # 微前端環境配置
├── .env                    # 環境變量
├── package.json           # 項目依賴配置
└── README.md              # 項目說明文檔

micro 沙箱體(js 隔離)

  1. new Fuction("return window")()
  2. (0,eval)("window")
  3. window.rawWindow

比如職位類型可能幾個子應該都用到職位類型,我們可以將其提取到基座應該中,另外我們可以在子應用中通過window.__MICRO_APP_PUBLIC_PATH__
如果在主應用中顯示 micro-app 不能識別的警告,但不影響使用我們需要在主應用中添加一些配置,在基座應用中 vite.config.js 中添加

//...
plugins: [
  vue({
    template: {
      compilerOptions: {
        isCustomElement: (tag) => /^micro-app/.test(tag),
      },
    },
  }),
];
// ..

使用基座應用數據的邏輯

mounted() {
  if (window.__MICRO_APP_ENVIRONMENT__) {
    // 微前端環境
    this.jobTypeArr = window.rawWindow.jobTypeArr;
  } else {
    this.jobTypeArr = jobTypeArr;
  }
  // this.getAddressDict();
  // this.searchJobList();
}

樣式隔離(默認開啓)

通過基座應該設置前綴來隔離,通過命名空間來

<el-config-provider namespace="ep">
  <common-header v-if="route.name !== 'login'" />
  <main-container />
  <common-footer v-if="route.name !== 'login'" />
</el-config-provider>

創建一個 scss 文件將

// styles/element/index.scss
// we can add this to custom namespace, default is 'el'
@forward 'element-plus/theme-chalk/src/mixins/config.scss' with (
  $namespace: 'ep'
);
// ...

註釋掉 main 中的引入import 'element-plus/dist/index.css' 換成 scss 文件

在 vite.config 配置中聲明

css: {
  preprocessorOptions: {
    scss: {
      additionalData: `@use "./src/styles/element/index.scss" as *;`,
    },
  },
},

元 s 隔離

shadow dom 元素可以重複,但又不會產生衝突,所有元素都不會逃離micro-app這個邊界

生命週期(micro-app)

可以 start 上配置lifeCycles,也可以在每一個標準上使用@mounted來爲每一個子應該設置

主子通信

micro-app標籤上添加數據

import microApp from '@micro-zoe/micro-app'
const globalData = microApp.getGlobalData()
<micro-app :data="globalData"></micro-app>

在子應用項目中

if (window.__MICRO_APP_ENVIROMENT__) {
  const dataForchild = window.microApp.getData();
  // 獲取數據對象
  const { token } = dataForChild;
  axios.defaults.headers['x-client-token'] = token;
}

也可以使用microApp.setData('childEnterprise',data) 來設置,這個名字要和micro-app的 name 保持一致

子應用向主應用發送數據

if (window.__MICRO_APP_ENVIRONMENT__) {
  window.microApp.dispatch({
    activeIndex: 'job',
  });
}
// 在基座應用中獲取數據
<script setup>
function handleDataChange(e) {
  let { activeIndex } = e.detail.data;
  localStorage.setItem('activeIndex', activeIndex);
}
</script>

<template>
  <div>
    <micro-app
      @datachange="handleDataChange"
      name="childHome"
      url="http://localhost:3000/childHome/"
    ></micro-app>
  </div>
</template>

<style></style>

子應用間通信

在首頁應用點擊搜索,把關鍵字帶入到找工作子應用

  1. 判斷是不是微前端環境
  2. 把數據發給基座
searchIt() {
  let { homeSearchValue } = this;
  if (window.__MICRO_APP_ENVIRONMENT__) {
    window.microApp.setGlobalData({ homeSearchValue });
    const baseRouter = window.microApp.router.getBaseAppRouter();
    baseRouter.push('/main/childJob');
  }
},
// 應用啓動時要註冊其路由信息
microApp.router.setBaseAppRouter(router) //router是基座路由信息
// 在找工作子應用的mounted中把數據拿出來添加到查詢接口的參數中
const globalData = window.microApp.getGlobalData()
if(globalData){

}

主應用跳轉子應用,我們在基座應用的路由中已經處理過了,如何從子應用跳轉到主應用(刷新頁面跳,不刷新頁面跳)

// 1.
window.microApp.location.href = '/main/login';
// 2
// 獲取基座應用的路由然後來設置
const baseRouter = window.microApp.router.getBaseAppRouter();
baseRouter.push('/main/login');

微前端應用的優化

預加載:requestIdleCallback 在瀏覽器不忙的時候把資源加載一下,在基座應用中在 start({})對象中添加屬性prefetchApps

import microApp from '@micro-zoe/micro-app';

microApp.start({
  prefetchApps: [
    {
      name: 'childHome',
      url: 'http://localhost:3000/childHome/',
      level: 3,
    },
    {
      name: 'childJob',
      url: 'http://localhost:8080',
      level: 3,
    },
    {
      name: 'childEnterprise',
      url: 'http://localhost:3002/child/findEnterprise/',
      level: 3,
      iframe: true,
    },
    {
      name: 'childAbout',
      url: 'http://localhost:3003/',
      level: 3,
    },
  ],
});

要和標籤的配置保持一致

配前端的資源共享,加載一次,其它子應用加載時從緩存中獲取

globalAssets 項配置,但這個配置不是很好,可以在 index.html 中給 link 標籤和 script 標籤添加 global 屬性來標識

<link global rel="stylesheet" href="xx.css" />
<script global src="xx.js"></script>

子應用緩存,keep-alive 不會真正的被卸載,加載的生命週期是 afterHide beforeShow afterShow

絲滑轉場

頁面加載動效(或者骨架屏),基座應用加載完之後它消失,注意幾個點 基座應用加載完成前端的 loading, micro-app 加載前後的 loading,及子應用渲染完成前後,還有點是每個子應用的獨立個體的性能優化

優雅上線

這個已經不是我的學習重點了,過一下得了。如需要瞭解移步其它課程的學習

每一個應用單獨打包部署,且集成到基座應用中,生部署子系統應用,然後再部署基座應用

發佈工具

  • Putty
  • Xftp

服務器環境依賴

  • Nodejs 16.11.0
  • Nginx
  • Screen

線上域名

  • localhost
  • 線上域名
  • 📘 統一管理本地和線上 url

發佈線上

🚩 子應用部署

  • Nuxt2 子應用
  • Vue2 子應用
  • Vue3 子應用
  • React18 子應用
  • Gzip 壓縮

🟡 基座應用部署

  • Vue3 主應用

多頁應用

mpa 不同與我們的微前端架構(單一技術架構),不能爲了技術而技術,vue2 實現一個多頁面應用(也不是這個的重點)

主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/4451

(0)
Walker的頭像Walker
上一篇 2026年3月10日 00:00
下一篇 2026年3月8日 15:40

相關推薦

  • Go 工程師體系課 004【學習筆記】

    需求分析 後台管理系統 商品管理 商品列表 商品分類 品牌管理 品牌分類 訂單管理 訂單列表 使用者資訊管理 使用者列表 使用者地址 使用者留言 輪播圖管理 電商系統 登入頁面 首頁 商品搜尋 商品分類導覽 輪播圖展示 推薦商品展示 商品詳情頁 商品圖片展示 商品描述 商品規格選擇 加入購物車 購物車 商品列表 數量調整 刪除商品 結帳功能 使用者中心 訂單中心 我的…

    2025年11月25日
    27600
  • Go 工程師體系課 013【學習筆記】

    訂單事務 先扣庫存 後扣庫存 都會對庫存和訂單都會有影響,所以要使用分散式事務 業務(下單不對付)業務問題 支付成功再扣減(下單了,支付時沒庫存了) 訂單扣減,不支付(訂單超時歸還)【常用方式】 事務和分散式事務 1. 什麼是事務? 事務(Transaction)是資料庫管理系統中的一個重要概念,它是一組資料庫操作的集合,這些操作要麼全部成功執行,要麼全部…

    個人 2025年11月25日
    28700
  • 深入理解ES6 013【學習筆記】

    用模組封裝程式碼 JavaScript 使用「共享一切」的方式載入程式碼,這是該語言中最容易出錯且令人感到困惑的地方。其他語言使用諸如套件(package)之類的概念來定義程式碼作用域。在 ES6 以前,在應用程式的每一個 JavaScript 檔案中定義的一切都共享一個全域作用域。隨著網頁應用程式變得更加複雜,JavaScript 程式碼的使用量也開始增長,這種做法會引起問題,例如命名衝突和安全性問題。ES6 的一個目標是解決作用域問題…

    個人 2025年3月8日
    1.2K00
  • Go工程師體系課 protobuf_guide【學習筆記】

    Protocol Buffers 入門指南 1. 簡介 Protocol Buffers(簡稱 protobuf)是 Google 開發的一種語言無關、平台無關、可擴充的結構化資料序列化機制。與 JSON、XML 等序列化方式相比,protobuf 更小、更快、更簡單。 專案首頁:https://github.com/protocolbuffers/prot…

    個人 2025年11月25日
    1.3K00
  • Nuxt3_掃盲 入門與原理介紹【學習筆記】

    Nuxt 3 入門與原理介紹 💡 什麼是 Nuxt 3? Nuxt 3 是基於 Vue 3 和 Vite 打造的全端前端框架,支援: 伺服器端渲染(SSR) 靜態網站生成(SSG) 單頁應用程式(SPA) 建構全端應用程式(支援 API) Nuxt 3 是 Vue 的「加強版」,幫你簡化專案結構與開發流程。 🔧 核心原理 功能 Nuxt 如何處理 ✅ 頁面路由 自動根…

    個人 2025年4月6日
    2.2K00
簡體中文 繁體中文 English