Skip to content
一、运行环境隔离-快照沙箱

隔离全局变量 缺点:内存消耗大,不支持多实例【一个页面只能有一个实例,不可出现多个实例】 应用场景:比较老版的浏览器

  • 新建 main/micro/sandbox/snapShotSandbox.js

    javascript
     /**
      * 快照沙箱
      */
      export class SnapShotSandbox {
          constructor() {
              // 1. 代理对象
              this.proxy = window
              this.active()
          }
        
         /**
          * 沙箱激活
          */
          active(){
              // 创建一个沙箱快照
              this.snapshot = new Map()
              // 遍历全局环境
              for (const key in window) {
                  this.snapshot[key] = window[key]
              }
          }
        
         /**
          * 沙箱销毁
          */
          inactive() {
              for (const key in window) {
                  if (window[key] !== this.snapshot[key]) {
                      // 还原操作
                      window[key] = this.snapshot[key]
                  }
              }
          }
      }
  • main/micro/sandbox/index.jssandBox 方法中添加代理

    javascript
    import { SnapShotSandbox } from "./snapShotSandbox";
    
     /**
      * 子应用的生命周期处理和环境变量设置
      */
      export const sandBox = (app, script) => {
          const proxy = new SnapShotSandbox()
          if (!app.proxy) {
              app.proxy = proxy
          }
          // 1. 设置环境变量
          window.__MICRO_FRONTEND__ = true
          // 2. 运行 js 文件
          const lifeCycle = performScriptForEval(script, app.name, app.proxy.proxy)
          // 生命周期,挂载到 app 上
          if (isCheckLifeCycle(lifeCycle)) {
              app.bootstrap = lifeCycle.bootstrap
              app.mount = lifeCycle.mount
              app.unmount = lifeCycle.unmount
          }
      }
  • main/micro/lifeCycle/index.jslifeCycle方法中添加沙箱销毁

    javascript
    export const lifeCycle = async () => {
      ...
      if (JSON.stringify(preApp) !== '{}') {
        if (preApp.proxy) {
          preApp.proxy.inactive() // 将沙箱销毁
        }
        await destoryed(preApp)
      }
      ...
    }
二、运行环境隔离-代理沙箱

支持 proxy 语法糖

  • 新建 main/micro/sandbox/proxySandbox.js

    javascript
    // 子应用的沙箱容器
    let defaultValue = {}
      /**
       * 代理沙箱
       */
       export class ProxySandbox {
          constructor() {
          this.proxy = null;
          this.active()
        }
      
       /**
        * 沙箱激活
        */
        active() {
          // 子应用需要设置属性,
          this.proxy = new Proxy(window, {
            get(target, key) {
              if (typeof target[key] === 'function') {
                return target[key].bind(target)
              }
              return defaultValue[key] || target[key]
            },
            set(target, key, value) {
              defaultValue[key] = value
              return true
            }
          })
        }
      
       /**
        * 沙箱销毁
        */
        inactive() {
          defaultValue = {}
        }
      }
  • 改造 main/micro/sandbox/performScript.js 的js执行方法

    javascript
     /**
      * 执行js脚本
      * @param script
      */
      export const performScriptForFunction = (script, appName, global) => {
        window.proxy = global
        const scriptText = `return ((window) => {${script} return window['${appName}']})(window.proxy)`
        return new Function(scriptText)()
      }
      
      export const performScriptForEval = (script, appName, global) => {
        window.proxy = global
        const scriptText = `((window) => {${script} return window['${appName}']})(window.proxy)`
        return eval(scriptText)
      }
  • main/micro/sandbox/index.js 替换代理

    javascript
    import { ProxySandbox } from './proxySandbox'
    
    const proxy = new ProxySandbox()

Released under the MIT License.