微前端解决方案

        在实施微前端架构时,前端框架和技术的选型是非常重要的。不同的框架和技术有着不同的优缺点,需要结合具体的应用场景进行选择。

一、常见的微前端解决方案

Web Components

        Web Components(包括Custom Elements、Shadow DOM和HTML Imports)是浏览器原生支持的组件封装技术,允许开发者创建可复用的自定义元素,这些元素包含了完整的HTML结构、CSS样式和JavaScript逻辑。这种封装机制为微前端架构的实现提供了天然的土壤,使得不同子应用可以在同一页面上共存,同时保持各自的独立性和封装性。

  • 原理:利用标准化的Web组件技术封装各个子应用,每个子应用作为一个独立的可复用的Web Component或自定义元素,这些组件可以直接在DOM中插入并独立运行。

优点:

  • CSS和JavaScript天然隔离,避免了样式冲突和脚本污染,拥有对应的用于单独部署子应用组件的域名

  • 多个子应用可以并存,支持并行开发和独立部署

  • 代码的可读性变得非常清晰,组件资源内部高内聚,组件资源由自身加载控制

  • 原生浏览器支持,不依赖于特定的框架或库

    缺点:

  • 浏览器和框架的支持不够:浏览器实现不一致,存在向后不兼容的版本问题,需要额外的polyfills支持

  • 开发成本较高:需要重写现有的前端应用,在整个前端应用上把它们全部转换成Web Components

  • 系统架构复杂:当应用被拆分为一个又一个的组件时,组件间通信需要额外设计

Shadow DOM

        Shadow DOM 是一种浏览器的 Web 组件技术,是一种将HTML结构、样式和行为封装在一个独立的、封闭的DOM中的机制。它允许开发者将一个 Web 组件的样式和结构隐藏在组件作用域内,防止其与全局样式或逻辑发生冲突,创建一个封装的影子树(Shadow Tree),这个影子树对于外部是不可见的,它与组件的外部 DOM 树(也称为 Light DOM)是隔离的。在同一页面上运行多个互不干扰的前端环境。

  • 原理:通过将HTML结构、样式和行为封装在一个独立的、封闭的DOM(即Shadow Tree)中,实现组件的封装和隔离,防止与全局样式或逻辑发生冲突。

优点:

  • 封装性:提供了强大的封装能力,允许开发者将HTML结构、CSS样式和JavaScript代码封装在一个独立的DOM子树中,这些子树与主文档DOM树保持分离,从而保证了组件内部代码的隔离性和干净整洁

  • 样式隔离:内部定义的CSS样式只在其作用域内有效,不会影响到外部文档,这有助于防止样式冲突,使得组件的样式更加独立和可控

  • 简化组件开发:通过封装,开发者可以更容易地创建可复用的Web组件,而无需担心组件内部实现细节对外部的影响,这有助于提高开发效率和组件的可维护性

缺点:

  • 兼容性:部分浏览器不完全支持

  • 调试困难:由于Shadow DOM的封装性,内部DOM结构不易直接访问,增加调试复杂度

  • 第三方集成限制:可能影响与第三方库或服务的集成,某些第三方库或扩展可能无法直接处理或解析Shadow DOM内容,因为它们不是为处理Shadow DOM而设计的,或者需要额外的配置才能与Shadow DOM兼容

iframe

        iframe是一种HTML元素,允许在一个文档(父页面)中嵌入另一个文档(子页面),通过设置url 来做微应用的划分,使用 Iframe 可以将一个应用嵌入到另一个应用中,将不同的微前端应用程序嵌入到主应用程序的页面中,从而实现微前端的隔离和独立部署。在主应用中嵌入多个iframe,每个子应用在一个单独的iframe中运行,通过消息传递机制(如postMessage)进行通信。

        它提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决,应用之间不会互相干扰。但最大问题也在于它的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题,还存在如安全性和性能等方面的问题。

  • 原理:每个子应用在一个单独的iframe中运行,通过消息传递机制(如postMessage API)进行通信,通过在主应用页面中嵌入iframe标签,并设置其src属性为子应用的URL,从而实现将多个独立的前端应用聚合到同一个页面中。

优点:

  • 实现简单且隔离性强:iframe提供了天然的沙箱环境,web应用隔离的非常完美,无论是js、css、dom都完全隔离开来,互不影响

  • 消息传递:只要每个iframe同源,可以使用Window. postMessageAPI来进行消息传递

