【微前端】实现沙箱隔离

1,246 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

随着应用架构复杂,微前端方案的出现,js运行环境沙箱在浏览器中的需求越来越多

需要js沙箱的场景

  1. 多个微前端应用中,变量冲突
  2. 执行第三方js:当你有必要执行第三方js的时候,而这份js文件又不一定可信的时候

需要实现的功能

一个独立的上下文作用域,其中的代码执行不会影响到其他的运行环境。 需要支持多个沙箱环境存在,每个沙箱需要有加载、卸载、再次恢复的能力,其对应着微应用的运行生命周期。

实现过程在这里插入图片描述

原来的实现 上面的get/set条件不够完善,应该使用如下: 完整的实现 1、核心是使用proxy对象创建window代理,并将需要被隔离起来的代码的执行作用域绑定到proxy对象上 2、属性active用来外界控制沙箱是否运行 3、new set()injectedKeys用于记录添加的属性,在沙箱停止的时删除 4、使用Reflect高级地实现属性操作 5、withcallwindow的执行绑定到proxyWindow

微前端应用: 5、微应用初始化的时候 new sandbox 6、ajax获取script标签的代码,并调用bindScope方法用eval在全局作用域执行 7、webpack打包后动态加载的js是使用document.createElementhead里增加了script标签,浏览器自动执行。则对document.createElement重新复制并代理src属性的getset,在set中获取js内容并在沙箱中执行

proxynew Proxy(target, handler)handler中指定对象的属性的getset等操作。详见MDN Object.defineProperty:对象的某个属性的操作进行代理Object.defineProperty(obj, prop, descriptor)descriptor中(valuewritable)与(getset)是两者其中之一,不能同时都有,详见MDN 题外话:vue3 /2 分别用上述原理实现响应式 Reflect:和直接对象赋值没有区别,优点在于可以知道set的结果成功/失败,且不会因为报错而中断正常的代码逻辑执行,还有厉害的receiver参数,详见:张鑫旭 eval(string)工作在当前作用域下,会将传入的字符串当做 JavaScript 代码进行执行。使用引用或者(0, eval)('x + y')会工作在全局作用域下 题外话:eval的使用 with语句 扩展一个语句的作用域链,指定代码执行的默认对象。详见:MDN

在这里插入图片描述 在这里插入图片描述

一些优化

1、实现沙箱的再次恢复 2、不使用eval和with来实现对应功能

参考:从零开始写一个微前端框架-沙箱篇