当前位置: 首页 > article >正文

微前端介绍

微前端

  • 微前端介绍
    • 微前端定义
    • 微前端特点
  • 微前端常见框架
    • 路由分发式微前端
    • iframe
    • single-spa
    • qiankun
    • webpack5:module federation
    • Web Component
  • 微前端问题总结
    • js隔离

微前端介绍

微前端定义

微前端(Micro-Frontends)是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。
简单的说:微前端就是在一个Web应用中独立运行其他的Web应用

微前端特点

  1. 技术栈无关:主框架不限制接入应用的技术栈,微应用具备完全自主权;
  2. 独立开发、独立部署:微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新;
  3. 增量升级:在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略;
  4. 独立运行时:每个微应用之间状态隔离,运行时状态不共享;
  5. 环境隔离:应用之间 JavaScript、CSS 隔离避免互相影响;
  6. 消息通信:统一的通信方式,降低使用通信的成本;
  7. 依赖复用:解决依赖、公共逻辑需要重复维护的问题;

微前端常见框架

路由分发式微前端

路由分发式微前端,即通过路由将不同的业务分发到不同的独立前端应用上。最常用的方案是通过 HTTP 服务的反向代理来实现。

下面是一个基于路由分发的 Nginx 配置:


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

 - List item

{
                proxy_pass http://localhost:3002/api;
            }
            location / {
                proxy_pass /;
            }
        }
    }

优点:

  • 实现简单;
  • 不需要对现有应用进行改造;
  • 完全技术栈无关;

缺点:

  • 用户体验不好,每次切换应用时,浏览器都需要重新加载页面;
  • 多个子应用无法并存;
  • 局限性比较大;
  • 子应用之间的通信比较困难;
  • 子应用切换时需要重新登录;

iframe

iframe 作为一项非常古老的技术,也可以用于实现微前端。通过 iframe,我们可以很方便的将一个应用嵌入到另一个应用中,而且两个应用之间的 css 和 javascript 是相互隔离的,不会互相干扰。
优点:

实现简单;

  • css 和 js 天然隔离,互不干扰;
  • 完全技术栈无关;
  • 多个子应用可以并存;
  • 不需要对现有应用进行改造;

缺点:

  • 用户体验不好,每次切换应用时,浏览器需要重新加载页面;
  • UI 不同步,DOM 结构不共享;
  • 全局上下文完全隔离,内存变量不共享,子应用之间通信、数据同步过程比较复杂;
  • 对 SEO 不友好;
  • 子应用切换时可能需要重新登录,体验不好;

single-spa

single-spa 提供了新的技术方案,可以帮忙我们实现类似单页应用的体验。

single-spa 方案中,应用被分为两类:基座应用子应用。其中,子应用就是文章上面描述的需要聚合的子应用;而基座应用,是另外的一个单独的应用,用于聚合子应用

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

优点:

  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验;
  • 完全技术栈无关;
  • 多个子应用可并存;
  • 生态丰富;

缺点:

  • 需要对原有应用进行改造,应用要兼容接入 sing-spa 和独立使用;
  • 有额外的学习成本;
  • 使用复杂,关于子应用加载、应用隔离、子应用通信等问题,需要框架使用者自己实现;
  • 子应用间相同资源重复加载;
  • 启动应用时,要先启动基座应用;

qiankun

single-spa 一样,qiankun 也能给我们提供类似单页应用的用户体验。qiankun 是在 single-spa 的基础上做了二次开发,在框架层面解决了使用 single-spa 时需要开发人员自己编写子应用加载、通信、隔离等逻辑的问题,是一种比 single-spa 更优秀的微前端方案。

优点:

  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验;
  • 相比 single-spa,解决了子应用加载、应用隔离、子应用通信等问题,使用起来相对简单;
  • 完全和技术栈无关;
  • 多个子应用可并存;

缺点:

  • 需要对原有应用进行改造,应用要兼容接入 qiankun 和独立使用;
  • 有额外的学习成本;
  • 相同资源重复加载;
  • 启动应用时,要先启动基座应用;

webpack5:module federation

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

优点:

  • 不需要对原有应用进行改造,只需改造打包脚本;
  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验;
  • 多个子应用可并存;
  • 相同资源不需要重复加载;
  • 开发技术栈无关;
  • 应用启动后,无需加载与自己无关的资源;
  • 免登友好;

缺点:

  • 构建工具只能使用 webpack5;
  • 有额外的学习成本;
  • 对老项目不友好,需要对 webpack 进行改造;

Web Component

基于 Web ComponentShadow Dom 能力,我们也可以实现微前端,将多个子应用聚合起来。

Shadow Dom 的用法如下:

const shadow = document.querySelector('#hostElement').attachShadow({mode: 'open'});
// url 为应用的地址,基于 fetch,我们可以获取到应用的 html 模板,添加到指定节点下
fetch(url).then(res => {
    shadow.innerHTML = res
});