缺点:

  • 通信复杂且状态管理困难:iFrame间的通信方式(如postMessage、contentWindow访问或父子页面直接方法调用)相对繁琐,需制定复杂的通讯规范,,状态管理和公共依赖处理不如其他微前端方案高效,由于子父应用隔离,iframe 内外系统的通信、数据同步交互差,且URL状态不同步

  • 全局上下文完全隔离,内存变量不共享:子应用切换时可能需要重新登录,体验不好,iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的微应用中实现免登效果

  • 路由和URL管理受限:路由状态不保活, iframe 的页面 url 中的状态信息并不能同步到父窗口,刷新iFrame会丢失其URL状态,无法使用浏览器的前进后退功能,需要配合存储解决

  • DOM隔离与交互限制:DOM结构不共享,iframe内的DOM与主页面完全隔离,限制了交互能力,iframe 的页面布局只针对于 iframe 窗口,如弹窗无法覆盖全局,弹窗只能在 iframe 内部展示,无法无法突破其本身覆盖全局,并且事件传递上存在者很大的问题,例如拖拽

  • 性能问题:加载性能差,白屏时间长,不适合SPA应用,资源竞争可能影响页面加载速度,且每次加载都是新实例,整个应用全量资源加载,每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程,加载慢

  • 样式和布局挑战:样式难以控制,全屏样式可能影响全局布局,UI不同步,iFrame内容独立,拥有自己的 CSS 样式和布局上下文,难以实现全局样式的一致性,以及子应用之间的布局和交互的协调

  • 资源竞争:可能因资源竞争影响页面加载速度,iFrame与主页面共享连接池,而浏览器对相同域的连接有限制,因此会影响页面的并行加载,出现iframe中的资源占⽤了可用连接而阻塞了主页面的资源加载,Bundle的大小各异,构建时不能提取公共依赖关系

  • 安全性与跨域限制:由于安全策略的限制,跨域iFrame通信受限,需处理复杂的安全策略问题

  • 生命周期管理复杂:iframe的生命周期管理(如加载、渲染、卸载等)需要额外处理,处理不当可能影响用户体验

  • 资源加载阻塞:iframe可能阻塞主页面的onload事件,影响页面加载效率

  • 不利于SEO,预加载难以实现

基于服务端渲染的解决方案 SSR

        服务端渲染可以将微前端应用程序的 HTML 和 JavaScript 在服务器端进行预处理,从而减少客户端的加载和渲染时间。这种解决方案可以提高性能和 SEO,但是也需要在服务器端增加额外的负载。

  • 原理:在服务器端完成页面的HTML结构拼接处理,包括路由匹配、数据预取等,然后将生成的HTML页面直接发送给浏览器,再由浏览器进行展示。

优点:

  • 性能优化:减少首屏加载时间,因为HTML内容已经在服务器上渲染完成,客户端只需接收和显示

  • SEO友好:搜索引擎爬虫能够直接获取到渲染后的HTML内容,有利于网站内容的索引和排名

  • 更好的用户体验:对于依赖大量数据的页面,服务端渲染能够更快地显示关键内容,提升用户体验

  • 代码共享:在某些情况下,服务端渲染可以更容易地实现代码共享,特别是当服务器和客户端使用相同或相似的技术栈时,这有助于减少代码重复和提高开发效率

缺点:

  • 服务器资源消耗大:增加服务器的CPU和内存消耗,特别是在高流量情况下,需要更多的资源支持

  • 开发复杂度增加:需要处理服务器和客户端之间的数据同步、状态管理等,开发门槛相对较高

  • 缓存和CDN限制:动态生成的页面内容可能难以有效利用缓存和CDN,影响页面加载速度和可伸缩性

  • 状态管理困难:在SSR中,由于服务器端和客户端都需要处理数据和状态,因此需要更加复杂的状态管理机制来确保数据的一致性和同步性

基于 JavaScript 模块加载器的解决方案

        使用 JavaScript 模块加载器可以将不同的微前端应用程序作为独立的模块,在需要时动态加载这些模块,然后将渲染好的页面直接发送给客户端浏览器,从而减少了客户端的加载和渲染时间,实现微前端的隔离和独立部署。这种解决方案可以提高可维护性和扩展性,但是也需要使用特定的 JavaScript 模块加载器,如 SystemJS 或者 Webpack 等。

  • 原理:将子应用分割成可动态加载的部分,主应用根据需要动态请求并执行子应用的代码。

优点:

  • 按需加载和性能优化:减少加载时间,提升用户体验

  • 易于扩展和维护:支持轻松添加或替换功能模块

  • 支持多种模块规范:灵活选择适合项目的模块规范

缺点:

  • 配置复杂性:使用模块加载器需要进行一定的配置工作,包括模块路径、依赖关系、加载顺序等

  • 调试难度:由于模块之间的隔离和封装,当出现问题时可能需要跨模块进行调试,增加了调试的难度和复杂性

  • 兼容性问题:不同的浏览器和JavaScript环境对模块加载器的支持程度可能不同,这可能会导致兼容性问题

  • 模块间通信成本:模块间通信可能增加额外成本

基于微服务网关路由分发(路由分发式微前端)

        通过HTTP服务器的反向代理功能或应用框架自带的路由机制,将不同的业务请求分发到对应的独立前端应用上,允许不同的子应用负责不同的路由空间,根据用户访问的路由动态加载对应的应用。

        最常用的方案是通过 http服务的反向代理来实现。其实就是把一个大型项目拆分成多个微应用,每个微前端服务负责应用中的一个特定部分或功能,然后通过微服务网关(如Nginx、Zuul等)进行路由分发,确保用户请求能够正确转发到相应的前端服务,比如通过 Nginx 配置代理映射到不同的子应用上,这也叫路由分发式微前端。不同的子应用负责不同的路由空间,根据路由变化,加载对应的前端应用。

