Skip to content

JS隔离的实现原理

在微前端架构,不同的子应用运行在同一个主应用的环境下,共享一个window对象、全局事件、全局变量,为了避免互相污染,三大微前端框架(qianduan、Wujie、micro-app)都引入了JS隔离机制

Qiankun的JS隔离机制

基于Proxy沙箱和Snapshot沙箱

Proxy沙箱

  • QianKun的沙箱主要是基于ES6的proxy实现,通过代理window对象来隔离子应用的全局状态。
  • 在Proxy沙箱中,子应用内部对window的读写并不会影响到主应用。
  • 实现原理
    • 当子应用加载时,会创建一个代理对象proxy
js
const sandbox = new Proxy(window,{
    get(target,prop) {
        return prop in target?target[prop]:undefined;
    }
    set(target, prop, val) {
        target[prop] = val;
        return true;
    }
})
    • 访问window当任何属性都会被代理,所有修改只在当前作用域生效。
    • 子应用卸载时,会清空沙箱环境

Snapshot沙箱

  • 这是Qiankun的另一种隔离模式,适合不支持Proxy的低版本浏览器
  • 主要是通过在挂载和卸载时,保持和恢复window的状态
js
// 激活前保存window的状态
const snapshot = {...window};
// 激活后还原window的状态
Object.keys(snapshot).forEach((key)=> window[key] = snapshot[key])

总结

  • 主要靠proxy代理window对象
  • 变量修改、事件注册都在沙箱内部独立存在。
  • 卸载时自动回复,防止全局污染。

Wujie的JS隔离机制

基于iframe沙箱Proxy沙箱的双重隔离

iframe沙箱

  • Wujie的核心隔离时基于<iframe></iframe>
  • <iframe></iframe>天然隔离JS作用域,CSS和DOM
  • 每一个子应用在一个独立的iframe内执行
html
<iframe src="" sandbox="allow-scripts allow-same-origin"></iframe>
  • Wujie会自动设置iframesandbox属性,屏蔽跨域访问,防止主应用修改。

Proxy沙箱

  • Wujie内部通过Proxy封装了iframe的window,对子应用内部的修改都映射到iframe到作用域中
js
const proxyWindow = new Proxy(iframe,contentWindow,{
 get(target, prop) {
    return target[prop];
  },
  set(target, prop, value) {
    target[prop] = value;
    return true;
  },
})

总结

  • 基于原生iframe 完全独立的JS沙箱
  • 通过Proxy代理对window的操作,避免污染
  • 隔离最彻底,适合跨域场景。

micro-app的JS隔离机制

Proxy沙箱

基于Proxy沙箱+ Patch DOM API

  • micro-app和qiankun类似,也使用Proxy沙箱隔离JS作用域
  • 当子应用执行修改window的操作时,会被沙箱捕获并仅在内部生效。
js
const proxyWindow = new Proxy(window, {
  get(target, prop) {
    return prop in target ? target[prop] : undefined;
  },
  set(target, prop, value) {
   if (target.hasOwnProperty(prop)) {
      target[prop] = value;
    } else {
      target[prop] = value;
    }
    return true;
  },
});

Patch DOM API

  • micro-app还会对dom相关api做隔离处理
    • document.getElementByIddocument.querySelector等方法会自动限定作用域。
    • 事件监听 addEventListener也会仅限当前子应用内。

总结

  • 通过proxy实现js隔离,通过DOM Patch实现更细粒度的控制
  • 自动隔离DOM事件,保证不同子应用互不干扰。
  • 兼容性更好,支持IE11以上。

三者对比

特性QiankunWujiemicro-app
隔离方式Proxyiframe+proxyproxy+patch DOM API
全局变量隔离强,基于Proxy最强,基于iframe强,基于Proxy
Dom操作隔离需要手动ScopedCssiframe内天然隔离自动Patch DOM
事件隔离沙箱内独立iframe内独立自动隔离
兼容性高(不支持ie11)中(部分新特性需要polyfill)高(支持IE11以上)
隔离彻底性最彻底

Released under the MIT License.