当前位置: 首页 > news >正文

微前端架构学习笔记

前言

之前遇到过一个需求,有两个项目分别由两个不同的部门负责,不同技术栈,不同代码仓库:

  • A 项目是官网,负责展示产品亮点等信息,有多个入口可以进入 B 项目中的不同页面。
  • B 项目是业务线,负责处理具体的功能,可以跳转到 A 项目中登录/注册等。

现在想在这样跨域的两个项目之间,仅通过两个客户端,如何传递客户从 A 项目中上传的文件,使得 B 项目可以接收文件再处理后续的业务逻辑。

因为并未引入微前端方案,最终通过 传递文件的 DataURL + IndexedDB 的方式来实现。

跑题一点,每个文件都可以生成 DataURL 和 BlobURL,在这篇文章中不展开讲了,之后会更新一篇文章记录两者的使用。

最终决定使用 DataURL 的原因是,涉及到链接跳转的动作,会导致 BlobURL 丢失。

如果引入了微前端的方案,那么这个问题就很好解决,下面将详细记录微前端相关的笔记。


 1.什么是微前端?

        微前端(Micro Frontends)是一种将前端应用程序拆分成多个较小、独立、可管理的部分的架构方法。

图片来源于micro-app官网 

微前端借鉴微服务架构(Micro Services),将一个前端应用程序拆分成多个子应用,子应用可以分别独立开发、测试、部署和维护。

微前端平台

single-spa

将多个独立的单页面应用组合到一个父应用中的微前端框架

特点
  • 无框架限制

        对于 React,可以使用 single-spa-react

        对于 Vue,可以使用 single-spa-vue

        对于 Angular,可以使用 single-spa-angular

  • 可以与其他微前端框架(如 qiankun)结合使用
  • 主应用与子应用无耦合,每个子应用都可以独立加载和卸载
缺点
  • 配置较为繁琐,需要开发者手动管理每个子应用的生命周期和加载

        要求子应用暴露三个生命周期方法(bootstrapmountunmount),并且需要对子应用的入口进行适当的修改。

适用场景
  • 需要多种前端技术栈共存的项目
  • 可以与现有的应用逐步迁移到微前端架构中
以 Vue3.0 为例,借用 single-spa-vue
npm install vue@next single-spa-vue
目录结构
my-micro-frontend/
├── dist/                      # 构建后的输出
├── public/
│   └── index.html             # 主页面,包含单页面应用入口
├── src/
│   ├── main.ts                # 主应用,加载子应用
│   ├── vue-app.ts             # 子应用生命周期方法
│   ├── vue-app.vue            # Vue 3 组件
├── tsconfig.json              # TypeScript 配置
├── webpack.config.js (or vite.config.ts)
└── package.json
配置子应用
// vue-app.vue
<template><div id="app"><h1>Vue 3 Micro Frontend</h1><p>This is a micro frontend app rendered using Vue 3 and Single-spa!</p></div>
</template><script setup lang="ts">
/*** 这个组件通过 single-spa 在主应用中渲染*/
</script>

        在 vue-app.ts 中,使用 singleSpaVue 暴露 bootstrapmountunmount 方法。

