微前端框架 qiankun 全面解析到源码实现
- 微前端(Micro Frontends)是一种将大型前端应用拆分为多个独立模块的架构设计思想,旨在解决复杂应用开发与维护的难题。qiankun 是目前流行的微前端解决方案之一,基于 single-spa 进行封装,提供了一种简单且完整的微前端架构实践。
微前端概念与优势
- 微前端类似于后端的微服务架构,将一个大型的前端应用拆分为多个独立的前端模块,每个模块可以独立开发、测试、部署和运行。每个子应用(微应用)可以使用不同的技术栈,如 React、Vue、Angular 等。
- 独立开发:每个微应用可以由独立的团队开发,甚至可以使用不同的技术栈,降低团队间的耦合度。
- 渐进迁移:在技术更新或重构过程中,可以通过逐步替换微应用来实现平滑迁移,而不是一次性更新整个系统。
- 独立部署:每个微应用可以独立部署,减少部署时的影响面。
- 复用性高:微应用可以在不同项目间复用,减少重复开发的工作。
qiankun 简介
- qiankun 是基于 single-spa 实现的微前端框架,它通过提供完整的生命周期管理、应用间通信机制以及对沙箱的支持,简化了微前端的开发和集成。
- 简单易用:对 single-spa 进行了封装,开发者不需要关心底层细节,只需按照简单的 API 使用即可。
- 无技术栈限制:支持任意框架(React、Vue、Angular 等)的微应用接入。
- 沙箱隔离:通过沙箱机制隔离不同微应用的全局变量、样式,确保互不干扰。
- 应用通信机制:支持主应用与微应用之间的数据传递与通信,提供灵活的 API。
qiankun 核心概念
- 主应用是整个微前端系统的宿主应用,负责微应用的注册、加载和调度。主应用通常使用统一的框架(如 React 或 Vue)进行开发。
- 微应用是独立开发的前端模块,可以在主应用中注册和运行。每个微应用可以独立运行,也可以在主应用中加载时与其他微应用协同工作。
- qiankun 提供了标准的生命周期钩子,包括 bootstrap、mount、unmount,分别对应应用的初始化、挂载和卸载过程。
- qiankun 通过沙箱机制隔离不同微应用的运行环境,确保它们之间的全局变量和样式互不影响。
- qiankun 提供了简单的 API 用于主应用与微应用之间进行数据传递和事件通
基本使用
- 在主应用中安装 qiankun:
npm install qiankun --save
import { registerMicroApps, start } from 'qiankun';// 注册微应用
registerMicroApps([{name: 'app1',entry: '//localhost:7100', // 子应用的访问地址container: '#container', // 子应用挂载的 DOM 节点activeRule: '/app1', // 子应用激活的路径},{name: 'app2',entry: '//localhost:7200',container: '#container',activeRule: '/app2',},
]);// 启动微前端
start();
- 在每个微应用中,你需要导出标准的生命周期钩子:
export async function bootstrap() {console.log('微应用启动');
}export async function mount(props) {console.log('微应用挂载', props);
}export async function unmount() {console.log('微应用卸载');
}
qiankun 的高级功能
qiankun 通过沙箱机制实现对微应用的全局变量和样式隔离,确保不同的微应用不会相互干扰。每个微应用的运行环境是相互独立的。
// 主应用中创建全局状态
import { initGlobalState } from 'qiankun';
const actions = initGlobalState({ user: 'admin' });actions.onGlobalStateChange((state, prev) => {console.log('状态变化', state, prev);
});// 微应用中使用全局状态
props.onGlobalStateChange((state, prev) => {console.log('子应用状态变化', state, prev);
});
- qiankun 支持动态注册和加载微应用,可以根据业务需求在运行时决定是否加载某个微应用。
import { loadMicroApp } from 'qiankun';const microApp = loadMicroApp({name: 'app3',entry: '//localhost:7300',container: '#container',props: { someProp: 'someValue' },
});// 动态卸载微应用
microApp.unmount();
- qiankun 支持多实例的微应用,可以在同一页面上运行同一个微应用的多个实例。
源码分析
- qiankun 是基于 single-spa 封装的微前端解决方案,旨在提供更加简单、开箱即用的微前端架构。通过对 qiankun 源码的分析,能帮助我们更好地理解其工作原理及微前端的核心思想。本文将逐步分析 qiankun 源码的核心部分,包括微应用的注册、加载、沙箱机制、应用间通信等。
qiankun 的核心代码主要包括以下模块:
- registerMicroApps:微应用的注册、管理模块。
- start:微前端的启动模块。
- loadMicroApp:微应用的动态加载模块。
- 沙箱机制:隔离微应用的全局变量和样式。
- 应用间通信:主应用和微应用之间的状态管理。
src
├── globalState // 应用间状态管理
├── interfaces // 类型声明和接口定义
├── sandbox // 沙箱隔离机制
├── utils // 工具方法
├── index.ts // 核心注册与启动代码
├── start.ts // start 函数,启动微前端
└── register.ts // registerMicroApps 函数,注册微前端应用
- registerMicroApps 是 qiankun 的核心 API,负责将微应用注册到主应用中。其源码位于 register.ts 文件。
export function registerMicroApps(apps: Array<RegistrableApp<any>>,lifeCycles?: FrameworkLifeCycles<any>,
) {// 对微应用的配置进行标准化const unmountPromises = apps.map((app) => {return validateRegistrableApp(app);});// 传递到 single-spa 中注册微应用unmountPromises.forEach((promise) => {promise.then((appConfig) => {registerApplication(appConfig);});});
}
- 在 start.ts 文件中,start 方法用于启动微前端环境。它会触发微应用的加载,并控制应用的生命周期。
export function start(opts: StartOptions = {}) {// 启动 single-spastartSingleSpa(opts);// 初始化沙箱if (opts.sandbox) {initializeSandbox(opts.sandbox);}// 启动全局状态管理if (opts.globalState) {initializeGlobalState(opts.globalState);}
}
qiankun 使用 single-spa 管理应用的生命周期,而 start 方法会通过 startSingleSpa 启动整个微前端架构,并根据配置初始化沙箱机制和全局状态管理。
- 沙箱机制是 qiankun 的核心之一,它通过隔离不同微应用的全局变量和样式,确保应用之间互不干扰。qiankun 的沙箱模块位于 src/sandbox 中,主要包括 ProxySandbox 和 LegacySandbox 两种沙箱实现。
- proxySandbox 使用现代浏览器的 Proxy API 来隔离全局对象。这是 qiankun 默认的沙箱实现方式。
export class ProxySandbox {private updatedValueSet = new Set<string>();private sandboxRunning = false;private proxy: WindowProxy;constructor() {const rawWindow = window;const fakeWindow = Object.create(null);this.proxy = new Proxy(fakeWindow, {get(target, key) {return key in target ? target[key] : rawWindow[key];},set(target, key, value) {target[key] = value;if (this.sandboxRunning) {this.updatedValueSet.add(key);}return true;}});}// 启动沙箱activate() {this.sandboxRunning = true;}// 停止沙箱deactivate() {this.sandboxRunning = false;}
}
- 激活沙箱:调用 activate() 方法时,Proxy 开始拦截对 window 对象的修改。
- 停止沙箱:调用 deactivate() 方法后,所有全局对象的修改将不再生效。
- LegacySandbox 是为不支持 Proxy 的浏览器设计的沙箱实现。它通过手动保存和恢复全局变量的方式来实现隔离。
export class LegacySandbox {private originalWindowProperties: Map<string, any>;constructor() {this.originalWindowProperties = new Map();}// 记录原始全局变量recordOriginalState() {Object.keys(window).forEach((key) => {this.originalWindowProperties.set(key, window[key]);});}// 恢复原始全局变量restoreOriginalState() {this.originalWindowProperties.forEach((value, key) => {window[key] = value;});}
}
- 这类沙箱实现比较粗糙,性能上不如 ProxySandbox,但能兼容旧浏览器。
- qiankun 提供了全局状态管理器 GlobalState,用于主应用和微应用之间的数据通信。
- initGlobalState 用于初始化全局状态,并提供 setGlobalState 和 onGlobalStateChange 方法,用于跨应用通信。
export function initGlobalState(initialState: Record<string, any>) {let state = initialState;function setGlobalState(newState: Record<string, any>) {state = { ...state, ...newState };// 通知所有订阅者subscribers.forEach((listener) => listener(state));}function onGlobalStateChange(listener: (state: any) => void) {subscribers.push(listener);return () => {subscribers = subscribers.filter((item) => item !== listener);};}return {setGlobalState,onGlobalStateChange,};
}
- setGlobalState: 设置新的全局状态,所有应用会自动收到更新。
- onGlobalStateChange: 订阅状态变化的监听器,微应用可以通过它获取主应用的数据更新。
- loadMicroApp 是 Qiankun 提供的用于动态加载微应用的方法,允许在运行时按需加载微应用,而不需要在应用启动时注册。
export function loadMicroApp(appConfig: LoadableApp<any>,opts?: FrameworkConfiguration,
) {// 加载微应用const microApp = loadApp(appConfig, opts);// 启动微应用microApp.mount();return microApp;
}
- 通过 loadMicroApp,开发者可以在特定场景下按需加载微应用,而无需一开始就注册所有应用。这样可以减小主应用的初始加载体积,提升性能。
相关文章:
微前端框架 qiankun 全面解析到源码实现
微前端(Micro Frontends)是一种将大型前端应用拆分为多个独立模块的架构设计思想,旨在解决复杂应用开发与维护的难题。qiankun 是目前流行的微前端解决方案之一,基于 single-spa 进行封装,提供了一种简单且完整的微前端…...
初始化数据的正确方式?
关于这篇文章 https://proandroiddev.com/loading-initial-data-in-launchedeffect-vs-viewmodel-f1747c20ce62 pl的视频解读 当在viewmodel中需要进行数据的初始化的时候 viewmodel.initData() 放在哪里合适呢,大部分情况下可以放在 viewmodel的init{}模块&…...
Flutter平台嵌入器
When you build a Flutter app, it’s not just about the code you write in Dart and the Flutter framework. There’s also a crucial piece called the platform embedders that enable your Flutter app to run on different operating systems like Android, iOS, and s…...
微信小程序——婚礼邀请函
一、界面设计 首页: 精美的婚礼主题背景图,可能是新人的婚纱照或浪漫的插画。温馨的欢迎语,如 “欢迎参加我们的婚礼”。一个 “打开邀请函” 的按钮,引导用户进入邀请函详情页面。 邀请函详情页面: 顶部展示新人的照片…...
WebRTC Connection Negotiate解决
最近有个项目 ,部署之后一直显示,查了一些资料还是没有解决,无奈只有自己研究解决?经过排查,应该是内网穿透的问题 什么是内网穿透? 我们访问我们自己的官网产品页面,我们的服务器是一个单独…...
Redis面试篇1
1、为什么要用缓存? 使用缓存的目的就是提升读写性能。在实际的业务场景下,更多的是为了提升读性能,带来更好的性能和并发量。Redis的读写性能比MySQL好的多,我们就可以把MySQL中的热点数据缓存到Redis,提升读取性能&…...
Debezium系列之:Debezium 3.0.0.Final发布
Debezium系列之:Debezium 3.0.0.Final发布 Debezium 核心的变化需要 Java 17基于Kafka 3.8 构建废弃的增量信号字段的删除每个表的详细指标MariaDB连接器的更改版本 11.4.3 支持MongoDB连接器的更改MongoDB sink connectorMySQL连接器的改变MySQL 9MySQL向量数据类型Oracle连接…...
一文解决jQuery表格插件DataTable导出PDF中文乱码问题
原因是默认字体不支持中文,需要更换字体。 详情官网:pdfmake 官网的大致意思是,下载pdfmake后,自行生成可用的字体js文件 以下是详细操作: 重要前提:电脑上需要已安装nodejs 点击进入官网下载安装即可&a…...
使用pytorch进行迁移学习的两个步骤
1. 步骤及代码 迁移学习一般都会使用两个步骤进行训练: 固定预训练模型的特征提取部分,只对最后一层进行训练,使其快速收敛;使用较小的学习率,对全部模型进行训练,并对每层的权重进行细微的调节。 impor…...
ChatGPT相关参数示例
max_token 用于控制最大输出长度,若ChatGPT的回复大于max_tokens,则对输出结果进行截断。 from openai import OpenAI client OpenAI(base_url"https://api.chatanywhere.tech/v1" ) response client.chat.completions.create(model"…...
OWASP发布大模型安全风险与应对策略(QA测试重点关注)
开放式 Web 应用程序安全项目(OWASP)发布了关于大模型应用的安全风险,这些风险不仅包括传统的沙盒逃逸、代码执行和鉴权不当等安全风险,还涉及提示注入、对话数据泄露和数据投毒等人工智能特有的安全风险。 帮助开发者和测试同学更…...
【HarmonyOS开发笔记 2 】 -- ArkTS语法中的变量与常量
ArkTS是HarmonyOS开发的编程语言 ArkTS语法中的变量 【语法格式】: let 变量名: 类型 值 let:是定义变量的关键字类型: 值数据类型, 常用的数据类型 字符型(string)、数字型(number…...
UI自动化测试示例:python+pytest+selenium+allure
重点应用是封装、参数化: 比如在lib文件夹下,要存储封装好的方法和必要的环境变量(指网址等) 1.cfg.py:封装网址和对应的页面 SMP_ADDRESS http://127.0.0.1:8234SMP_URL_LOGIN f{SMP_ADDRESS}/login.html SMP_URL_DE…...
C/C++ 编程小工具
编写了 tools.h 和 tools.cpp,用于 Debug、性能测试、打印日志。 tools.h #ifndef TOOLS_H #define TOOLS_H#include <time.h> #include <fstream> #include <iostream> #include <random> #include <chrono> #include <vector&…...
第四十二章 使用 WS-ReliableMessaging
文章目录 第四十二章 使用 WS-ReliableMessaging从 Web 客户端发送一系列消息 第四十二章 使用 WS-ReliableMessaging IRIS 支持 WS-ReliableMessaging 规范的部分内容,如简介中所述。此规范提供了一种按顺序可靠地传递一系列消息的机制。本页介绍如何手动使用可靠…...
利士策分享,婚姻为何被称为大事?
利士策分享,婚姻为何被称为大事? 在历史的长河中,婚姻一直被视为人生中的头等大事,这一观念跨越时空,深深植根于各种文化和社会结构中。 古人为何将婚姻称为“大事”,这背后蕴含着丰富的社会、文化和心理寓…...
malloc源码分析之 ----- 你想要啥chunk
文章目录 malloc源码分析之 ----- 你想要啥chunktcachefastbinsmall binunsorted binbin处理top malloc源码分析之 ----- 你想要啥chunk tcache malloc源码,这里以glibc-2.29为例: void * __libc_malloc (size_t bytes) {mstate ar_ptr;void *victim;vo…...
软考系统分析师知识点五:数据通信与计算机网络
前言 今年报考了11月份的软考高级:系统分析师。 考试时间为:11月9日。 倒计时:32天。 目标:优先应试,其次学习,再次实践。 复习计划第一阶段:扫平基础知识点,仅抽取有用信息&am…...
windows客户端SSH连接ubuntu/linux服务器,三种网络连接:局域网,内网穿透(sakuraftp),虚拟局域网(zerotier)
windows客户端SSH连接ubuntu/linux服务器,三种网络连接:局域网,内网穿透(sakuraftp),虚拟局域网(zerotier) 目录 SSH简述、三种网络连接特点SSH简述局域网内连接内网穿透(…...
Python 工具库每日推荐【openpyxl 】
文章目录 引言Python Excel 处理库的重要性今日推荐:openpyxl 工具库主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例:自动生成月度销售报告案例分析高级特性条件格式数据验证扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 TypeScript 设计…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
2.2.2 ASPICE的需求分析
ASPICE的需求分析是汽车软件开发过程中至关重要的一环,它涉及到对需求进行详细分析、验证和确认,以确保软件产品能够满足客户和用户的需求。在ASPICE中,需求分析的关键步骤包括: 需求细化:将从需求收集阶段获得的高层需…...
Android屏幕刷新率与FPS(Frames Per Second) 120hz
Android屏幕刷新率与FPS(Frames Per Second) 120hz 屏幕刷新率是屏幕每秒钟刷新显示内容的次数,单位是赫兹(Hz)。 60Hz 屏幕:每秒刷新 60 次,每次刷新间隔约 16.67ms 90Hz 屏幕:每秒刷新 90 次,…...
VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...