优点:

  • 实现简单;
  • css 和 js 天然隔离,互不干扰;
  • 完全技术栈无关;
  • 多个子应用可以并存;
  • 不需要对现有应用进行改造;

缺点:

  • 主要是浏览器兼容性问题;
  • 开发成本较高;

微前端问题总结

微前端框架中,js隔离样式隔离元素隔离是必须解决的三个问题,下面我们就来分别说说这三个问题是什么?怎么解决?

js隔离

问题:

情况1:都对全局变量赋值

应用A,写 window.r = 1;然后有应用B,又写 window.r = 2,这就乱套了

情况2:都设置事件

应用A,window.addEventListener(‘click’,()=>console.log(‘A’));
应用B,window.addEventListener(‘click’,()=>console.log(‘B’));,这就乱套了

解决:

方法一用 Proxy 代理

es2015 Reflect属于一个静态类或者设置属性等用法

const rawWindow = window
const proxyWindow = new Proxy({},{
    get: (target, key): unknown => {
        // 原 target 上有就返回,否则返回 rawWindow 属性
        return Reflect.has(target, key) ? Reflect.get(target, key) : Reflect.get(rawWindow, key)
    },
    set: (target, key, value): boolean => {
        if(!Object.prototype.hasOwnProperty.call(target, key) && Object.prototype.hasOwnProperty.call(rawWindow, key)){
            const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key)
            const { configurable, enumerable, writable, set } = descriptor!
            // set value because it can be set
            rawDefineProperty(target, key, {
              value,
              configurable,
              enumerable,
              writable: writable ?? !!set,
            })
        } else {
            Reflect.set(target, key, value)
        }
    }
})

window.r = 1window.addEventListener('click',()=>console.log('A')) 包括到自执行函数里面

A和B互不干扰

;(function(window){
    window.r = 1
    window.addEventListener('click',()=>console.log('A'))
})(proxyWindowA)
;(function(window){
    window.r = 2
    window.addEventListener('click',()=>console.log('B'))
})(proxyWindowB)

法二 用快照

快照隔离有个前提条件是,当前还有一个应用显示,不能出现多个应用并存显示在界面上,应用A,B切换时,比如当前应用是A,现在要切入到应用B

  • 暂存起来应用A的全局变量和事件
  • 恢复全局变量和事件到应用A之前
  • 检查之前是否保持有应用B的全局变量和事件,如果有,则载入

样式隔离

问题

同理,各个应用之前可能相互设置标签样式,会相互影响,或者影响全局样式,比如应用A给body设置样式,应用B也给body设置样式

方法一 样式增加不同前缀

每个应用通过前缀独立区分开,京东micro-app默认是采用的这个策略,唯一注意的一个小点是,基座样式会影响子应用的样式,所以需要注意基座中不要写太多样式

在这里插入图片描述
方法二 ShadawDom

大多数Html标签都有 attachShadow() 方法给指定的元素挂载一个 Shadow DOM。参数是openclosed

ShadawDom 样式绝对隔离,不用加前缀,如下图

//open 是外界可以访问到Element.shadowRoot再访问到内部元素,closed就是完全不能访问内部元素
var shadowroot = element.attachShadow('open|closed')  

在这里插入图片描述
元素隔离

元素隔离是 基座应用和子应用都有一个元素<div id='root'></div>,此时子应用通过document.querySelector('#root'),因为js隔离已经做了代理,此时document.querySelector只是子应用本身了


http://www.kler.cn/a/499905.html

相关文章:

  • 网工_网络体系结构
  • 索引页与B+树的关系
  • halcon三维点云数据处理(十)locate_cylinder_3d
  • VS Code的设置功能以及多层级的设置方式与解密
  • 海康机器人IPO,又近了一步
  • 青稞Talk预告!面向自动驾驶与物理世界对齐的视频生成模型
  • PY_11_07
  • 深入详解自然语言处理(NLP)中的语言模型:BERT、GPT及其他预训练模型的原理与应用
  • Qt学习笔记第81到90讲
  • SpringBoot日常:集成Kafka
  • 【深度学习】数据预处理
  • vue3的v-for 与 v-if
  • React setState详细使用总结
  • Bytebase 3.1.0 - 通过 Google / GitHub SSO 功能开放给专业版
  • C语言gdb调试
  • 14.C语言Union详解:节省内存的利器
  • GaussDB分布式数据倾斜处理
  • 2021 年 3 月青少年软编等考 C 语言五级真题解析
  • 如何使用MVC模式设计和实现校园自助点餐系统的微信小程序
  • Day04-后端Web基础(Maven基础)
  • uniApp通过xgplayer(西瓜播放器)接入视频实时监控