微前端架构学习笔记
前言
之前遇到过一个需求,有两个项目分别由两个不同的部门负责,不同技术栈,不同代码仓库:
- 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)结合使用
- 主应用与子应用无耦合,每个子应用都可以独立加载和卸载
缺点
- 配置较为繁琐,需要开发者手动管理每个子应用的生命周期和加载
要求子应用暴露三个生命周期方法(
bootstrap、mount、unmount),并且需要对子应用的入口进行适当的修改。适用场景
- 需要多种前端技术栈共存的项目
- 可以与现有的应用逐步迁移到微前端架构中
以 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 暴露bootstrap、mount和unmount方法。// 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
相关文章:
微前端架构学习笔记
前言 之前遇到过一个需求,有两个项目分别由两个不同的部门负责,不同技术栈,不同代码仓库: A 项目是官网,负责展示产品亮点等信息,有多个入口可以进入 B 项目中的不同页面。B 项目是业务线,负责…...
DApp开发:从合约到系统快速上线解决方案
在区块链技术迅猛发展的今天,去中心化应用(DApp)作为区块链的一项重要应用,已经吸引了众多开发者和企业的关注。与传统应用程序不同,DApp依托于区块链的去中心化特点,实现了透明、安全、不可篡改等优势&…...
react 中 useState 中的 set 方法异步解决
使用 useEffect 监听状态的改变。 一、异步特性 在批量处理状态更新时,用以提高性能。 二、异步解决 使用useEffect来处理更新后的状态,useEffect钩子在组件渲染后执行,并且会在依赖项(第二个参数)发生变化时重新执…...
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是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源。 Docker可以让开方子打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到…...
Selenium:强大的 Web 自动化测试工具
Selenium:强大的 Web 自动化测试工具 在当今的软件开发和测试领域,自动化工具的重要性日益凸显。Selenium 就是一款备受欢迎的 Web 自动化测试工具,它为开发者和测试人员提供了强大的功能和便利。本文将详细介绍 Selenium 是什么,…...
设计模式 在PLM系统的应用场景介绍
通义灵码 设计模式在 PLM(产品生命周期管理)系统中扮演着重要的角色,可以帮助开发人员更好地组织代码、提高系统的可维护性和扩展性。以下是一些常见的设计模式及其在 PLM 系统中的应用场景: 1. 单例模式(Singleton …...
C#请求https提示未能为 SSL/TLS 安全通道建立信任关系
System.Net.WebException: 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系 ,这个错误通常表明你的应用程序在尝试建立一个安全的 SSL/TLS 连接时遇到了问题。这通常是由于证书验证失败引起的。证书验证失败可能有几个原因: 证书不受信任&#…...
【人工智能】GaussDB数据库技术及应用
文章目录 前言一、数据库的基本概念及发展演进1、数据库概念DB2、数据库管理系统概念DBMS3、数据库与数据库管理系统的关系4、数据库的演进及发展5、数据模型的基本概念6、数据模型的要求和类型7、层次模型的基本概念8、网状模型的基本概念8、关系模型的基本概念9、非关系模型的…...
OpenAI12天 –第3天的实时更新,包括 ChatGPT、Sora、o1 等
OpenAI提前开启了假期,推出了为期 12 天的活动,名为“OpenAI 12 天”。在接下来的一周左右的每一天,OpenAI 都将发布现有产品的新更新以及新软件,包括备受期待的 Sora AI 视频生成器。 OpenAI 首席执行官 Sam Altman 表示&#x…...
删除Yocto中build-x9hp_ms_a12_vemmc_ap2/tmp/work/aarch64-sdrv-linux/package后再编译出错问题
前言: 在yocto编译中,一般会添加自己的package并编译打包到yocto里去。这个包里的内容有时候需要添加或者删除。但是我删除了文件,在编译完成烧录到板子上,里面还有自己删除的文件,于是就在yocto搜索哪个目录有该文件&…...
2024三掌柜赠书活动第三十五期:Redis 应用实例
目录 前言 Redis操作都会,却不知道怎么用? 关于《Redis 应用实例》 编辑推荐 内容简介 作者简介 图书目录 《Redis 应用实例》全书速览 拓展:Redis使用场景 实例1:缓存应用 场景描述 实现方法 具体代码示例 实例2&a…...
观察者模式的理解和实践
引言 在软件开发中,设计模式是开发者们为了解决常见的设计问题而总结出来的一系列最佳实践。观察者模式(Observer Pattern)是其中一种非常经典且使用率极高的设计模式。它主要用于定义对象之间的一对多关系,使得当一个对象的状态发…...
查看Windows系统上的Redis服务器是否设置了密码
查看 Redis 配置文件 1.找到 Redis 配置文件: 通常Redis配置文件名为 redis.windows.conf 或 redis.conf,它位于Redis安装目录中。 2.打开配置文件: 使用文本编辑器(如Notepad、VS Code等)打开该文件。 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 第一步:…...
wsl2子系统ubuntu发行版位置迁移步骤
默认的wsl2发行版是安装在windos的c盘,占用空间较大,有迁移需求,也可以迁移到其他电脑; 查看现有发行版信息 运行以下命令查看现有的 WSL 发行版及其状态: wsl --list --verbose# 输出示例NAME STATE …...
协程设计原理与实现
协程设计原理与汇编实现 同步与异步 对于任何一个事情,都可以划分为不同的步骤。所谓同步,就先做第一个事情,按照这件事的步骤完成这件事之后,再去做第二件事。再去做第三件事,以此类推。 异步就是,可以…...
合并区间C和C++的区别、布尔、整型、浮点、指针类型和0做比较、malloc、calloc、realloc的区别
56. 合并区间 class Solution { public:vector<vector<int>> merge(vector<vector<int>>& intervals) {//先按照每个区间的左元素排序,这样每个区间的左边界就固定了,所以之后考虑相邻的//区间是否是相交的就行 类似与栈的…...
Flutter 图片编辑板(一) 事件路由
一个图片编辑板,有两部分组成。编辑板和内容项。每一个内容项是被InteractiveViewer修饰的widget,具有缩放偏移的功能。 在图片编辑板上, 会有多个内容相,图片或文字(添加文字目前还没做过)。 当要编辑其中…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