这种方式看上去更像是多个前端应用的聚合,即我们只是将这些不同的前端应用拼凑到一起,使他们看起来像是一个完整的整体。但是它们并不是,每次用户从 A 应用到 B 应用的时候,往往需要刷新一下页面。

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

通过上述配置,不同页面的请求就可以分发到不同的服务器上。

  • 原理:通过微服务网关(如Nginx、Zuul等)的路由分发功能,将用户请求映射到不同的独立前端应用上,每个微前端服务负责处理特定路由的业务逻辑和界面渲染,实现应用的拆分、独立部署和按需加载。

优点:

  • 实现简单、快速、易配置

  • 不需要对现有应用进行改造,允许现有的前端应用作为微前端服务直接集成 缺点:

  • 用户体验不好,在切换应用时会触发浏览器刷新,如果每个子应用都维护自己的会话状态,那么用户在切换子应用时可能需要重新登录

  • 多个子应用无法并存,由于每个请求都直接映射到一个子应用,因此默认情况下,用户只能看到一个子应用的界面

  • 应用状态管理困难,在多个微前端服务之间共享状态可能变得复杂,尤其是在没有统一状态管理方案的情况下

  • 子应用之间的通信比较困难,可能会遇到跨域请求的问题

组合式应用路由分发(中心基座方案)

该方案的核心是主从思想,即包括一个基座(MainApp)应用和若干个微(MicroApp)应用。

① 基座应用:通常是一个前端SPA项目,负责整个系统的应用注册、路由映射、消息下发等核心功能。

② 微应用:独立前端项目,这些项目不限于采用 React,Vue,Angular 或者 JQuery 开发,每个微应用注册到基座应用中,由基座进行管理,也可以脱离基座单独访问。

  • 原理:通过一个中心基座应用来管理多个独立的微应用,基座应用负责应用注册、路由映射和消息传递等核心功能,而微应用则以独立前端项目的形式存在,可以注册到基座中由基座统一管理,也可以独立运行。用户访问时,基座应用根据路由动态加载并渲染对应的微应用,实现应用的模块化、独立开发和部署。

        基本的流程如下图所示:

优点:

  • 技术不限制: 可以各自使用完全不同的前端框架

  • 无感切换: 因为是一个 SPA 项目,所以切换时不会感觉到页面的刷新或重载,体验极佳

  • 利于SEO,通过使用SPA框架和服务器端渲染(SSR)等技术,可以优化搜索引擎对内容的抓取和索引

  • 独立开发与部署,降低了系统之间的耦合度,提高了开发效率

  • 微前端优势几乎都有,包括资源复用、技术栈多样性、快速迭代等微前端架构的常见优势

    缺点:

  • 沙箱不隔离: 也就是 js 与 css 样式会出现冲突的问题

  • 配置复杂:为了实现微应用之间的无缝集成和路由分发,基座应用需要进行复杂的配置,包括路由映射、资源加载、样式隔离等

  • 性能考虑:虽然微前端架构可以提高资源的复用率,但在某些情况下,加载多个微应用可能会导致页面加载时间的增加

  • 调试困难:由于微应用之间可能存在复杂的依赖和交互关系,因此在出现问题时,调试可能会变得比较困难

容器化方案

        主要是通过容器化技术(如Docker)将前端应用及其所有依赖项打包成独立的容器镜像,并在容器环境中运行,开发者能够确保应用在不同环境中的一致性和可移植性。当容器被部署到任何支持容器技术的环境中时,它都能以相同的方式运行,无需担心环境差异带来的兼容性问题。这种方式允许前端应用以独立的服务形式存在,并通过API进行通信和集成。同时,也可以利用Webpack模块联邦等工具实现前端应用的模块化和共享。

  • 原理:利用容器化技术(如Docker)封装前端应用及其环境,通过容器编排实现应用的独立、可移植、可扩展部署与管理。

优点:

  • 提高应用的可移植性和可扩展性:容器化确保应用在不同环境中一致运行,并轻松应对负载增加

  • 便于在多个环境中部署和运维:自动化工具支持容器化应用的快速部署、回滚和扩展,简化运维流程

  • 促进前后端分离和微服务架构:容器化使前端应用独立运行,通过API与后端服务通信,促进模块化

缺点:

  • 需要掌握容器化技术的相关知识:团队成员需学习Docker、Kubernetes等新技术和工具

  • 可能增加系统的复杂性和运维成本:容器化引入新架构和运维挑战,需额外工具和流程支持

  • 容器化可能不是所有情况的最佳选择:小型项目或团队可能因复杂度和成本考虑而不适合容器化

