qiankun沙箱实现原理
文章目录
- 前言
- Qiankun 沙箱实现原理
- 1.全局变量隔离:
- 2.DOM 操作隔离:
- 3.事件隔离:
- 具体实现细节
- 使用 Proxy 对象
- 2.DOM 操作隔离
- 3.事件隔离
- 示例代码
- 总结
前言
Qiankun 设置沙箱(Sandbox)主要是为了实现子应用之间的隔离,防止子应用之间的全局变量污染和副作用。Qiankun 使用了多种技术手段来实现这一目标,包括但不限于 JavaScript 的 Proxy 对象、自定义的全局变量管理等。
Qiankun 沙箱实现原理
Qiankun 的沙箱实现主要通过以下几个步骤来完成:
1.全局变量隔离:
- Qiankun 使用 Proxy 对象来拦截对全局变量的访问和修改。
- 当子应用试图访问或修改全局变量时,Qiankun 会捕获这些操作,并在沙箱环境中进行处理。
2.DOM 操作隔离:
- Qiankun 通过创建一个虚拟的 DOM 环境来隔离子应用的 DOM 操作。
- 子应用的 DOM 操作会被映射到这个虚拟的 DOM 环境中,从而不影响主应用和其他子应用。
3.事件隔离:
- Qiankun 会对子应用中发生的事件进行监听和管理,确保事件不会影响到全局范围。
具体实现细节
使用 Proxy 对象
Qiankun 使用 Proxy 对象来拦截对全局变量的操作,从而实现全局变量的隔离。
const sandbox = {
global: window,
};
const proxyHandler = {
get(target, key) {
// 拦截对全局变量的访问
return Reflect.get(sandbox.global, key) || target[key];
},
set(target, key, value) {
// 拦截对全局变量的修改
sandbox.global[key] = value;
return true;
},
};
// 创建一个全局变量的代理对象
window = new Proxy(sandbox, proxyHandler);
2.DOM 操作隔离
Qiankun 通过创建一个沙箱 DOM 环境来隔离子应用的 DOM 操作。
function createSandboxDOM() {
const sandboxDiv = document.createElement('div');
sandboxDiv.id = 'sandbox';
document.body.appendChild(sandboxDiv);
return sandboxDiv;
}
const sandboxDiv = createSandboxDOM();
// 将子应用的所有 DOM 操作映射到 sandboxDiv 中
document.body = sandboxDiv;
3.事件隔离
Qiankun 会对子应用中的事件进行监听和管理,确保事件不会影响到全局范围。
function addEventListenerWrapper(type, listener) {
const originalAddEventListener = window.addEventListener;
window.addEventListener = function (eventType, cb) {
originalAddEventListener(eventType, function (event) {
// 检查事件是否来自子应用
if (event.target && event.target.ownerDocument === sandboxDiv) {
cb(event);
}
});
};
}
addEventListenerWrapper('click', function (event) {
console.log('子应用点击事件', event);
});
示例代码
主应用配置
// main.js
import { init, MicroApp, router } from 'qiankun';
function createSandboxDOM() {
const sandboxDiv = document.createElement('div');
sandboxDiv.id = 'sandbox';
document.body.appendChild(sandboxDiv);
return sandboxDiv;
}
const sandboxDiv = createSandboxDOM();
init({
apps: [
new MicroApp({
name: 'sub-app-1',
entry: '//localhost:8001',
container: sandboxDiv,
activeRule: '/sub-app-1',
}),
],
router,
});
// 路由监听
router.onNavigate(({ location }) => {
console.log('navigate to', location.pathname);
});
子应用配置
// sub-app.js
if (window.__POWERED_BY_QIANKUN__) {
// 当前环境是 Qiankun 环境
window.__onGlobeEvent = function (event) {
console.log('received event:', event);
};
// 创建沙箱环境
const sandbox = {
global: window,
};
const proxyHandler = {
get(target, key) {
return Reflect.get(sandbox.global, key) || target[key];
},
set(target, key, value) {
sandbox.global[key] = value;
return true;
},
};
// 创建一个全局变量的代理对象
window = new Proxy(sandbox, proxyHandler);
} else {
// 非 Qiankun 环境下的普通应用
// ...
}
总结
Qiankun 通过使用 Proxy 对象来拦截全局变量的访问和修改,通过创建沙箱 DOM 环境来隔离子应用的 DOM 操作,并通过自定义的事件监听来管理子应用中的事件。这些措施共同实现了子应用之间的隔离,确保了主应用和子应用之间的互不干扰。通过这些技术手段,Qiankun 能够有效保障微前端架构的安全性和稳定性。