内容更新于: 2022-10-12 05:24:46
qiankun中JS沙箱的基本实现
前言:微前端中,为了保证应用之间js环境(主要是window全局变量)的独立,需要使用JS沙箱来对各应用的执行环境进行隔离。本文主要记述其是如何实现的。
qiankun中使用了两种方案来实现这一隔离
1.快照沙箱
2.代理沙箱Proxy
对于支持Proxy的浏览器使用代理沙箱,不支持的浏览器降级使用快照沙箱。
两种沙箱均具备相同的使用方式:卸载应用时,使沙箱失活;挂载应用时,使沙箱激活;
即对于应用A,应用B,都会去创建应用A\B独立的沙箱。初始化时(若需挂载A应用),则使沙箱A激活;从A应用切换至B应用时,沙箱A失活,沙箱B激活。
快照沙箱
其基本思路是记录差异并存储 。
不同沙箱激活状态切换的时候,根据存储数据,动态的为当前激活状态的沙箱赋值,同时为 失活的沙箱赋初始值,从而实现了window的相对纯净状态。
class SnapshotSandbox {
constructor() {
this.proxy = window;
this.originalSnapshot = {};
this.modifyPropsMap = {};
}
active() {
for (const prop in window) {
if (window.hasOwnProperty(prop)) {
this.originalSnapshot[prop] = window[prop];
}
}
Object.keys(this.modifyPropsMap).forEach(prop => {
window[prop] = this.modifyPropsMap[prop];
});
}
inActive() {
for (const prop in window) {
if (window.hasOwnProperty(prop)) {
if (window[prop] !== this.originalSnapshot[prop]) {
this.modifyPropsMap[prop] = window[prop];
window[prop] = this.originalSnapshot[prop];
}
}
}
}
}
代理沙箱
代理沙箱运用了proxy,保证了window对象的纯净,不被污染。
class ProxySandbox {
constructor() {
const originalWindow = window;
const fakeWindow = {};
const proxyWindow = new Proxy(fakeWindow, {
get(target, prop) {
if (target.hasOwnProperty(prop)) {
return target[prop];
}
return originalWindow[prop];
},
set(target, prop, receiver) {
target[prop] = receiver;
return true;
}
});
this.proxy = proxyWindow;
}
active() {}
inActive() {}
}
参考
本文结束
