qiankun的js隔离机制-沙箱(一)

83 阅读2分钟

今天主要介绍快照沙箱,直接上核心代码。

class SnapshotSandBox {
    windowSnapshot = {};
    modifyPropsMap = {};
    active() {
        for (const prop in window) {
            this.windowSnapshot[prop] = window[prop];
        }
        Object.keys(this.modifyPropsMap).forEach(prop => {
            window[prop] = this.modifyPropsMap[prop];
        });
    }
    inactive() {
        for (const prop in window) {
            if (window[prop] !== this.windowSnapshot[prop]) {
                this.modifyPropsMap[prop] = window[prop];
                window[prop] = this.windowSnapshot[prop];
            }
        }
    }
}
// 验证:
let snapshotSandBox = new SnapshotSandBox();
snapshotSandBox.active();
window.city = 'Jinan';
console.log("window.city-01:", window.city);   // result Jinan
snapshotSandBox.inactive();
console.log("window.city-02:", window.city);   // result undefined
snapshotSandBox.active();
console.log("window.city-03:", window.city);   // result Jinan

代码分析

class说明

1.定义了两个空的对象windowSnapshotmodifyPropsMap;
2.定义了active方法,该方法先是遍历的window对象上的所有属性,分别将其拷贝至对应的windowSnapshot上;然后迭代了modifyPropsMap对象上的属性,将各个属性拷贝给window对象对应的属性上。
3.定义了inactive方法,该方法遍历window对象上的所有属性,如果window对象上的属性的值不等于对应的windowSnapshot对象上的值,就将window对象属性的值拷贝给对应modifyPropsMap对象属性的值,并且将window对象的属性的值恢复至windowSnapshot对象所存储的对应的值;

调用说明

1.实例化类SnapshotSandBox
2.调用“snapshotSandBox”对象的“active()”方法。 这会拍摄“window”对象当前状态的快照,并根据“modifyPropsMap”对象中的值修改其属性(当前为空数组[],所以不会走forEach回调) 3.在“window”对象上设置一个新属性“city”,其值为“Jinan”。
4.将“window.city”的值打印到控制台,该值将是“Jinan”,因为它刚刚在上一步中设置。
5.调用“snapshotSandBox”对象的“inactive()”方法。 这将检查自拍摄快照以来“window”对象的任何属性是否已被修改。 在这种情况下,“city”属性已被修改,将当前修改的值存入modifyPropsMap对象,并且将window对象上对应属性的值恢复为“undefined”。
6.将“window.city”的值记录到控制台,该值将是“undefined”,因为它在上一步中已恢复。
7.再次调用“snapshotSandBox”对象的“active()”方法。 这会获取“window”对象当前状态的新快照,并根据“modifyPropsMap”对象中的值修改其属性。(因为之前在inactive方法中保存了修改的值)
8.将“window.city”的值记录到控制台,该值将是“Jinan”,因为它刚刚在上一步中设置。

总结:

沙箱激活时,保存当前window对象的快照,并将上一次改变的状态恢复至window对象上。
沙箱失活时,将当前对window对象的改变保存起来,并将window对象恢复至之前window快照时的状态。
如果同时运行多个微应用,都对window对象进行修改,会出现状态混乱的情况,所以快照沙箱只支持对单个微应用的运行,而且通过对window对象所有属性进行diff,是一件比较消耗性能的事情,后面会介绍通过es6的proxy的方式实现的其他隔离方式以及支持多个微应用同时运行。