// vue-app.ts
import { createApp, App as VueApp } from "vue";
import { singleSpaVue } from "single-spa-vue";
import App from "./App.vue";// 定义 Single-spa 生命周期方法的类型
const vueLifecycles = singleSpaVue({createApp,appOptions: {render: (h: any) => h(App), // 渲染根组件},
});// 暴露 Single-spa 所需的生命周期方法
export const bootstrap: (props: any) => Promise<void> = vueLifecycles.bootstrap;
export const mount: (props: any) => Promise<void> = vueLifecycles.mount;
export const unmount: (props: any) => Promise<void> = vueLifecycles.unmount;
配置主应用

        主应用负责注册子应用并启动 single-spa,不需要直接渲染 Vue 应用。在主应用中不需要手动调用 createApp(App).mount('#app'),都由 single-spa-vue 管理。

// main.ts
import { registerApplication, start } from "single-spa";// 注册 Vue 子应用
registerApplication("vue-app", // 子应用名称() => import("./vue-app.ts"), // 动态导入子应用生命周期方法(location) => location.pathname.startsWith("/vue-app") // 激活条件
);// 启动 single-spa
start();
配置 Webpack 或 Vite
// webpack.config.js
const path = require("path");module.exports = {entry: "./src/main.ts",output: {path: path.resolve(__dirname, "dist"),filename: "bundle.js",publicPath: "/",},resolve: {extensions: [".ts", ".js", ".vue", ".json"],alias: {vue: "vue/dist/vue.esm-bundler.js",},},module: {rules: [{test: /\.ts$/,loader: "ts-loader",exclude: /node_modules/,},{test: /\.vue$/,loader: "vue-loader",},],},plugins: [new (require("vue-loader").VueLoaderPlugin)(),],devServer: {historyApiFallback: true,},
};
// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";export default defineConfig({plugins: [vue()],build: {target: "esnext",outDir: "dist",lib: {entry: "src/vue-app.ts",name: "VueApp",fileName: "vue-app",formats: ["es"],},rollupOptions: {external: ["vue"],},},
});
qiankun

基于 single-spa 的微前端实现库,提供了更易用的 API

特点
  • 无框架限制
  • 支持按需加载子应用,支持懒加载、动态加载
  • 提供沙箱机制,可以隔离不同微前端应用的全局状态
  • 支持使用插件系统来扩展功能
缺点
  • 封装了 single-spa,因此继承了对子应用的生命周期管理
适用场景
  • 适合已有单页面应用架构,并计划迁移或拆分成多个微前端应用的场景
MicroApp

基于 WebComponent 的微前端框架,使用原生浏览器支持的 Web Component 标准来封装和管理微前端应用

特点
  • 将每个微前端应用封装为 Web Component,子应用能够更好地与其他应用隔离
  • Web Component 是原生浏览器技术,MicroApp 不依赖任何前端框架
  • 支持自定义生命周期函数,能精细控制子应用的加载、渲染、销毁等过程
缺点
  • Web Component 在不同浏览器的兼容性可能会存在差异
  • 对开发者来说,需要一定的 Web Component 知识
适用场景
  • 适合希望轻量化的微前端架构,或者不希望依赖第三方框架的场景
  • 对应用的封装性和隔离性有较高要求的场景
Module federation

Webpack 5 引入的一个新特性,允许将一个应用的模块动态加载到另一个应用中。

特点
  • 能够共享模块,比如 React 和 Vue 等常用依赖,避免重复加载
  • 可以按需加载子应用,并支持运行时动态决定要加载哪些模块
  • 不依赖框架,是直接基于 Webpack 的构建系统
缺点
  • 配置复杂,需要对 Webpack 的运行机制有较深入的了解
  • 很少提供封装好的 API,开发者需要更多的手动管理
适用场景
  • 适合已经使用 Webpack 的项目,特别是对微前端的集成要求较高的场景

2.微前端的架构实现方式

1)基于 URL 路由

通过 URL 路由来加载不同的微前端子应用

        假设有一个电商平台,主应用是一个统一的首页展示,而不同的页面(如产品详情页、用户中心、购物车等)分别由不同的子应用负责。

  • 使用主应用中的路由管理器来控制子应用的加载和渲染。
  • 主应用的路由会根据 URL 地址来决定展示哪个子应用的页面。
// 主应用路由配置示例
const routes = [{ path: '/products', component: ProductApp },{ path: '/cart', component: CartApp },{ path: '/user', component: UserApp }
];

2)基于 Web Components

