不积跬步,无以至千里。

我的学习笔记

首页

前端框架

微前端

内容更新于: 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() {}
}


参考

本文结束