微前端--single-spa

微前端

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
使用微前端的挑战: 子应用切换,应用相互隔离,互补干扰,子应用之前的通信,多个子应用并存,用户状态的存储,免登。

常用技术方案

路由分发式微前端

通过http服务的反向代理

http {server {listen 80;server_name xxx.xxx.com;location /api/ {proxy_pass http://localhost:3001/api    }location /web/admin {proxy_pass http://localhost:3002/api}location / {proxy_pass /;}}
}

实现简单,不需要对现有应用进行改造,和技术栈无关。
切换应用的时候,浏览器都需要重新加载页面。

iframe

html的标签
实现简单,css和js隔离,互不干扰。全局上下文完全隔离,内存变量不共享,子应用之间的通信,数据同步过程比较复杂,对seo不友好。切换应用的时候,浏览器都需要重新加载页面。

single-spa

在single-spa方案中,应用被分为两类:基座应用和子应用。
single-spa 会在基座应用中维护一个路由注册表,每个路由对应一个子应用。基座应用启动以后,当我们切换路由时,如果是一个新的子应用,会动态获取子应用的 js 脚本,然后执行脚本并渲染出相应的页面;如果是一个已经访问过的子应用,那么就会从缓存中获取已经缓存的子应用,激活子应用并渲染出对应的页面。

// 基座
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router';
const  { registerApplication, start } =  require('single-spa');Vue.use(VueRouter)Vue.config.productionTip = false// 接入 single-spa 的标志
window.__SINGLE_SPA__ = trueconst router = new VueRouter({mode: 'history',routes: []
});// 远程加载子应用
function createScript(url) {return new Promise((resolve, reject) => {const script = document.createElement('script')script.src = urlscript.onload = resolvescript.onerror = rejectconst firstScript = document.getElementsByTagName('script')[0]firstScript.parentNode.insertBefore(script, firstScript)})
}
// 加载子应用
function loadApp(url, globalVar, entrypoints) {return async () => {for(let i = 0; i < entrypoints.length; i++) {await createScript(url + entrypoints[i])}return window[globalVar]}
}
// 子应用路由注册表
const apps = [{// 子应用名称name: 'app1',// 子应用加载函数app: loadApp('http://localhost:8081', 'app1', [ "/js/chunk-vendors.js", "/js/app.js" ]),// 当路由满足条件时(返回true),激活(挂载)子应用activeWhen: location => location.pathname.startsWith('/app1'),// 传递给子应用的对象customProps: {}},{name: 'app2',app: loadApp('http://localhost:8082', 'app2', [ "/js/chunk-vendors.js", "/js/app.js" ]),activeWhen: location => location.pathname.startsWith('/app2'),customProps: {}},{// 子应用名称name: 'app3',// 子应用加载函数app: loadApp('http://localhost:3000', 'app3', ["/main.js"]),// 当路由满足条件时(返回true),激活(挂载)子应用activeWhen: location => location.pathname.startsWith('/app3'),// 传递给子应用的对象customProps: {}}
]// 注册子应用
for (let i = apps.length - 1; i >= 0; i--) {registerApplication(apps[i])
}new Vue({router,render: h => h(App),mounted() {// 启动start()},
}).$mount('#app')
  • name: 子应用的唯一表示
  • activeWhen: 子应用激活的条件,当url发生变化的升级后,会遍历执行注册的子应用的activeWhen方法,当activeWhen返回的是true,对应的子应用就会被激活
  • app: 用户获取子应用提供给基座应用的生命周期,bootstrap mount unmount等。基座应用切换子应用时,也是同样的操作,即先执行上一个子应用的 unmount 操作,然后再执行下一个子应用的 mount 操作。因此就需要子应用提供 mount、unmount 等生命周期方法,供基座应用调用。和单页应用的懒加载一样,基座应用在激活子应用时,如果子应用是首次激活,就会执行 app 方法,动态去加载子应用的入口 js 文件,然后执行,得到子应用的生命周期方法。
  • customProps: 子应用激活的时候,可以传递给子应用的自定义属性,是一个对象
// index.jsimport Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = falseconst appOptions = {render: (h) => h(App)
};let vueInstance;// 子应用没有接入 single-spa
if (!window.__SINGLE_SPA__) {new Vue(appOptions).$mount('#app')
}// 提供 bootstrap 生命周期方法
export function bootstrap () {console.log('app1 bootstrap')return Promise.resolve().then(() => {});
}
// 提供 mount 生命周期方法
export function mount (props) {console.log('app1 mount', props)return Promise.resolve().then(() => {vueInstance = new Vue(appOptions)vueInstance.$mount('#microApp')})
}// 提供 unmount 生命周期方法
export function unmount () {console.log('app1 unmount')return Promise.resolve().then(() => {if (!vueInstance.$el.id) {vueInstance.$el.id = 'microApp'}vueInstance.$destroy()vueInstance.$el.innerHTML = ''})
}// 提供 update 生命周期方法
export function update () {console.log('app1 update');
}

通常通过webpack构建工具生成的js脚本,表现形式都是iiff,就是立即执行函数表达式。各子应用对应的脚本执行的时是相互隔离的,如果是这样,基座应用在激活子应用的时候,是无法获取到子应用的生命周期方法的,也无法挂载子应用。添加libaray,libarayTarget配置项,将子应用入口文件的返回值就是生命周期方法暴露给window,这样基座应用就可以从window中获取子应用的生命周期的方法。

// 项目的构建脚本
module.exports = {configureWebpack: {...publicPath: 'http://localhost:8081'output: {library: 'app1',   libraryTarget: 'var'}    }
}
  • 单页应用的路由切换功能是基于window.history(window.location.hash)实现。在单页面应用中,会给window对象注册popstate(hashchange)事件,在callback中,添加页面切换的逻辑,当通过执行 pushState(replaceState) 方法、修改 hash 值、使用浏览器前进后退(go、back、forward)功能改变 url 时,会触发 popstate(hashchange) 事件,然后切换页面。
  • 基座应用加载执行 single-spa 时,也会给 window 对象注册 popstate (hashchange) 事件, popstate(hashchange) 的 calback 中,就是激活子应用的逻辑。当基座应用通过执行pushState(replaceState)、修改 hash、使用浏览器前进后退(go、back、forward)功能的方式修改 url 时,popstate(hashchange) 就会触发,相应的子应用的激活逻辑就会执行。
// 通过原生构造函数 - popStateEvent 创建一个popstate事件对象
function createPopStateEvent(state, originalMethodName) {var evt;try {evt = new PopStateEvent("popstate", {state: state    })} catch(err) {evt = document.createEvent('popstateevent')evt.initPopStateEvent("popstate", false, false, state)}evt.singleSpa = trueevt.singleSpaTrigger = originalMethodNamereturn evt
}
// 重写 updateState、replaceState 方法,通过 window.dispatchEvent 方法,手动触发 popstate 事件
function patchedUpdateState(updateState, methodName) {return function () {var urlBefore = window.location.href;var result = updateState.apply(this, arguments);var urlAfter = window.location.href;if (!urlRerouteOnly || urlBefore !== urlAfter) {window.dispatchEvent(createPopStateEvent(window.history.state, methodName));}return result;};
}
// 重写 pushState 方法
window.history.pushState = patchedUpdateState(window.history.pushState, "pushState");
// 重写 replaceState 方法
window.history.replaceState = patchedUpdateState(window.history.replaceState, "replaceState");
...
const router = new VueRouter({mode: 'history',base: '/app1',routes: [{path: '/foo',name: 'foo',component: {...}}, {path: '/bar',name: 'bar',component: {...}}]
})
...

application 模式下,single-spa 的工作流程,application 模式下,我们需要先通过registerApplication 注册子应用,然后在基座应用挂载完成以后执行 start 方法, 这样基座应用就可
以根据 url 的变化来进行子应用切换,激活对应的子应用。
在这里插入图片描述

parcel模式下,single-spa的工作流程。mountRootParcel 方法会返回一个parcel实例对象,内部包含update、unmount 方法。当我们需要更新组件时,直接调用parcel对象的update方法,就可以触发组件的update生命周期方法;当我们需要卸载组件时,直接调用parcel对象的unmount方法。在执行mountRootParcel 方法时,传入的第二个参数,会作为组件 mount 生命周期方法的入参;在执行 parcel.update 方法时,传入的参数,会作为组件 update 生命周期方法的入参。

子应用是否被挂载

  • NOT_LOADED 未加载/待加载
  • LOAD_SOURCE_CODE 加载源代码
  • NOT_SOURCE_CODE 未启动/待启动
  • BOOTSTRAPPING 子应用启动中
  • NOT_MOUNTRED 为挂载/待挂载
  • MOUNTING 子应用挂载中
  • UNMOUNTING 需要卸载
  • UNMOUNTED 已经卸载
  • LOAD_ERROR 子应用加载失败
传参

父组件和parcel组件的通信
mount 阶段,父组件在执行 mountRootParcel 时,可以将要传递给 parcel 组件的值作为第二个参数,这个参数会作为 parcel 组件 mount 方法执行时的入参,这样 parcel 组件就可以拿到父组件传递的值。update 阶段也一样,父组件执行 parcel.update 时,传入的参数会作为 parcel 组件 update 方法执行时的入参。
基座应用和子组件之间的通信
基座应用在定义路由注册表的时候,会给每个子应用定义一个customProps,这个customoProps会作为子应用mount方法的入参,在子应用中, customProps(或者 customProps 里面的某个值) 可以作为子应用的共享状态(使用 vuex、mobx、redux 等)。这样,当基座应用修改 customProps 时,子应用就可接受到通知,然后更新。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/382714.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高翔【自动驾驶与机器人中的SLAM技术】学习笔记(二)——带着问题的学习;一刷感受;环境搭建

按照作者在读者寄语中的说法&#xff1a;我们得榨干这本书的知识。 带着问题 为了更好的学习&#xff0c;我们最好带着问题去探索。 第一&#xff1a;核心问题与基础知识 如上图&#xff1a;这本书介绍了SLAM相关的核心问题和基础知识。王谷博士给我们做了梳理&#xff1a;…

人工智能学习笔记 - 初级篇Ⅱ - 图形可视化 - 第5节-设置刻度、刻度标签和网格

微信公众号&#xff1a;御风研墨 关注可了解更多。问题或建议&#xff0c;请公众号留言 文章目录 设置刻度、刻度标签和网格应用背景准备工作操作步骤工作原理补充说明最后 设置刻度、刻度标签和网格 应用背景 在数据可视化中&#xff0c;合理设置刻度、刻度标签和网格是提高…

【BUG】已解决:libpng warning: iccp: known incorrect sRGB profile

已解决&#xff1a;libpng warning: iccp: known incorrect sRGB profile 目录 已解决&#xff1a;libpng warning: iccp: known incorrect sRGB profile 【常见模块错误】 错误原因&#xff1a; 原因分析 解决方案 具体步骤 欢迎来到英杰社区https://bbs.csdn.net/topics…

MySQL第四次作业

&#xff08;一&#xff09;建立数据库及表 &#xff08;二&#xff09;处理表 1.修改student 表中年龄(sage)字段属性&#xff0c;数据类型由int 改变为smallint 2.为Course表中Cno 课程号字段设置索引,并查看索引 3.为SC表建立按学号(sno)和课程号(cno)组合的升序的主键索引…

python每日学习12:pandas库的用法(1)

python每日学习12&#xff1a;pandas库的用法&#xff08;1&#xff09; 安装 pip install pandas设定系统环境 import pandas as pd #设定自由列表输出最多为 10 行 pd.options.display.max_rows 10 # 显示当前 Pandas 版本号 pd.__version__进入jupyter notebook 页面 在终端…

乐室预约小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;公告信息管理&#xff0c;乐室信息管理&#xff0c;乐器分类管理&#xff0c;乐器管理&#xff0c;乐器知识管理&#xff0c;用户管理&#xff0c;用户预约管理&#xff0c;取消预约管理&#xff0c;用…

Rust代码答疑报错|Python一对一辅导答疑

Question 你好&#xff0c;我是悦创。 学员答疑&#xff1a; https://code.bornforthis.cn/?id4e72084d-1eaf-44ed-8067-744671491574https://code.bornforthis.cn/?id664ff169-41d6-409f-a05b-02ed42279759 问题代码&#xff1a; // You can bring module paths into sc…

MongoDB文档整理

过往mongodb文档&#xff1a; https://blog.csdn.net/qq_46921028/article/details/123361633https://blog.csdn.net/qq_46921028/article/details/131136935https://blog.csdn.net/qq_46921028/article/details/139247847 1. MongoDB前瞻 1、MongoDB概述&#xff1a; MongoDB是…

分享从零开始学习网络设备配置--任务6.1 实现计算机的安全接入

项目描述 随着网络技术的发展和应用范围的不断扩大&#xff0c;网络已经成为人们日常生活中必不可少的一部分。园区网作为给终端用户提供网络接入和基础服务的应用环境&#xff0c;其存在的网络安全隐患不断显现出来&#xff0c;如非人为的或自然力造成的故障、事故&#xff1b…

手写RPC-令牌桶限流算法实现,以及常见限流算法

为什么需要服务限流、降级 分布式架构下&#xff0c;不同服务之间频繁调用&#xff0c;对于某个具体的服务而言&#xff0c;可能会面临高并发场景。在这样的情况下&#xff0c;提供服务的每个服务节点就都可能由于访问量过大而引起一系列问题&#xff0c;比如业务处理耗时过长、…

px4ctrl里calculateControl的代码解析

px4ctrl的代码里将目标加速度转成飞控的rpy的calculateControl代码 LinearControl::LinearControl(Parameter_t &param) : param_(param) {resetThrustMapping(); } quadrotor_msgs::Px4ctrlDebug LinearControl::calculateControl(const Desired_State_t &des,const …

【Apache Doris】数据副本问题排查指南

【Apache Doris】数据副本问题排查指南 一、问题现象二、问题定位三、问题处理 本文主要分享Doris中数据副本异常的问题现象、问题定位以及如何处理此类问题。 一、问题现象 问题日志 查询报错 Failed to initialize storage reader, tablet{tablet_id}.xxx.xxx问题说明 查…

Linux下docker快速安装gitea

之前在服务器上装的gitlab来管理个人项目&#xff0c;但是gitlab服务启动后能明显感受到占用资源比较严重。最近服务器到期&#xff0c;换了个服务器还没来得及装gitlab&#xff0c;刚好最近接触到gitea&#xff0c;网上是这么说的 占用资源少&#xff0c;适合个人开发者&…

DeepFaceLive黄仙人高清模型416DFM

链接&#xff1a;https://pan.baidu.com/s/1b5nu23Z93bDcxgNyyR3KjA?pwdj8kz 提取码&#xff1a;j8kz 黄羿DF-5M-UDT416_320_80_80_26DFM

【ProtoBuf】通讯录实现(网络版)

Protobuf 还常用于通讯协议、服务端数据交换场景。那么在这个示例中&#xff0c;我们将实现一个网络版本的通讯录&#xff0c;模拟实现客户端与服务端的交互&#xff0c;通过 Protobuf 来实现各端之间的协议序列化。 需求如下&#xff1a; 客户端可以选择对通讯录进行以下操…

关于pycharm上push项目到gitee失败原因

版权声明&#xff1a;本文为博主原创文章&#xff0c;如需转载请贴上原博文链接&#xff1a;https://blog.csdn.net/u011628215/article/details/140577821?spm1001.2014.3001.5502 前言&#xff1a;最近新建项目push上gitee都没有问题&#xff0c;但是当在gitee网站进行了一个…

新生上大学提前去西藏旅游有什么要注意的,语言上该怎么办?

新生前往西藏旅游并提前适应大学生活是一次充满挑战与发现的旅程。在准备过程中&#xff0c;重要的是要对高原反应有所准备&#xff0c;了解其症状并采取预防措施&#xff0c;同时携带必要的防晒和保暖衣物以应对极端的气候条件。在交通和饮食方面&#xff0c;选择安全可靠的选…

第二证券:回购队伍持续扩容!这类公司行动

近期&#xff0c;上市公司密布发布回购方案&#xff0c;一些中期成果较好的公司赫然在列。除了发布正式的回购方案&#xff0c;部分上市公司控股股东、实践控制人、董事长、总经理提议回购公司股份。 绩优股活泼回购 7月23日晚&#xff0c;包括圣泉集团、中科三环、翔楼新材在…

IntelliJ IDEA 直接在软件中更新为最新版

当我们的 IDEA 工具许久没有更新&#xff0c;已经拖了好几个版本&#xff0c;想跨大版本更新&#xff0c;比如从2020.2.1 -> 2023.x.x 此时&#xff0c;我们菜单栏点击 Help -> Check for Updates… &#xff0c;右下角会有提示更新&#xff0c;如下图&#xff1a; 点…

Unity Shader - 2024 工具篇

目录 IDE 工具建议 IDE工具 Sublime 3 大势所趋&#xff0c;但是Sublime 使用插件还是相当的不习惯 代码跳转 Go to definite IDE 工具建议 () what is the best ide for coding shaderlab - #4 by DaveAstator - Unity Engine - Unity Discussions​​​​​​​I IDE工…