使用 Web Components 技术来将不同的子应用封装成独立的组件。这样可以确保每个子应用的样式和功能相互隔离,避免冲突。

        假设有一个新闻网站,主应用展示统一的导航栏和布局,而每个新闻分类(如国内新闻、国际新闻、科技新闻)由不同的微前端子应用负责。

  • 每个子应用作为一个独立的 Web Component 封装,主应用直接通过 <my-product-app></my-product-app> 这样的标签来加载和渲染。
  • Web Components 提供了封装功能,避免了样式和脚本冲突。
基础写法
// 子应用:ProductApp 使用 Web Components 封装
class ProductApp extends HTMLElement {connectedCallback() {this.innerHTML = `<div>Product List</div>`;}
}customElements.define('my-product-app', ProductApp);// 主应用直接使用 Web Component
<my-product-app></my-product-app>
复杂结构写法
// 定义子应用组件 ProductApp
class ProductApp extends HTMLElement {constructor() {super();this.attachShadow({ mode: 'open' }); // 使用 Shadow DOM,避免样式污染}connectedCallback() {this.render();}render() {const template = document.createElement('template');template.innerHTML = `<style>.product-list {color: #333;font-size: 16px;}.product-item {margin: 10px 0;}</style><div class="product-list"><div class="product-item">Product 1</div><div class="product-item">Product 2</div><div class="product-item">Product 3</div></div>`;// 将模板内容插入 Shadow DOMthis.shadowRoot.appendChild(template.content.cloneNode(true));}
}// 注册自定义元素
customElements.define('my-product-app', ProductApp);
// 在主应用中
<my-product-app></my-product-app>

通过 Shadow DOM 进行样式隔离,也可以使用外部样式表。Shadow DOM 有两个主要好处:

  • 样式封装:子应用的样式不会影响到主应用或其他子应用。
  • DOM 隔离:确保子应用的内部结构和样式不会被外部应用干扰。
使用外部样式表
class ProductApp extends HTMLElement {constructor() {super();this.attachShadow({ mode: 'open' });}connectedCallback() {this.render();}render() {// 引入外部样式const link = document.createElement('link');link.rel = 'stylesheet';link.href = 'styles.css'; // 外部 CSS 文件// 模板内容const template = document.createElement('template');template.innerHTML = `<div class="product-list"><div class="product-item">Product 1</div><div class="product-item">Product 2</div><div class="product-item">Product 3</div></div>`;// 将样式和模板添加到 Shadow DOMthis.shadowRoot.appendChild(link);this.shadowRoot.appendChild(template.content.cloneNode(true));}
}

3)基于 JavaScript 动态加载

使用 JavaScript 动态加载工具(如 Webpack)来按需加载不同的子应用。

        假设有一个在线教育平台,主应用加载时并不加载所有课程内容,而是按需加载不同课程模块。

  • 在主应用中通过 import() 动态加载子应用的 JavaScript 模块。
// 使用 Webpack 动态加载子应用
const loadCourseApp = () => {import(/* webpackChunkName: "course-app" */ './course-app').then(module => {module.renderCoursePage();}).catch(err => {console.error('Error loading course app:', err);});
};

4)基于 iFrame

每个子应用运行在一个独立的 iFrame 中,彼此之间无任何依赖。

        假设有一个跨域的企业管理平台,不同的部门使用不同的子系统(如人事管理、财务管理等),每个部门的系统是独立的。

  • 每个子应用运行在独立的 iFrame 中,iFrame 嵌入到主应用页面中。
  • 可以完全隔离不同的子系统,避免了跨域和样式冲突的问题。
<!-- 主应用使用 iFrame 嵌入子应用 -->
<iframe src="https://example.com/finance" width="100%" height="500px"></iframe>
<iframe src="https://example.com/hr" width="100%" height="500px"></iframe>

3.类单页应用


4.参考文章链接

https://tech.meituan.com/tags/%E5%BE%AE%E5%89%8D%E7%AB%AF.html

https://wujie-micro.github.io/doc/guide/

https://juejin.cn/post/7113503219904430111

https://developer.jdcloud.com/article/2898

相关文章:

微前端架构学习笔记

