一、运行环境隔离-快照沙箱
隔离全局变量 缺点:内存消耗大,不支持多实例【一个页面只能有一个实例,不可出现多个实例】 应用场景:比较老版的浏览器
新建
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.js
的sandBox
方法中添加代理javascriptimport { 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.js
的lifeCycle
方法中添加沙箱销毁javascriptexport 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
替换代理javascriptimport { ProxySandbox } from './proxySandbox' const proxy = new ProxySandbox()