webpack5: Module Fedearation

        webpack5 提供一个新特性 module fedaration(模块联邦),允许将JavaScript应用程序拆分成独立的模块,并在不同的Webpack构建中共享这些模块。可以帮助将多个独立的构建组成一个应用程序, 不同的构建可以独立开发与部署。允许每个模块(或子应用)暴露自己的入口点和共享模块给其他模块使用,同时也能够远程加载并执行其他模块暴露的入口点和模块。

基于这个特性,我们可以在一个 js 应用中动态加载并运行另一个js 应用的代码,在一个应用里动态渲染另一个应用的页面,并实现应用之间的依赖共享,这样也就实现了多个子应用的聚合。

  • 原理:通过配置 Webpack 的 Module Federation 插件,可以将不同的应用打包成独立的模块,并在需要时从其他应用中动态加载这些模块。

优点:

  • 开箱即用:只需要执行几行命令即可拉取相应的模块代码并把项目跑起来,包括基座应用和微前端应用,无需处理构建工具的复杂配置

  • 独立开发与部署:基于提供的代理工具,在单独开发微应用时需启动基座或者其它微应用,应用启动后,无需加载与自己无关的资源

  • 去中心化,子应用依赖解耦:通过模块共享的方式避免了传统微前端架构中的中心基座依赖,使得系统更加灵活和可扩展

  • 相同资源不需要重复加载:组件共享,与npm发包类似的组件共享管理,相同的资源在多个应用间共享,避免了重复加载

  • 不需要对原有应用进行改造,主要集中于打包脚本的调整,对应用代码的影响较小

  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验

  • 多个子应用可并存(通过动态加载的方式,支持在运行时动态加载和执行远程应用的代码,实现了应用的灵活聚合)

    缺点:

  • 无法沙箱隔离:没有有效的CSS沙箱和JavaScript沙箱,需借助其它工具和框架才能做到应用层面的隔离

  • 对Webpack强依赖,老旧项目不友好:构建工具只能使用 webpack5 版本以上,对已有项目使用旧版本 Webpack 的情况不友好,需进行升级和改造

  • 代码封闭性高:依旧需要做npm那一套管理和额外的拉取代码,需要仔细管理不同模块之间的依赖关系,以避免版本冲突

  • 拆分粒度需要权衡:共享的lib无法做到tree-shaking,可能引入不必要的代码

  • 依赖前置:可能需要预加载一些依赖,导致时间加载变长

  • 主、子应用的路由可能发生冲突

二、微前端框架

single-spa