前言 之前遇到过一个需求&#xff0c;有两个项目分别由两个不同的部门负责&#xff0c;不同技术栈&#xff0c;不同代码仓库&#xff1a; A 项目是官网&#xff0c;负责展示产品亮点等信息&#xff0c;有多个入口可以进入 B 项目中的不同页面。B 项目是业务线&#xff0c;负责…...

DApp开发:从合约到系统快速上线解决方案

在区块链技术迅猛发展的今天&#xff0c;去中心化应用&#xff08;DApp&#xff09;作为区块链的一项重要应用&#xff0c;已经吸引了众多开发者和企业的关注。与传统应用程序不同&#xff0c;DApp依托于区块链的去中心化特点&#xff0c;实现了透明、安全、不可篡改等优势&…...

react 中 useState 中的 set 方法异步解决

使用 useEffect 监听状态的改变。 一、异步特性 在批量处理状态更新时&#xff0c;用以提高性能。 二、异步解决 使用useEffect来处理更新后的状态&#xff0c;useEffect钩子在组件渲染后执行&#xff0c;并且会在依赖项&#xff08;第二个参数&#xff09;发生变化时重新执…...

UAC2.0 speaker——带反馈端点的 USB speaker(16bit 单声道)

UAC2.0 speaker 系列文章 UAC2.0 speaker——单声道 USB speaker(16bit) UAC2.0 speaker——类特殊请求 UAC2.0 speaker——音量控制 UAC2.0 speaker——多采样率支持 UAC2.0 speaker——24/32bit 支持 UAC2.0 speaker——speaker 数据传输 UAC2.0 speaker——同时支持 16bi…...

docker的简单使用

文章目录 docker简介docker架构镜像和容器镜像有关的常用命令容器相关常用命令 docker简介 Docker是一个开源的应用容器引擎&#xff0c;基于Go语言并遵从Apache2.0协议开源。 Docker可以让开方子打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到…...

Selenium:强大的 Web 自动化测试工具

Selenium&#xff1a;强大的 Web 自动化测试工具 在当今的软件开发和测试领域&#xff0c;自动化工具的重要性日益凸显。Selenium 就是一款备受欢迎的 Web 自动化测试工具&#xff0c;它为开发者和测试人员提供了强大的功能和便利。本文将详细介绍 Selenium 是什么&#xff0c…...

设计模式 在PLM系统的应用场景介绍

通义灵码 设计模式在 PLM&#xff08;产品生命周期管理&#xff09;系统中扮演着重要的角色&#xff0c;可以帮助开发人员更好地组织代码、提高系统的可维护性和扩展性。以下是一些常见的设计模式及其在 PLM 系统中的应用场景&#xff1a; 1. 单例模式&#xff08;Singleton …...

C#请求https提示未能为 SSL/TLS 安全通道建立信任关系

System.Net.WebException: 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系 &#xff0c;这个错误通常表明你的应用程序在尝试建立一个安全的 SSL/TLS 连接时遇到了问题。这通常是由于证书验证失败引起的。证书验证失败可能有几个原因&#xff1a; 证书不受信任&#…...

【人工智能】GaussDB数据库技术及应用

文章目录 前言一、数据库的基本概念及发展演进1、数据库概念DB2、数据库管理系统概念DBMS3、数据库与数据库管理系统的关系4、数据库的演进及发展5、数据模型的基本概念6、数据模型的要求和类型7、层次模型的基本概念8、网状模型的基本概念8、关系模型的基本概念9、非关系模型的…...

OpenAI12天 –第3天的实时更新,包括 ChatGPT、Sora、o1 等

OpenAI提前开启了假期&#xff0c;推出了为期 12 天的活动&#xff0c;名为“OpenAI 12 天”。在接下来的一周左右的每一天&#xff0c;OpenAI 都将发布现有产品的新更新以及新软件&#xff0c;包括备受期待的 Sora AI 视频生成器。 OpenAI 首席执行官 Sam Altman 表示&#x…...

