Fancy Front End Fancy Front End
  • 开始上手
  • 基础
  • 调度器(Scheduler)
  • 更新器(Updater)
  • 渲染器(Render)
  • 更新周期
  • hooks 原理
  • 总结
  • 📙 React源码漂流记
  • 开始上手
  • 基础
  • reactivity
  • runtime-core
  • runtime-dom
  • Awesome Web
  • Awesome NodeJS
话题
  • 导航
  • Q&A
  • 幻灯片
  • 关于
  • 分类
  • 标签
  • 归档
博客 (opens new window)
GitHub (opens new window)

Jonsam NG

让有意义的事变得有意思,让有意思的事变得有意义
  • 开始上手
  • 基础
  • 调度器(Scheduler)
  • 更新器(Updater)
  • 渲染器(Render)
  • 更新周期
  • hooks 原理
  • 总结
  • 📙 React源码漂流记
  • 开始上手
  • 基础
  • reactivity
  • runtime-core
  • runtime-dom
  • Awesome Web
  • Awesome NodeJS
话题
  • 导航
  • Q&A
  • 幻灯片
  • 关于
  • 分类
  • 标签
  • 归档
博客 (opens new window)
GitHub (opens new window)
  • 开始上手
  • Plan 计划
  • typescript-utility

  • single-spa源码

  • qiankun源码

    • 开始阅读
    • core

    • sandbox

      • 本章概要
      • createSandboxContainer 创建沙箱
      • proxySandbox
      • snapshotSandbox
        • 目录
        • SnapshotSandbox
        • 快照沙箱的核心功能是什么?
        • 快照沙箱如何隔离 JS?
        • 优点
        • 缺点
    • import-html-entry 原理
  • webpack

  • axios

  • solid

  • vite源码

  • jquery源码

  • snabbdom

  • am-editor

  • html2canvas

  • express

  • acorn源码

  • immutable.js源码

  • web
  • qiankun源码
  • sandbox
jonsam
2022-04-14
目录

snapshotSandbox

标签: 核心

# 目录

  • 目录
  • SnapshotSandbox
  • 快照沙箱的核心功能是什么?
  • 快照沙箱如何隔离 JS?
  • 优点
  • 缺点

# SnapshotSandbox

快照沙箱较为简单,这种基于快照机制的沙箱有很大的局限性就是不能同时多个沙箱同时打快照,不然就会混乱,因为快照是直接基于 window 的。代码如下:

function iter(obj: typeof window, callbackFn: (prop: any) => void) {
  // eslint-disable-next-line guard-for-in, no-restricted-syntax
  for (const prop in obj) {
    // patch for clearInterval for compatible reason, see #1490
    if (obj.hasOwnProperty(prop) || prop === 'clearInterval') {
      callbackFn(prop);
    }
  }
}

/**
 * 基于 diff 方式实现的沙箱,用于不支持 Proxy 的低版本浏览器
 */
export default class SnapshotSandbox implements SandBox {
  proxy: WindowProxy;

  name: string;

  type: SandBoxType;

  sandboxRunning = true;

  private windowSnapshot!: Window;

  private modifyPropsMap: Record<any, any> = {};

  constructor(name: string) {
    this.name = name;
    // 基于快照的实现,直接使用 window
    this.proxy = window;
    this.type = SandBoxType.Snapshot;
  }

  active() {
    // 记录当前快照
    this.windowSnapshot = {} as Window;
    // 将 window 上的属性克隆到 windowSnapshot
    iter(window, (prop) => {
      this.windowSnapshot[prop] = window[prop];
    });

    // 恢复之前的变更
    Object.keys(this.modifyPropsMap).forEach((p: any) => {
      window[p] = this.modifyPropsMap[p];
    });

    this.sandboxRunning = true;
  }

  inactive() {
    // 先清空 modifyPropsMap,理论上在 active 时已经被消费
    this.modifyPropsMap = {};
    // 如果 window 上的属性和快照上的属性不一致,说明在沙箱中有修改,在 modifyPropsMap 保存这个宝盖以便在重新启动沙箱时恢复,同时将 window 重置为快照的状态
    iter(window, (prop) => {
      if (window[prop] !== this.windowSnapshot[prop]) {
        // 记录变更,恢复环境
        this.modifyPropsMap[prop] = window[prop];
        window[prop] = this.windowSnapshot[prop];
      }
    });

    this.sandboxRunning = false;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# 快照沙箱的核心功能是什么?

快照沙箱有两个主要的任务,一是关闭沙箱时将 window 从快照恢复,二是重新开启沙箱时从缓存恢复上次的沙箱状态。

  • 关闭沙箱时将 window 从快照恢复
  • 重新开启沙箱时从缓存恢复上次的沙箱状态

# 快照沙箱如何隔离 JS?

快照沙箱在关闭时会将 window 与开启沙箱时的快照进行 diff,并且恢复到快照状态下的 window。

# 优点

快照沙箱有如下优点:

  • 原理简单。
  • 兼容性很好,几乎所有浏览器都支持。

# 缺点

快照沙箱有如下缺点:

  • 不支持多应用实例。一个页面只能有一个沙箱实例。
  • 在 active 和 inactive 中都需要迭代大量属性,耗费性能。
  • 尽管沙箱关闭时会清理 window,但是在沙箱开启时,主应用和微应用共用一个 window,容易造成 js 混乱。
编辑 (opens new window)
上次更新: 2022/09/06, 14:25:16
proxySandbox
import-html-entry 原理

← proxySandbox import-html-entry 原理→

最近更新
01
渲染原理之组件结构与 JSX 编译
09-07
02
计划跟踪
09-06
03
开始上手
09-06
更多文章>
Theme by Vdoing | Copyright © 2022-2022 Fancy Front End | Made by Jonsam by ❤
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式