Single-SPA管理一个主路由,根据路由的变化动态地加载和卸载子应用。每个子应用都是独立的,拥有自己的路由和生命周期,但在主应用的上下文中运行。

        一个将多个单页面应用聚合为一个整体应用的 JavaScript 微前端框架,实际上就是一个聚合,使用这个库可以让应用使用多个不同的技术栈进行同步开发,最后使用一个公用的路由去实现完美的切换。在single-spa方案中,应用被分为两类:基座应用和子应用。其中,子应用就是需要聚合的子应用;而基座应用,是另外一个单独的应用,用于聚合子应用。采用的是 JS entry,它通过监听 URL 变化并在路由级别管理各个子应用的加载、挂载和卸载过程。子应用需要暴露特定的生命周期钩子函数(如 bootstrap、mount 和 unmount)以便与 single-spa 框架集成。

        single-spa实现微前端的整体流程:

  • 资源模块加载器:专为加载子项目初始化资源设计的。它将子项目的入口JavaScript文件构建为UMD格式,并利用模块加载器(如SystemJs,但非必须)远程加载这些资源。

  • 子应用资源配置表:负责存储每个子应用入口资源的URL,确保在切换子应用时,能够迅速通过加载器加载到最新版本。由于子应用更新会改变资源文件的hash值,服务端需定期更新此配置表,以保证框架加载的是最新资源。

  • 值得注意的是,single-spa原生不支持直接管理子应用资源列表。每个子应用需将其所有初始化资源打包至单一入口文件。若子应用初始化资源分散于多个文件,可利用webpack-manifest-plugin等工具生成资源清单,并据此进行额外处理,实现多文件资源的有效加载。

        核心原理: 在 基座 (主) 应用 中注册所有 App 的路由,single-spa 保存各子应用的路由映射关系,充当微前端控制器 Controler,当对应的 URL 变换时,除了匹配基座应用本身的路由外,还会匹配子应用路由并加载渲染子应用。single-spa是一个顶层路由,当路由处于活动状态时,它会下载并执行该路由的相关代码。通过劫持路由的方式来做子应用之间的切换,但接入方式需要融合自身的路由,有一定的局限性。

        和单页应用的实现原理类似,single-spa 会在基座应用中维护一个路由注册表,每个路由对应一个子应用。基座应用启动后,当我们切换路由时,如果是一个新的子应用,会动态获取子应用的js脚本,然后执行脚本并渲染出相应的页面;如果是一个访问过的子应用,那么就会从缓存中获取已经缓存的子应用,激活子应用并渲染出对应的页面。(核心思想: 路由劫持 === >应用加载

优点:

  • 在同一页面上使用多个前端框架而不用刷新页面

  • 独立开发、独立部署每一个单页面应用

  • 新功能使用新框架,旧的单页应用不用重写可以共存

  • 改善初始加载时间,延迟加载代码

    缺点:

  • 不支持Js沙箱、样式隔离,容易会出现Js冲突,样式污染,window对象的穿透问题等

  • 不支持元素隔离、预加载等

  • 路由管理复杂:需要仔细设计路由规则,以确保子应用之间的路由不冲突

  • 无通信机制

  • 状态管理挑战:由于子应用是独立运行的,因此状态管理(如全局状态)需要额外的考虑和设计

  • 只支持 JS entry,限制了它只能支持 vue 、 react 、 angular 等技术开发的项目,对一些 jQuery 老项目则无能为力

  • 调试和监控难度增加:随着应用规模的扩大,调试和监控多个子应用可能变得更加复杂

single-spa是通过监听url change事件,在路由变化时匹配到渲染的子应用并进行渲染,这个思路也是目前实现微前端的主流方式。同时single-spa要求子应用修改渲染逻辑并暴露出三个方法:bootstrapmountunmount,分别对应初始化、渲染和卸载,这也导致子应用需要对入口文件进行修改。因为qiankun是基于single-spa进行封装的,所以这些特点也被qiankui继承下来,并且需要对webpack配置进行一些修改。

qiankun

Qiankun 在 single-spa 的基础上,增加了应用加载、沙箱隔离、资源预加载等特性,使得微前端的实现更加简单和高效。

        qiankun(阿里蚂蚁金服)是一个基于 single-spa 进行二次开发的微前端框架,旨在提供更简单、无痛的构建一个生产可用微前端架构系统。和 single-spa 一样,qiankun 也能提供类似单页应用的用户体验,同时也支持按需加载和运行时动态注入资源,具有较高的灵活性和扩展性。可以认为是由single-spa和import-html-entry两个库结合,并进行二次开发的产物,在框架层面解决了使用single-spa 时需要开发人员自己编写子应用加载、通信、隔离等逻辑的问题。通过 import-html-entry 包解析 HTML 获取资源路径,然后对资源进行解析、加载。

  • 子应用加载:使用的是HTML Entry,通过动态创建 script 标签的方式加载子应用的入口文件,加载完成后,会执行子应用暴露出的生命周期函数

  • JS沙箱:使用的是ProxySandbox,通过 Proxy 对象创建了一个 JavaScript 沙箱,用于隔离子应用的全局变量,防止子应用之间的全局变量污染

  • CSS沙箱:有两种方式,一种是严格样式隔离,通过 shadow dom 来实现,另一种是实验性的样式隔离,就是 scoped css,两种方式不可共存。通过动态添加和移除样式标签的方式实现样式隔离,当子应用启动时,会动态添加子应用的样式标签,当子应用卸载时,会移除子应用的样式标签

  • 父子应用通信:使用的是GlobalState,原理其实就是上面提到的全局公共BUS, 提供了一个全局的通信机制,允许子应用之间进行通信

  • 基于路由的动态加载:qiankun的路由系统可以实现根据路由动态加载子应用,在用户访问不同的页面时,qiankun会根据当前页面的路由信息动态加载相应的子应用,从而实现多个子应用的集成

  • 增加资源预加载能力,预先子应用html、js、css资源缓存下来,加快子应用的打开速度

        子应用 dom 结构如下:

优点:

  • HTML entry 及沙箱的设计使得接入微应用像使用 iframe 一样简单,既支持 JS entry,又支持 HTML entry,不必像 single-spa 那样需要手动梳理资源链接

  • 切换应用时,浏览器不用重载页面,提供和单页面一样的用户体验,监听路由自动的加载、卸载当前路由对应的子应用

  • 路由保持,浏览器刷新、前进、后退,都可以作用到子应用

  • 相比single-spa,解决了子应用加载、应用隔离、子应用通信等问题,通过 Proxy 和 iframe 等技术实现了样式隔离和脚本隔离,避免了子应用之间的冲突

  • 丰富的插件系统:支持通过插件扩展功能,如应用间的通信、状态共享等,提供了更加开箱即用的 API

  • 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度

  • 多个子应用可并存,应用间通信简单,全局注入

    缺点:

  • 子应用接入成本较高,需要对原有应用进行改造,应用要兼容接入qiankun和独立使用,从 webpack、代码、路由等等都要做一系列的适配

  • 可能对一些 jQuery 老项目支持性不是特别好

  • 相同资源重复加载

  • 启动应用时,要先启动基座应用

  • 无法支持 vite 等 ESM 脚本运行

  • 基于路由匹配,无法同时激活多个子应用,也不支持子应用保活

  • css 沙箱无法绝对的隔离,js 沙箱在某些场景下执行性能下降严重

wujie

        wujie(腾讯)是一款基于 Web Components + iframe 的微前端架,很好地解决了Iframe做沙箱的痛点,简单说,无界的方案就是:JS 放 iframe 里运行,DOM 放 webComponent 渲染。

在应用 A 中构造一个shadowRoot 和iframe,然后将应用 B 的html写入shadowRoot中,js运行在iframe中,因为iframe的js隔离真的很完美。即:子应用加载在一个shadowRoot里,JS在iframe中执行并代理到这个shadowRoot上。

  • 子应用加载:Htmlentry + 渲染到shadowRoot上

    创建了一个标签名为wujie-app的Webcomponent,JS、CSS加载。

  • JS沙箱

    基本原理:直接把js丢在一个隐藏的iframe里执行

    细节:在iframe中拦截document对象,统一将dom指向shadowRoot,此时比如新建元素、弹窗或者冒泡组件就可以正常约束在shadowRoot内部。

  • CSS沙箱

    基于上面说的shadowRoot

  • 父子应用通信

    • Props 注入

    子应用通过 $wujie.props 可以拿到主应用注入的数据

    • window.parent 通信

window.document.querySelector("iframe[name=子应用id]").contentWindow.xxx
// 子应用调用
window.parent.xxx
  • 去中心化的通信

    上面提到的EventBus

优点:

  • 极速、应用保活

  • 开箱即用,相比 qiankun 接入成本更低

  • 子应用理论上不需要做任何改造

  • iframe 沙箱隔离性好、原生性能

  • vite 兼容性好

    缺点:

  • 需要时间学习、坑比较多

  • 对于不支持 webcompnent 的浏览器没有做降级处理

  • 长期维护性一般、内存开销较大

  • 目前还比较新,社区相对不够活跃

micro-app

        micro-app (京东)是一个基于 Web Components 的前端微服务框架,支持多种前端框架。它是目前市面上接入微前端成本最低的框架,并且提供了 JS沙箱、样式隔离、元素隔离、预加载、资源地址补全、插件系统、数据通信 等一系列完善的功能。它的特点就是取各家所长,最终成为了功能最丰富的微前端框架。

样式隔离方案与 qiankun 的实验方案类似,也是在运行时给子应用中所有的样式规则增加一个特殊标识来限定 css 作用范围。

子应用路由同步方案与 wujie 类似,也是通过劫持路由跳转方法,同步记录到 url 的 query 中,刷新时读取并恢复。

组件化的使用方式与 wujie 方案类似,这也是 micro-app 主打的宣传点。

它内置了两种沙箱:①类 qiankun 的 with 代理沙箱,据说相比 qiankun 性能高点,但目前微前端框架界并没有一个权威的基准性能测试依据,所以并无有效依据支撑。②类 wujie 的 iframe 沙箱,用于兼容 vite 场景。开发者可以根据自身的实际情况自由选择。

优点:

  • 兼容所有框架,支持的功能最丰富:为了保证各个业务之间独立开发、独立部署的能力,micro-app做了诸多兼容,在任何技术框架中都可以正常运行

  • 接入成本低、零依赖、使用简单:将所有功能都封装到一个类WebComponent组件内,从而实现在基座应用中嵌入一行代码即可渲染一个微前端应用

  • 开箱即用:提供了is沙箱、样式隔离、元素隔离、预加载、数据通信、静态资源补全、插件系统等一系列完善的功能

    缺点:

  • 功能丰富导致配置项与 api 太多

  • 对于不支持 webcompnent 的浏览器没有做降级处理

  • 静态资源补全问题:静态资源补全是基于父应用的,而非子应用则需要开发者自己手动解决

  • 0.x版本 vite支持不是很好,使用的时候需要关闭沙箱;1.x版本 支持vite,需要采用iframe沙箱模式,这点和wujie的方案一样了,都是webComponent + iframe

借鉴了WebComponent的思想,通过CustomElement结合自定义的ShadowDom,将微前端封装成一个类WebComponent组件,从而实现微前端的组件化渲染。并且由于自定义ShadowDom的隔离特性,micro-app不需要像single-spaqiankun一样要求子应用修改渲染逻辑并暴露出方法,也不需要修改webpack配置,是目前市面上接入微前端成本最低的方案。

EMP

        EMP(欢聚时代)是一款基于Webpack5 Module Federation构建的微前端解决方案。与其他微前端方案相比,它在处理跨框架和状态管理时可能面临一定的复杂性。然而,EMP的主要优势在于其强大的项目解耦能力,而非专注于多系统的直接聚合。这一特点使得EMP更接近于像bit这样的跨项目组件复用平台,专注于提升组件和模块的可重用性与独立性。 ​ 优点:

  • 依赖自动管理,可以共享 Host 中的依赖,版本不满足要求时自动 fallback 到 Remote 中依赖

  • 共享模块粒度自由掌控,小到一个单独组件,大到一个完整应用。既实现了组件级别的复用,又实现了微服务的基本功能

  • 共享模块非常灵活,模块中所有组件都可以通过异步加载调用

缺点:

  • 无法做到多框架兼容等微前端方案的痛点

  • 基于 Webpack5 Module Federation,需要统一 Webpack5 技术

  • 文档资料,社区不够活跃

Garfish

        Garfish(字节跳动)旨在应对现代Web应用面临的两大挑战:前端技术生态的繁荣与Web应用本身的复杂化。它有效解决了跨团队协作的难题,支持多样化的技术体系,并简化了复杂应用的开发与管理。经过大量线上应用的实践验证,Garfish功能稳定可靠,为开发团队提供了强大的支持。 ​ 优点:

  • 高效预加载:Garfish 强大预加载机制,根据用户习惯智能加载,显著缩短应用切换时间

  • 依赖共享:支持依赖共享,减少重复加载,大幅降低整体包体积

  • 数据监控:内置数据收集功能,实时监控应用运行状态,助力问题排查与性能优化

  • 多实例运行:支持多实例同时运行,增强业务拆分灵活性,满足复杂场景需求

  • 灵活接入:通过 Loader 支持多种入口方式(HTML/JS),简化微前端应用接入流程

  • 路由隔离:Router 模块实现路由驱动与主子路由隔离,简化配置,自动渲染与销毁

  • 运行时隔离:Sandbox 模块提供运行时隔离,避免 JS、CSS 副作用影响,确保应用稳定

缺点:

  • 架构复杂:增加系统复杂性,维护成本上升

  • 技术栈限制:可能不完全兼容所有技术栈,集成难度大

  • 性能调优:需要细致的性能调优,子应用增多可能影响性能

  • 调试困难:问题定位复杂,需了解整个系统架构

  • 学习成本:不熟悉微前端架构的开发者需投入时间学习

  • 社区支持有限:开源社区活跃度和文档可能不足

Bit

        Bit 是一款由国际开发团队开源的跨项目组件复用平台,它专注于将独立的组件进行构建、封装,并集中管理,以便在不同项目间轻松集成和复用这些组件。这一平台极大地提高了组件的可重用性和开发效率。 ​ 优点:

  • 安全性与健壮性:继承了传统单体式前端项目的安全性和健壮性特性,确保组件的可靠运行

  • 易于接入与高度可伸缩:提供简单的介入方式,同时支持高度的可伸缩性,满足不同规模项目的需求

  • 优化工作流程:通过解耦代码库、鼓励自治团队、定义清晰的小型API、建立独立的发布流程以及支持持续增量升级,增强了开发工作流程的效率与灵活性

  • 适用于组件化开发:严格意义上讲,Bit 与微前端在某些方面存在差异,因此它更适合那些以组件为核心开发模式,且技术栈相对统一的项目,有助于实现高效的组件复用和项目管理

缺点:

  • 技术栈限制:可能最适合技术栈较为统一的项目,对于技术栈多样化的项目可能兼容性较差

  • 学习曲线:对于新使用者来说,需要一定时间来熟悉其组件管理流程和工具链

  • 社区与文档:相比一些主流框架,其社区活跃度和文档丰富度可能稍逊一筹

参考资料:

一个写给初学者如何搞微前端的「从入门到放弃专栏」 - 掘金 (juejin.cn)

聊聊微前端的原理和实践-腾讯云开发者社区-腾讯云 (tencent.com)

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

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

相关文章

数据建设实践之大数据平台(一)准备环境

大数据组件版本信息 zookeeper-3.5.7hadoop-3.3.5mysql-5.7.28apache-hive-3.1.3spark-3.3.1dataxapache-dolphinscheduler-3.1.9大数据技术架构 大数据组件部署规划 node101node102node103node104node105datax datax datax ZK ZK ZK RM RM NM

HTML网页大设计-家乡普宁德安里

代码地址: https://pan.quark.cn/s/57e48c3b3292

二分图——AcWing 257. 关押罪犯

目录 二分图 定义 运用情况 注意事项 解题思路 AcWing 257. 关押罪犯 题目描述 运行代码 代码思路 改进思路 二分图 定义 二分图(Bipartite Graph)是一种特殊的图,在这种图中,顶点可以被分成两个互不相交的集合&…

C语言 | Leetcode C语言题解之第233题数字1的个数

题目: 题解: int countDigitOne(int n) {// mulk 表示 10^k// 在下面的代码中,可以发现 k 并没有被直接使用到(都是使用 10^k)// 但为了让代码看起来更加直观,这里保留了 klong long mulk 1;int ans 0;f…

硬盘HDD:AI时代的战略金矿?

在这个AI如火如荼的时代,你可能以为硬盘HDD已经像那些过时的诺基亚手机一样,被闪存和云存储淘汰到历史的尘埃里。但,别急着给HDD们举行退休派对,因为根据Finis Conner这位硬盘界的传奇人物的说法,它们非但没退场&#…

Linux进程——子进程详解

文章目录 查看进程的另一种方式如何创建子进程fork函数详解fork函数的用法fork函数做了什么为什么fork有两个返回值父子进程的运行顺序是什么样的为什么fork函数的两个返回值不同 在上一节中我们简单介绍了进程的概念,还有父进程和子进程 这篇文章的主要内容是介绍…

eNsp公司管理的网络NAT策略搭建

实验拓扑图 实验需求: 7,办公区设备可以通过电信链路和移动链路上网(多对多的NAT,并且需要保留一个公网IP不能用来转换) 8,分公司设备可以通过总公司的移动链路和电信链路访问到Dmz区的http服务器 9,多出口环境基于带…

护网HW面试——redis利用方式即复现

参考:https://xz.aliyun.com/t/13071 面试中经常会问到ssrf的打法,讲到ssrf那么就会讲到配合打内网的redis,本篇就介绍redis的打法。 未授权 原理: Redis默认情况下,会绑定在0.0.0.0:6379,如果没有采用相关…

暴雨让服务器不怕热҈热҈热҈热҈

在AI算力呈几何倍数增长的趋势下,算力逐渐朝着“高性能、高密度、高耗能“发展。在高耗能的算力下,AI服务器功率已逐步逼近风冷散热极限,而液冷作为更加高效、低能耗的制冷技术,逐渐成为了高密度算力散热场景的首选方案。 液冷的…

网络安全----防御----防火墙nat以及智能选路

前面要求在前一篇博客 网络安全----防御----防火墙安全策略组网-CSDN博客 7,办公区设备可以通过电信链路和移动链路上网(多对多的NAT,并且需要保留一个公网IP不能用来转换) 8,分公司设备可以通过总公司的移动链路和电信链路访问到Dmz区的ht…

Jenkins中Node节点与构建任务

目录 节点在 Jenkins 中的主要作用 1. 分布式构建 分布式处理 负载均衡 2. 提供不同的运行环境 多平台支持 特殊环境需求 3. 提高资源利用率 动态资源管理 云端集成 4. 提供隔离和安全性 任务隔离 权限控制 5. 提高可扩展性 横向扩展 高可用性 Jenkins 主服务…

Python excel知识库批量模糊匹配的3种方法实例(fuzzywuzzy\Gensim)

前言 当然,基于排序的模糊匹配(类似于Excel的VLOOKUP函数的模糊匹配模式)也属于模糊匹配的范畴,但那种过于简单,不是本文讨论的范畴。 本文主要讨论的是以公司名称或地址为主的字符串的模糊匹配。 使用编辑距离算法进…

Is Temperature the Creativity Parameter of Large Language Models?阅读笔记

最近有小伙伴来问LLM的参数该如何设计,废话不多说来看看paper吧。首先,常见的可以进行调参的几个值有temperature,top-p和top-k。今天这篇文章是关于temperature的。 原文链接:https://arxiv.org/abs/2405.00492 temperature如果…

OSPF.中DBD数据包

指定路由器---DR的身份 备份指定路由器---BDR的身份(RID)注意在一个广播域中的所有设备DR和BDR的认知必须统一。 只有DR和BDR会监听224.0.0.6的组播地址 会发出多个数据包 作用: 1.用来主从选举(没有携带lsa再要信息的DBD报文…

《斯科特·凯尔比的风光摄影手册》读书笔记

写在前面 《斯科特凯尔比的风光摄影手册》读书笔记整理没有全部读完,选择了感兴趣的章节理解不足小伙伴帮忙指正 😃,生活加油 99%的焦虑都来自于虚度时间和没有好好做事,所以唯一的解决办法就是行动起来,认真做完事情,…

LabVIEW心电信号自动测试系统

开发了一种基于LabVIEW的心电信号自动测试系统,通过LabVIEW开发的上位机软件,实现对心电信号的实时采集、分析和自动化测试。系统包括心电信号采集模块、信号处理模块和自动化测试模块,能够高效、准确地完成心电信号的测量与分析。 硬件系统…

计算机视觉之Vision Transformer图像分类

Vision Transformer(ViT)简介 自注意结构模型的发展,特别是Transformer模型的出现,极大推动了自然语言处理模型的发展。Transformers的计算效率和可扩展性使其能够训练具有超过100B参数的规模空前的模型。ViT是自然语言处理和计算…

prompt第一讲-prompt科普

文章目录 大语言模型输入要求中英翻译助手直接抛出问题描述问题描述(详细)问题描述案例问题描述案例上下文问题为什么要加入上下文 prompt总结prompt心得 大语言模型输入要求 大语言模型本质上就是一个NLP语言模型,语言模型其实就是接受一堆…

ubuntu服务器安装labelimg报错记录

文章目录 报错提示查看报错原因安装报错 报错提示 按照步骤安装完labelimg后,在终端输入labelImg后,报错: (labelimg) rootinteractive59753:~# labelImg ………………Got keys from plugin meta data ("xcb") QFactoryLoader::Q…

hutool处理excel时候空指针小记

如图所示&#xff0c;右侧的会识别不到 参考解决方案&#xff1a; /***Description: 填补空缺位置为null/空串*Param: hutool读取的list*return: 无*Author: y*date: 2024/7/13*/public static void formatHutoolExcelArr(List<List<Object>> list) {if (CollUtil…