qiankun沙箱实现

前言

在前公司工作的时候,我曾经手写过qiankun的核心代码用于技术分享。

这里先简单说一下qiankun是如何完成子应用挂载的。

1.qiankun会在基座应用中请求子应用的模板
2.由于浏览器安全限制,模版中的script代码是无效的,所以qiankun会过滤出所有的script,单独请求下来并通过eval等方式执行(比如单页应用,其挂载实际上就是执行了主js代码,通过调用对应的mount函数完成挂载)

qiankun在执行脚本时可能会出现全局变量污染,因此需要使用沙箱去隔离

下面就来聊一下我是如何实现qiankun的沙箱,隔离子应用和基座应用间的全局变量污染。

代码实现

闲话少说,直接上代码。

js 复制代码
export class sandbox { // 沙箱完整版
    running = false // 是否启动沙箱

    fakeWindow = {}
    realWindow = window

    box = null // 沙箱proxy实例

    constructor() {
        this.box = new Proxy(this.fakeWindow, {
            get: (target, key) => {
                // 沙箱取值优先从 fakeWindow 上获取
                if (Reflect.has(target, key))  return Reflect.get(target, key) // 优先代理对象
                // 否则从window上找
                const result = Reflect.get(this.realWindow, key)
                if (typeof result == 'function') {
                    // 如果当前项在window中为函数则返回待执行函数
                    return result.bind(this.realWindow)
                }
                return result
            },
            set: (target, key, value) => {
                // 沙箱启动的前提下
                if (this.running) {
                    Reflect.set(target, key, value)
                }
                return true
            }
        })
    }
    // 启动沙箱
    active() {
        this.running = true
    }
    // 关闭沙箱
    inactive() {
        this.running = false
        this.fakeWindow = {}
    }
}

代码解读

这段代码是一个沙箱类的完整版本。

用于隔离代码执行环境的机制,可以限制代码的访问权限,提高代码的安全性。

代码中的 sandbox 类有以下几个属性和方法:

  • running :一个布尔值,表示沙箱是否启动。
  • fakeWindow :一个空对象,用于模拟窗口对象。
  • realWindow :指向全局的 window 对象。
  • box :沙箱的代理实例。

在构造函数中,通过 Proxy 对象创建了一个代理实例 box ,用于拦截对沙箱的访问。

代理对象的 get 方法用于拦截属性的读取操作,如果属性存在于 fakeWindow 对象中,则返回对应的值;否则,从全局的 window 对象中获取对应的值。如果获取的值是一个函数,则将其绑定到真正的 window 对象上返回。

代理对象的 set 方法用于拦截属性的赋值操作,只有在沙箱启动的前提下,才会允许属性的赋值; 赋值时会存储到 fakeWindow 上防止污染 realWindow

active() 方法用于启动沙箱,将 running 属性设置为 true

inactive() 方法用于关闭沙箱,将 running 属性设置为 false ,并重置 fakeWindow 对象为空对象。

通过使用这个沙箱类,可以在代码执行时限制对全局环境的访问,增加代码的安全性。

由于qiankun会使用eval等方式去执行脚本,通过eval读取上下文等特性,将沙箱劫持的代理对象作为window传入实现js隔离。

代码如下:

js 复制代码
((window, module, exports) => {
    try {
        eval(code);
    } catch (error) {
        console.log(error);
    }
})(app.sandbox.box, module, exports);
相关推荐
陈广亮3 分钟前
工具指南7-Unix时间戳转换工具
前端
NGBQ121389 分钟前
Adobe-Premiere-Pro-2026-26.0.2.2-m0nkrus 全解析:专业视频编辑软件深度指南
前端·adobe·音视频
北城笑笑10 分钟前
Chrome:Paused in debugger 的踩坑实录:问题排查全过程与终极解决方案( 在调试器中暂停 )
前端·chrome
haorooms12 分钟前
Promise.try () 完全指南
前端·javascript
kyriewen13 分钟前
闭包:那个“赖着不走”的家伙,到底有什么用?
前端·javascript·ecmascript 6
斌味代码17 分钟前
el-popover跳转页面不隐藏,el-popover销毁
前端·javascript·vue.js
该怎么办呢17 分钟前
cesium核心代码学习-01项目目录及其基本作用
前端·3d·源码·webgl·cesium·webgis
踩着两条虫24 分钟前
AI 驱动的 Vue3 应用开发平台 深入探究(十九):CLI与工具链之Create VTJ CLI 参考
前端·ai编程·vite
嫂子的姐夫27 分钟前
040-spiderbuf第C8题
javascript·爬虫·python·js逆向·逆向
天下无贼!35 分钟前
【Python】2026版——FastAPI 框架快速搭建后端服务
开发语言·前端·后端·python·aigc·fastapi