架构原理
// qiankun/src/loader.ts
if (jsSandbox) {
// appName 注册是传入的子应用 name
// containerGetter dom 的包装
// singular 单实例场景
const sandbox = genSandbox(appName, containerGetter, Boolean(singular));
// 用沙箱的代理对象作为接下来使用的全局对象
global = sandbox.sandbox;
mountSandbox = sandbox.mount;
unmountSandbox = sandbox.unmount;
}// qiankun/src/sandbox/index.ts
export function createSandbox(
appName: string,
elementGetter: () => HTMLElement | ShadowRoot,
singular: boolean
) {
// mounting freers are one-off and should be re-init at every mounting time
let mountingFreers: Freer[] = [];
let sideEffectsRebuilders: Rebuilder[] = [];
let sandbox: SandBox;
if (window.Proxy) {
sandbox = singular ? new LegacySandbox(appName) : new ProxySandbox(appName);
} else {
sandbox = new SnapshotSandbox(appName);
}
// some side effect could be be invoked while bootstrapping, such as dynamic stylesheet injection with style-loader, especially during the development phase
const bootstrappingFreers = patchAtBootstrapping(
appName,
elementGetter,
sandbox.proxy,
singular
);
return {
proxy: sandbox.proxy,
/**
* 沙箱被 mount
* 可能是从 bootstrap 状态进入的 mount
* 也可能是从 unmount 之后再次唤醒进入 mount
*/
async mount() {
// bootstrappingFreers 的 length 是 1
const sideEffectsRebuildersAtBootstrapping = sideEffectsRebuilders.slice(
0,
bootstrappingFreers.length
);
const sideEffectsRebuildersAtMounting = sideEffectsRebuilders.slice(
bootstrappingFreers.length
);
// must rebuild the side effects which added at bootstrapping firstly to recovery to nature state
if (sideEffectsRebuildersAtBootstrapping.length) {
// 执行 rebuild
sideEffectsRebuildersAtBootstrapping.forEach((rebuild) => rebuild());
}
/* ------------------------------------------ 因为有上下文依赖(window),以下代码执行顺序不能变 ------------------------------------------ */
/* ------------------------------------------ 1. 启动/恢复 沙箱------------------------------------------ */
sandbox.active();
/* ------------------------------------------ 2. 开启全局变量补丁 ------------------------------------------*/
// render 沙箱启动时开始劫持各类全局监听,尽量不要在应用初始化阶段有 事件监听/定时器 等副作用
mountingFreers = patchAtMounting(
appName,
elementGetter,
sandbox.proxy,
singular
);
/* ------------------------------------------ 3. 重置一些初始化时的副作用 ------------------------------------------*/
// 存在 rebuilder 则表明有些副作用需要重建
if (sideEffectsRebuildersAtMounting.length) {
sideEffectsRebuildersAtMounting.forEach((rebuild) => rebuild());
}
// clean up rebuilders
sideEffectsRebuilders = [];
},
/**
* 恢复 global 状态,使其能回到应用加载之前的状态
*/
async unmount() {
// record the rebuilders of window side effects (event listeners or timers)
// note that the frees of mounting phase are one-off as it will be re-init at next mounting
// 执行 free 操作
// sideEffectsRebuilders 赋值
sideEffectsRebuilders = [...bootstrappingFreers, ...mountingFreers].map(
(free) => free()
);
// 激活和卸载时都要用到这个
sandbox.inactive();
},
};
}qiankun 沙箱处理原理
qiankun 主基座样式会影响到子基座样式吗
最后更新于