删除Yocto中build-x9hp_ms_a12_vemmc_ap2/tmp/work/aarch64-sdrv-linux/package后再编译出错问题

前言&#xff1a; 在yocto编译中&#xff0c;一般会添加自己的package并编译打包到yocto里去。这个包里的内容有时候需要添加或者删除。但是我删除了文件&#xff0c;在编译完成烧录到板子上&#xff0c;里面还有自己删除的文件&#xff0c;于是就在yocto搜索哪个目录有该文件&…...

2024三掌柜赠书活动第三十五期:Redis 应用实例

目录 前言 Redis操作都会&#xff0c;却不知道怎么用&#xff1f; 关于《Redis 应用实例》 编辑推荐 内容简介 作者简介 图书目录 《Redis 应用实例》全书速览 拓展&#xff1a;Redis使用场景 实例1&#xff1a;缓存应用 场景描述 实现方法 具体代码示例 实例2&a…...

观察者模式的理解和实践

引言 在软件开发中&#xff0c;设计模式是开发者们为了解决常见的设计问题而总结出来的一系列最佳实践。观察者模式&#xff08;Observer Pattern&#xff09;是其中一种非常经典且使用率极高的设计模式。它主要用于定义对象之间的一对多关系&#xff0c;使得当一个对象的状态发…...

查看Windows系统上的Redis服务器是否设置了密码

查看 Redis 配置文件 1.找到 Redis 配置文件&#xff1a; 通常Redis配置文件名为 redis.windows.conf 或 redis.conf&#xff0c;它位于Redis安装目录中。 2.打开配置文件&#xff1a; 使用文本编辑器&#xff08;如Notepad、VS Code等&#xff09;打开该文件。 3.查找 re…...

认识Java中的异常(半成品)

1.异常的概念与体系结构 1.1在Java中,将程序执行过程中发生的不正常行为称为异常.比如 1.算数异常 public class Main1 {public static void main(String[] args){System.out.println(10/0);} } //异常信息为:Exception in thread "main" java.lang.ArithmeticExc…...

生成SSH秘钥文件

git生成文件命令 # 配置用户名和邮箱 git config --global user.name "你的GitHub用户名" git config --global user.email "你的GitHub邮箱"# 生成ssh-key ssh-keygen -t rsa -C “你的GitHub邮箱" # 验证 ssh -T gitgithub .com 第一步&#xff1a;…...

wsl2子系统ubuntu发行版位置迁移步骤

默认的wsl2发行版是安装在windos的c盘&#xff0c;占用空间较大&#xff0c;有迁移需求&#xff0c;也可以迁移到其他电脑&#xff1b; 查看现有发行版信息 运行以下命令查看现有的 WSL 发行版及其状态&#xff1a; wsl --list --verbose# 输出示例NAME STATE …...

协程设计原理与实现

协程设计原理与汇编实现 同步与异步 对于任何一个事情&#xff0c;都可以划分为不同的步骤。所谓同步&#xff0c;就先做第一个事情&#xff0c;按照这件事的步骤完成这件事之后&#xff0c;再去做第二件事。再去做第三件事&#xff0c;以此类推。 异步就是&#xff0c;可以…...

合并区间C和C++的区别、布尔、整型、浮点、指针类型和0做比较、malloc、calloc、realloc的区别

56. 合并区间 class Solution { public:vector<vector<int>> merge(vector<vector<int>>& intervals) {//先按照每个区间的左元素排序&#xff0c;这样每个区间的左边界就固定了&#xff0c;所以之后考虑相邻的//区间是否是相交的就行 类似与栈的…...

Flutter 图片编辑板(一) 事件路由

一个图片编辑板&#xff0c;有两部分组成。编辑板和内容项。每一个内容项是被InteractiveViewer修饰的widget&#xff0c;具有缩放偏移的功能。 在图片编辑板上&#xff0c; 会有多个内容相&#xff0c;图片或文字&#xff08;添加文字目前还没做过&#xff09;。 当要编辑其中…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...