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

关于qiankun沙箱sandbox(面试题)

为什么要有js资源隔离机制?

主应用和子应用,相同的全局变量,可能会发生冲突,子应用和子应用之间,相同的全局变量,也可能会发生冲突。在这里我们主要指的就是window。

思路:打开沙箱时能够修改属性值;关闭沙箱时恢复未开启沙箱前的属性值,并且要记录修改了哪些属性。

qiankun.js隔离机制

SnapshotSandBox

快照沙箱,支持单个微应用

class SnapShotBox {
    windowSnap = {} //保存window上原本的属性值
    modifyPropMap = {} //记录修改的属性
    //微应用激活状态
    active() {
        //保存window对象上所有属性的状态
        for (const prop in window) {
            this.windowSnap[prop] = window[prop]
        }
        //恢复上一次在运行该微应用时所修改过的window上的属性
        Object.keys(this.modifyPropMap).forEach(prop => {
            window[prop] = this.modifyPropMap[prop];
        })
    }
    //微应用未激活状态
    inactive() {
        for (const prop in window) {
            //判断是否值发生了变化
            if (window[prop] !== this.windowSnap[prop]) {
                //记录修改了window上的哪些属性
                this.modifyPropMap[prop] = window[prop]
                //将window上的属性状态还原至微应用运行之前的状态
                window[prop] = this.windowSnap[prop]
            }
        }
    }
}
const snapShotBox = new SnapShotBox()
window.city = 'Beijing'
console.log(window.city); //Beijing
snapShotBox.active()
window.city = 'Shanghai'
console.log(window.city); //Shanghai
snapShotBox.inactive()
console.log(window.city); //Beijing

完成了一个简易沙箱,但是会遍历window的所有属性,非常消耗性能,方案不是很可取,与此同时,影响了window上的值,如果多个微应用就可能会产生冲,只能激活一个微应用。

LegacySandBox
class LegacySandBox {
    currentUpdatePropsValueMap = new Map() //微应用中修改的属性
    modifiedPropsOriginValueMapInSanBox=new Map()//window中被修改的属性
    addedPropsMapInSandBox=new Map() //添加的属性

    proxyWindow={}
    constructor(){
        const fakeWindow = Object.create(null)
        this.proxyWindow = new Proxy(fakeWindow,{
            set:(target,prop,value,receiver)=>{
                const originalVal = window[prop]
                if(!window.hasOwnProperty(prop)){ //如果window上没有这个属性,那么就是新增的属性
                    this.addedPropsMapInSandBox.set(prop,value)
                    //如果修改对象中没有这个属性,就保存一下
                }else if(!this.modifiedPropsOriginValueMapInSanBox.has(prop)){
                    this.modifiedPropsOriginValueMapInSanBox.set(prop,originalVal)
                }
                this.currentUpdatePropsValueMap.set(prop,value)
                window[prop] = value
            },
            get:(target,prop,receiver)=>{
                return window[prop]
            },
        })
    }
    //设置window属性
    setWindowProp(prop, value, isToDelete) {
        if (value == "undfined" && isToDelete) {
            delete window[prop]
        } else {
            window[prop] = value
        }
    }
    //微应用激活状态
    active() {
        //恢复上一次在运行该微应用时所修改过的window上的属性
        this.currentUpdatePropsValueMap.forEach((value, prop) => {
            this.setWindowProp(prop, vaue);
        })
    }
    //微应用未激活状态
    inactive() {
        //还原window上原有的属性
        this.modifiedPropsOriginValueMapInSanBox.forEach((value,prop)=>{
            this.setWindowProp(prop,value)
        })
        //删除微应用运行期间,window上新增的属性
        this.addedPropsMapInSandBox.forEach((_,prop)=>{
            this.setWindowProp(prop,undefined,true)
        })
    }
}
let legacySandbox = new LegacySandBox()
window.city = 'Beijing'
console.log(window.city); //Beijing
snapShotBox.active()
window.city = 'Shanghai'
console.log(window.city); //Shanghai
snapShotBox.inactive()
console.log(window.city); //Beijing

不需要遍历window上的所有属性,性能良好,但是依然改变的是window上的值,但同一时间还是只能激活一个微应用。

ProxySandBox
class ProxySandBox {
    proxyWindow;
    isRunning = false
    //微应用激活状态
    active() {
        this.isRunning = true
    }
    //微应用未激活状态
    inactive() {
        this.isRunning = false
    }
    constructor() {
        const fakeWindow = Object.create(null)
        this.proxyWindow = new Proxy(fakeWindow, {
            set: (target, prop, value, receiver) => {
                if (this.isRunning) {
                    target[prop] = value
                }
            },
            get: (target, prop, receiver) => {
                return prop in target ? target[prop] : window[prop]
            }
        })
    }
}
window.city = 'Beijing'
let proxySandBox01 = new ProxySandBox()
let proxySandBox02 = new ProxySandBox()
proxySandBox01.active()
proxySandBox02.active()
proxySandBox01.proxyWindow.city = "Shanghai"
proxySandBox02.proxyWindow.city = "Tianjing"
console.log(window.city, proxySandBox01.proxyWindow.city, proxySandBox02.proxyWindow.city);
//Beijing Shanghai Tianjing
proxySandBox01.inactive()
proxySandBox02.inactive()
console.log(window.city, proxySandBox01.proxyWindow.city, proxySandBox02.proxyWindow.city);
//Beijing Shanghai Tianjing

这种ProxySandBox不需要遍历window上的所有属性,性能良好,同一时间可以激活多个微应用互不干扰。

SnapshotSandBox兼容性很好ProxySandBox适用于es6的语法中,就简单介绍到这里。


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

相关文章:

  • 基于Spring Boot+Unipp的博物馆预约小程序(协同过滤算法、二维码识别)【原创】
  • Solana 区块链的技术解析及未来展望 #dapp开发#公链搭建
  • 高光谱深度学习调研
  • 机器学习-36-对ML的思考之机器学习研究的初衷及科学研究的期望
  • async 和 await的使用
  • 基于Lora通讯加STM32空气质量检测WIFI通讯
  • SQL Server 数据库,使用函数查询统计信息
  • Android HCI日志分析案例1
  • 医保支付方式探索——利益共享机制的文章分析
  • Python模块与Linux stat 命令:双剑合璧的文件系统探索
  • C++知识点总结(7):枚举算法之最大公约数和最小公倍数
  • JTag 刷写TC397 的Flash
  • rank的相关loss
  • 基于瑞芯微rk3588+寒武纪 | 38TOPS INT8算力的AI边缘计算盒子,智能安防、智慧工地、智慧城管、智慧油站
  • org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder 实现密码加密 验证 代码示例
  • 在Android上搭建一个NDK项目
  • 解套方式之认识T+0
  • 国内高速下载huggingface上的模型
  • 微信小程序记住密码,让登录解放双手
  • 多平台小程序编译适配,是否会让更多App互联互通?
  • 麻吉POS集成:如何无代码开发实现电商平台和CRM系统的高效连接
  • GD32 定时器输入捕获模式测量PWM占空比和频率
  • SSM项目实战-POJO设计
  • 系统地自学 Python
  • 学习TypeScrip1(基本类型)
  • 论文阅读——Img2LLM(cvpr2023)