关于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的语法中,就简单介绍到这里。
 
                    
                     
                    
                 
                    
                

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号