微前端框架 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 设计…...

本地生活服务项目入局方案解析!本地生活服务商系统能实现怎样的作业效果?
当前,各大平台的本地生活服务业务日渐兴盛,提高创业者入局意向的同时,也让本地生活服务项目有哪些等问题也成为了多个创业者社群中的热议对象。而从目前的讨论情况来看,在创业者们所询问的众多本地生活服务项目中,通过…...

ML 系列:【13 】— Logistic 回归(第 2 部分)
文章目录 一、说明二、挤压方法三、Logistic 回归中的损失函数四、后记 一、说明 在这篇文章中,我们将深入研究 squashing 方法,这是有符号距离方法(第 12节)的一种很有前途的替代方案。squashing 方法通过提供增强的对异常值…...

45岁被裁员的程序员,何去何从?
在当今快速变化的技术行业,职业生涯的稳定性受到挑战。在45岁被裁员,对很多程序员来说,可能是一种惊慌失措的体验。然而,这个阶段也可以被视为一个重新审视和调整方向的机会。本文将对可能的出路进行全方位的分析,并提…...

云计算Openstack Neutron
OpenStack Neutron是OpenStack云计算平台中的网络服务组件,它为OpenStack提供了强大的网络连接功能。 一、基本概念 Neutron是一个网络服务项目,旨在为OpenStack提供网络连接。它允许用户创建和管理虚拟网络,包括子网、路由、安全组等&…...

PointNet++网络详解
数据集转换 数据集转换的意义在于将原本的 txt 点云文件转换为更方便运算的npy点云文件,同时,将原本的xyzrgb这 6 个维度转换为xyzrgbc,最后一个c维度代表该点云所属的类别。 for anno_path in anno_paths:print(anno_path)try:elements a…...

Java | Leetcode Java题解之第459题重复的子字符串
题目: 题解: class Solution {public boolean repeatedSubstringPattern(String s) {return kmp(s s, s);}public boolean kmp(String query, String pattern) {int n query.length();int m pattern.length();int[] fail new int[m];Arrays.fill(fa…...

【动态规划-最长公共子序列(LCS)】【hard】力扣1092. 最短公共超序列
给你两个字符串 str1 和 str2,返回同时以 str1 和 str2 作为 子序列 的最短字符串。如果答案不止一个,则可以返回满足条件的 任意一个 答案。 如果从字符串 t 中删除一些字符(也可能不删除),可以得到字符串 s &#x…...

图片编辑为底片,智能工具助力,创作精彩视觉作品
在当今数字化时代,图像编辑已成为表达创意和美化视觉作品的重要手段。借助智能工具,即使是初学者也能轻松驾驭图片编辑。接下为大家展示图片编辑为底片图片的效果。 1.打开“首助编辑高手”,选择这里“图片批量处理”版块页面上 2.导入保存有…...

机器学习/数据分析--用通俗语言讲解时间序列自回归(AR)模型,并用其预测天气,拟合度98%+
时间序列在回归预测的领域的重要性,不言而喻,在数学建模中使用及其频繁,但是你真的了解ARIMA、AR、MA么?ACF图你会看么?? 时间序列数据如何构造???,我打过不少…...

回溯算法之值子集和问题详细解读(附带Java代码解读)
子集和问题(Subset Sum Problem) 是一个经典的组合优化问题。问题可以这样描述: 给定一个整数集合和一个目标整数 target,我们需要从集合中选出若干个整数,使它们的和等于 target。如果这样的子集存在,返回…...