@micro-zoe/micro-app 1.0.0-alpha.7 → 1.0.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +5 -3
- package/lib/index.esm.js +413 -166
- package/lib/index.esm.js.map +1 -1
- package/lib/index.min.js +1 -1
- package/lib/index.min.js.map +1 -1
- package/lib/index.umd.js +1 -1
- package/lib/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/typings/global.d.ts +53 -21
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-alpha.
|
|
1
|
+
const version = '1.0.0-alpha.8';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -33,6 +33,10 @@ function isString(target) {
|
|
|
33
33
|
function isBoolean(target) {
|
|
34
34
|
return typeof target === 'boolean';
|
|
35
35
|
}
|
|
36
|
+
// is Number
|
|
37
|
+
function isNumber(target) {
|
|
38
|
+
return typeof target === 'number';
|
|
39
|
+
}
|
|
36
40
|
// is function
|
|
37
41
|
function isFunction(target) {
|
|
38
42
|
return typeof target === 'function';
|
|
@@ -565,6 +569,7 @@ var MicroAppConfig;
|
|
|
565
569
|
MicroAppConfig["SSR"] = "ssr";
|
|
566
570
|
MicroAppConfig["FIBER"] = "fiber";
|
|
567
571
|
})(MicroAppConfig || (MicroAppConfig = {}));
|
|
572
|
+
const PREFETCH_LEVEL = [1, 2, 3];
|
|
568
573
|
/**
|
|
569
574
|
* global key must be static key, they can not rewrite
|
|
570
575
|
* e.g.
|
|
@@ -1365,10 +1370,9 @@ class Adapter {
|
|
|
1365
1370
|
];
|
|
1366
1371
|
this.injectReactHRMProperty();
|
|
1367
1372
|
}
|
|
1368
|
-
// TODO: __DEV__ process.env.NODE_ENV !== 'production'
|
|
1369
1373
|
// adapter for react
|
|
1370
1374
|
injectReactHRMProperty() {
|
|
1371
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
1375
|
+
if ((process.env.NODE_ENV !== 'production')) {
|
|
1372
1376
|
// react child in non-react env
|
|
1373
1377
|
this.staticEscapeProperties.push('__REACT_ERROR_OVERLAY_GLOBAL_HOOK__');
|
|
1374
1378
|
// in react parent
|
|
@@ -1392,7 +1396,7 @@ function fixBabelPolyfill6() {
|
|
|
1392
1396
|
*/
|
|
1393
1397
|
function fixReactHMRConflict(app) {
|
|
1394
1398
|
var _a;
|
|
1395
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
1399
|
+
if ((process.env.NODE_ENV !== 'production')) {
|
|
1396
1400
|
const rawReactErrorHook = globalEnv.rawWindow.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__;
|
|
1397
1401
|
const childReactErrorHook = (_a = app.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__;
|
|
1398
1402
|
if (rawReactErrorHook && childReactErrorHook) {
|
|
@@ -1525,11 +1529,11 @@ function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild
|
|
|
1525
1529
|
configurable: true,
|
|
1526
1530
|
get() {
|
|
1527
1531
|
/**
|
|
1528
|
-
* When operate child from parentNode async,
|
|
1532
|
+
* When operate child from parentNode async, may have been unmount
|
|
1529
1533
|
* e.g.
|
|
1530
1534
|
* target.parentNode.remove(target)
|
|
1531
1535
|
*/
|
|
1532
|
-
return
|
|
1536
|
+
return !app.container ? hijackParent : document.body;
|
|
1533
1537
|
},
|
|
1534
1538
|
});
|
|
1535
1539
|
}
|
|
@@ -1547,8 +1551,7 @@ function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild
|
|
|
1547
1551
|
}
|
|
1548
1552
|
return targetChild;
|
|
1549
1553
|
}
|
|
1550
|
-
|
|
1551
|
-
if (process.env.NODE_ENV !== 'production' &&
|
|
1554
|
+
if ((process.env.NODE_ENV !== 'production') &&
|
|
1552
1555
|
targetChild instanceof HTMLIFrameElement &&
|
|
1553
1556
|
rawMethod === globalEnv.rawAppendChild) {
|
|
1554
1557
|
fixReactHMRConflict(app);
|
|
@@ -1664,7 +1667,6 @@ function patchElementPrototypeMethods() {
|
|
|
1664
1667
|
};
|
|
1665
1668
|
// prototype methods of delete element👇
|
|
1666
1669
|
Element.prototype.removeChild = function removeChild(oldChild) {
|
|
1667
|
-
var _a;
|
|
1668
1670
|
if (oldChild === null || oldChild === void 0 ? void 0 : oldChild.__MICRO_APP_NAME__) {
|
|
1669
1671
|
const app = appInstanceMap.get(oldChild.__MICRO_APP_NAME__);
|
|
1670
1672
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
@@ -1673,8 +1675,8 @@ function patchElementPrototypeMethods() {
|
|
|
1673
1675
|
try {
|
|
1674
1676
|
return globalEnv.rawRemoveChild.call(this, oldChild);
|
|
1675
1677
|
}
|
|
1676
|
-
catch (
|
|
1677
|
-
return (
|
|
1678
|
+
catch (_a) {
|
|
1679
|
+
return ((oldChild === null || oldChild === void 0 ? void 0 : oldChild.parentNode) && globalEnv.rawRemoveChild.call(oldChild.parentNode, oldChild));
|
|
1678
1680
|
}
|
|
1679
1681
|
}
|
|
1680
1682
|
return globalEnv.rawRemoveChild.call(this, oldChild);
|
|
@@ -2213,7 +2215,7 @@ function fetchScriptsFromHtml(wrapElement, app) {
|
|
|
2213
2215
|
for (const address of scriptList) {
|
|
2214
2216
|
const scriptInfo = sourceCenter.script.getInfo(address);
|
|
2215
2217
|
const appSpaceData = scriptInfo.appSpace[app.name];
|
|
2216
|
-
if ((!appSpaceData.defer && !appSpaceData.async) || app.isPrefetch) {
|
|
2218
|
+
if ((!appSpaceData.defer && !appSpaceData.async) || (app.isPrefetch && !app.isPrerender)) {
|
|
2217
2219
|
fetchScriptPromise.push(scriptInfo.code ? scriptInfo.code : fetchSource(address, app.name));
|
|
2218
2220
|
fetchScriptPromiseInfo.push([address, scriptInfo]);
|
|
2219
2221
|
}
|
|
@@ -2254,7 +2256,7 @@ function fetchScriptSuccess(address, scriptInfo, code, app) {
|
|
|
2254
2256
|
* 2. if app is inline or script is esmodule, skip this step
|
|
2255
2257
|
* 3. if global parseResult not exist, the current script occupies the position, when js is reused, parseResult is reference
|
|
2256
2258
|
*/
|
|
2257
|
-
if (app.isPrefetch) {
|
|
2259
|
+
if (app.isPrefetch && app.prefetchLevel === 2) {
|
|
2258
2260
|
const appSpaceData = scriptInfo.appSpace[app.name];
|
|
2259
2261
|
/**
|
|
2260
2262
|
* When prefetch app is replaced by a new app in the processing phase, since the scriptInfo is common, when the scriptInfo of the prefetch app is processed, it may have already been processed.
|
|
@@ -2639,17 +2641,19 @@ class EventCenter {
|
|
|
2639
2641
|
const force = eventInfo.force;
|
|
2640
2642
|
eventInfo.tempData = null;
|
|
2641
2643
|
eventInfo.force = false;
|
|
2644
|
+
let resArr;
|
|
2642
2645
|
if (force || !this.isEqual(eventInfo.data, tempData)) {
|
|
2643
2646
|
eventInfo.data = tempData || eventInfo.data;
|
|
2644
2647
|
for (const f of eventInfo.callbacks) {
|
|
2645
|
-
f(eventInfo.data);
|
|
2648
|
+
const res = f(eventInfo.data);
|
|
2649
|
+
res && (resArr !== null && resArr !== void 0 ? resArr : (resArr = [])).push(res);
|
|
2646
2650
|
}
|
|
2647
2651
|
(_b = (_a = temRecordStep[name]).dispatchDataEvent) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
2648
2652
|
/**
|
|
2649
2653
|
* WARING:
|
|
2650
2654
|
* If data of other app is sent in nextStep, it may cause confusion of tempData and force
|
|
2651
2655
|
*/
|
|
2652
|
-
temRecordStep[name].nextStepList.forEach((nextStep) => nextStep());
|
|
2656
|
+
temRecordStep[name].nextStepList.forEach((nextStep) => nextStep(resArr));
|
|
2653
2657
|
}
|
|
2654
2658
|
}
|
|
2655
2659
|
};
|
|
@@ -2824,7 +2828,7 @@ class EventCenterForGlobal {
|
|
|
2824
2828
|
setGlobalData(data, nextStep, force) {
|
|
2825
2829
|
// clear dom scope before dispatch global data, apply to micro app
|
|
2826
2830
|
removeDomScope();
|
|
2827
|
-
eventCenter.dispatch('global', data, () => isFunction(nextStep) && nextStep(), force);
|
|
2831
|
+
eventCenter.dispatch('global', data, (resArr) => isFunction(nextStep) && nextStep(resArr), force);
|
|
2828
2832
|
}
|
|
2829
2833
|
forceSetGlobalData(data, nextStep) {
|
|
2830
2834
|
this.setGlobalData(data, nextStep, true);
|
|
@@ -2892,7 +2896,7 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
2892
2896
|
* @param data data
|
|
2893
2897
|
*/
|
|
2894
2898
|
setData(appName, data, nextStep, force) {
|
|
2895
|
-
eventCenter.dispatch(formatEventName(formatAppName(appName), true), data, () => isFunction(nextStep) && nextStep(), force);
|
|
2899
|
+
eventCenter.dispatch(formatEventName(formatAppName(appName), true), data, (resArr) => isFunction(nextStep) && nextStep(resArr), force);
|
|
2896
2900
|
}
|
|
2897
2901
|
forceSetData(appName, data, nextStep) {
|
|
2898
2902
|
this.setData(appName, data, nextStep, true);
|
|
@@ -2948,7 +2952,7 @@ class EventCenterForMicroApp extends EventCenterForGlobal {
|
|
|
2948
2952
|
*/
|
|
2949
2953
|
dispatch(data, nextStep, force) {
|
|
2950
2954
|
removeDomScope();
|
|
2951
|
-
eventCenter.dispatch(formatEventName(this.appName, false), data, () => isFunction(nextStep) && nextStep(), force, () => {
|
|
2955
|
+
eventCenter.dispatch(formatEventName(this.appName, false), data, (resArr) => isFunction(nextStep) && nextStep(resArr), force, () => {
|
|
2952
2956
|
const app = appInstanceMap.get(this.appName);
|
|
2953
2957
|
if ((app === null || app === void 0 ? void 0 : app.container) && isPlainObject(data)) {
|
|
2954
2958
|
const event = new CustomEvent('datachange', {
|
|
@@ -3158,12 +3162,14 @@ function effectDocumentEvent() {
|
|
|
3158
3162
|
const { rawDocument, rawDocumentAddEventListener, rawDocumentRemoveEventListener, } = globalEnv;
|
|
3159
3163
|
!hasRewriteDocumentOnClick && overwriteDocumentOnClick();
|
|
3160
3164
|
document.addEventListener = function (type, listener, options) {
|
|
3161
|
-
var _a;
|
|
3162
3165
|
const appName = getCurrentAppName();
|
|
3163
3166
|
/**
|
|
3164
3167
|
* ignore bound function of document event in umd mode, used to solve problem of react global events
|
|
3168
|
+
* update in 2022-09-02:
|
|
3169
|
+
* boundFunction is no longer exclude, because events in UMD mode will not cleared from v1.0.0-alpha.4
|
|
3170
|
+
* if (appName && !(appInstanceMap.get(appName)?.umdMode && isBoundFunction(listener))) {
|
|
3165
3171
|
*/
|
|
3166
|
-
if (appName
|
|
3172
|
+
if (appName) {
|
|
3167
3173
|
const appListenersMap = documentEventListenerMap.get(appName);
|
|
3168
3174
|
if (appListenersMap) {
|
|
3169
3175
|
const appListenerList = appListenersMap.get(type);
|
|
@@ -3182,9 +3188,13 @@ function effectDocumentEvent() {
|
|
|
3182
3188
|
rawDocumentAddEventListener.call(rawDocument, type, listener, options);
|
|
3183
3189
|
};
|
|
3184
3190
|
document.removeEventListener = function (type, listener, options) {
|
|
3185
|
-
var _a;
|
|
3186
3191
|
const appName = getCurrentAppName();
|
|
3187
|
-
|
|
3192
|
+
/**
|
|
3193
|
+
* update in 2022-09-02:
|
|
3194
|
+
* boundFunction is no longer exclude, because events in UMD mode will not cleared from v1.0.0-alpha.4
|
|
3195
|
+
* if (appName && !(appInstanceMap.get(appName)?.umdMode && isBoundFunction(listener))) {
|
|
3196
|
+
*/
|
|
3197
|
+
if (appName) {
|
|
3188
3198
|
const appListenersMap = documentEventListenerMap.get(appName);
|
|
3189
3199
|
if (appListenersMap) {
|
|
3190
3200
|
const appListenerList = appListenersMap.get(type);
|
|
@@ -3249,69 +3259,80 @@ function effect(appName, microAppWindow) {
|
|
|
3249
3259
|
timeoutIdMap.delete(timeoutId);
|
|
3250
3260
|
rawClearTimeout.call(rawWindow, timeoutId);
|
|
3251
3261
|
};
|
|
3252
|
-
const
|
|
3253
|
-
const
|
|
3254
|
-
let
|
|
3255
|
-
let
|
|
3256
|
-
let
|
|
3257
|
-
const
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3262
|
+
const sstWindowListenerMap = new Map();
|
|
3263
|
+
const sstDocumentListenerMap = new Map();
|
|
3264
|
+
let sstIntervalIdMap = new Map();
|
|
3265
|
+
let sstTimeoutIdMap = new Map();
|
|
3266
|
+
let sstOnClickHandler;
|
|
3267
|
+
const clearSnapshotData = () => {
|
|
3268
|
+
sstWindowListenerMap.clear();
|
|
3269
|
+
sstIntervalIdMap.clear();
|
|
3270
|
+
sstTimeoutIdMap.clear();
|
|
3271
|
+
sstDocumentListenerMap.clear();
|
|
3272
|
+
sstOnClickHandler = null;
|
|
3263
3273
|
};
|
|
3264
|
-
|
|
3265
|
-
|
|
3274
|
+
/**
|
|
3275
|
+
* record event and timer
|
|
3276
|
+
* Scenes:
|
|
3277
|
+
* 1. exec umdMountHook in umd mode
|
|
3278
|
+
* 2. hidden keep-alive app
|
|
3279
|
+
* 3. after init prerender app
|
|
3280
|
+
*/
|
|
3281
|
+
const recordEffect = () => {
|
|
3266
3282
|
// record window event
|
|
3267
3283
|
eventListenerMap.forEach((listenerList, type) => {
|
|
3268
3284
|
if (listenerList.size) {
|
|
3269
|
-
|
|
3285
|
+
sstWindowListenerMap.set(type, new Set(listenerList));
|
|
3270
3286
|
}
|
|
3271
3287
|
});
|
|
3272
3288
|
// record timers
|
|
3273
3289
|
if (intervalIdMap.size) {
|
|
3274
|
-
|
|
3290
|
+
sstIntervalIdMap = new Map(intervalIdMap);
|
|
3275
3291
|
}
|
|
3276
3292
|
if (timeoutIdMap.size) {
|
|
3277
|
-
|
|
3293
|
+
sstTimeoutIdMap = new Map(timeoutIdMap);
|
|
3278
3294
|
}
|
|
3279
3295
|
// record onclick handler
|
|
3280
|
-
|
|
3296
|
+
sstOnClickHandler = documentClickListMap.get(appName);
|
|
3281
3297
|
// record document event
|
|
3282
3298
|
const documentAppListenersMap = documentEventListenerMap.get(appName);
|
|
3283
3299
|
if (documentAppListenersMap) {
|
|
3284
3300
|
documentAppListenersMap.forEach((listenerList, type) => {
|
|
3285
3301
|
if (listenerList.size) {
|
|
3286
|
-
|
|
3302
|
+
sstDocumentListenerMap.set(type, new Set(listenerList));
|
|
3287
3303
|
}
|
|
3288
3304
|
});
|
|
3289
3305
|
}
|
|
3290
3306
|
};
|
|
3291
|
-
// rebuild event and timer before remount
|
|
3292
|
-
const
|
|
3307
|
+
// rebuild event and timer before remount app
|
|
3308
|
+
const rebuildEffect = () => {
|
|
3293
3309
|
// rebuild window event
|
|
3294
|
-
|
|
3310
|
+
sstWindowListenerMap.forEach((listenerList, type) => {
|
|
3295
3311
|
for (const listener of listenerList) {
|
|
3296
3312
|
microAppWindow.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
|
|
3297
3313
|
}
|
|
3298
3314
|
});
|
|
3299
3315
|
// rebuild timer
|
|
3300
|
-
|
|
3316
|
+
sstIntervalIdMap.forEach((info) => {
|
|
3301
3317
|
microAppWindow.setInterval(info.handler, info.timeout, ...info.args);
|
|
3302
3318
|
});
|
|
3303
|
-
|
|
3319
|
+
sstTimeoutIdMap.forEach((info) => {
|
|
3304
3320
|
microAppWindow.setTimeout(info.handler, info.timeout, ...info.args);
|
|
3305
3321
|
});
|
|
3306
3322
|
// rebuild onclick event
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3323
|
+
sstOnClickHandler && documentClickListMap.set(appName, sstOnClickHandler);
|
|
3324
|
+
/**
|
|
3325
|
+
* rebuild document event
|
|
3326
|
+
* WARNING!!: do not delete setCurrentAppName & removeDomScope
|
|
3327
|
+
*/
|
|
3328
|
+
setCurrentAppName(appName);
|
|
3329
|
+
sstDocumentListenerMap.forEach((listenerList, type) => {
|
|
3310
3330
|
for (const listener of listenerList) {
|
|
3311
3331
|
document.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
|
|
3312
3332
|
}
|
|
3313
3333
|
});
|
|
3314
|
-
|
|
3334
|
+
removeDomScope();
|
|
3335
|
+
clearSnapshotData();
|
|
3315
3336
|
};
|
|
3316
3337
|
// release all event listener & interval & timeout when unmount app
|
|
3317
3338
|
const releaseEffect = () => {
|
|
@@ -3351,8 +3372,8 @@ function effect(appName, microAppWindow) {
|
|
|
3351
3372
|
}
|
|
3352
3373
|
};
|
|
3353
3374
|
return {
|
|
3354
|
-
|
|
3355
|
-
|
|
3375
|
+
recordEffect,
|
|
3376
|
+
rebuildEffect,
|
|
3356
3377
|
releaseEffect,
|
|
3357
3378
|
};
|
|
3358
3379
|
}
|
|
@@ -3378,7 +3399,6 @@ function removeMicroState(appName, rawState) {
|
|
|
3378
3399
|
delete rawState.microAppState;
|
|
3379
3400
|
}
|
|
3380
3401
|
}
|
|
3381
|
-
// 生成新的state对象
|
|
3382
3402
|
return assign({}, rawState);
|
|
3383
3403
|
}
|
|
3384
3404
|
// get micro app state form origin state
|
|
@@ -3390,12 +3410,15 @@ const ENC_AD_RE = /&/g; // %M1
|
|
|
3390
3410
|
const ENC_EQ_RE = /=/g; // %M2
|
|
3391
3411
|
const DEC_AD_RE = /%M1/g; // &
|
|
3392
3412
|
const DEC_EQ_RE = /%M2/g; // =
|
|
3413
|
+
// encode path with special symbol
|
|
3393
3414
|
function encodeMicroPath(path) {
|
|
3394
3415
|
return encodeURIComponent(commonDecode(path).replace(ENC_AD_RE, '%M1').replace(ENC_EQ_RE, '%M2'));
|
|
3395
3416
|
}
|
|
3417
|
+
// decode path
|
|
3396
3418
|
function decodeMicroPath(path) {
|
|
3397
3419
|
return commonDecode(path).replace(DEC_AD_RE, '&').replace(DEC_EQ_RE, '=');
|
|
3398
3420
|
}
|
|
3421
|
+
// Recursively resolve address
|
|
3399
3422
|
function commonDecode(path) {
|
|
3400
3423
|
try {
|
|
3401
3424
|
const decPath = decodeURIComponent(path);
|
|
@@ -3407,12 +3430,15 @@ function commonDecode(path) {
|
|
|
3407
3430
|
return path;
|
|
3408
3431
|
}
|
|
3409
3432
|
}
|
|
3410
|
-
//
|
|
3433
|
+
// Format the query parameter key to prevent conflicts with the original parameters
|
|
3411
3434
|
function formatQueryAppName(appName) {
|
|
3412
3435
|
// return `app-${appName}`
|
|
3413
3436
|
return appName;
|
|
3414
3437
|
}
|
|
3415
|
-
|
|
3438
|
+
/**
|
|
3439
|
+
* Get app fullPath from browser url
|
|
3440
|
+
* @param appName app.name
|
|
3441
|
+
*/
|
|
3416
3442
|
function getMicroPathFromURL(appName) {
|
|
3417
3443
|
var _a, _b;
|
|
3418
3444
|
const rawLocation = globalEnv.rawWindow.location;
|
|
@@ -3420,15 +3446,23 @@ function getMicroPathFromURL(appName) {
|
|
|
3420
3446
|
const microPath = ((_a = queryObject.hashQuery) === null || _a === void 0 ? void 0 : _a[formatQueryAppName(appName)]) || ((_b = queryObject.searchQuery) === null || _b === void 0 ? void 0 : _b[formatQueryAppName(appName)]);
|
|
3421
3447
|
return isString(microPath) ? decodeMicroPath(microPath) : null;
|
|
3422
3448
|
}
|
|
3423
|
-
|
|
3449
|
+
/**
|
|
3450
|
+
* Attach child app fullPath to browser url
|
|
3451
|
+
* @param appName app.name
|
|
3452
|
+
* @param microLocation location of child app
|
|
3453
|
+
*/
|
|
3424
3454
|
function setMicroPathToURL(appName, microLocation) {
|
|
3425
3455
|
let { pathname, search, hash } = globalEnv.rawWindow.location;
|
|
3426
3456
|
const queryObject = getQueryObjectFromURL(search, hash);
|
|
3427
3457
|
const encodedMicroPath = encodeMicroPath(microLocation.pathname +
|
|
3428
3458
|
microLocation.search +
|
|
3429
3459
|
microLocation.hash);
|
|
3430
|
-
|
|
3431
|
-
|
|
3460
|
+
/**
|
|
3461
|
+
* Is parent is hash router
|
|
3462
|
+
* In fact, this is not true. It just means that the parameter is added to the hash
|
|
3463
|
+
*/
|
|
3464
|
+
let isAttach2Hash = false;
|
|
3465
|
+
// If hash exists and search does not exist, it is considered as a hash route
|
|
3432
3466
|
if (hash && !search) {
|
|
3433
3467
|
isAttach2Hash = true;
|
|
3434
3468
|
if (queryObject.hashQuery) {
|
|
@@ -3458,7 +3492,11 @@ function setMicroPathToURL(appName, microLocation) {
|
|
|
3458
3492
|
isAttach2Hash,
|
|
3459
3493
|
};
|
|
3460
3494
|
}
|
|
3461
|
-
|
|
3495
|
+
/**
|
|
3496
|
+
* Delete child app fullPath from browser url
|
|
3497
|
+
* @param appName app.name
|
|
3498
|
+
* @param targetLocation target Location, default is rawLocation
|
|
3499
|
+
*/
|
|
3462
3500
|
function removeMicroPathFromURL(appName, targetLocation) {
|
|
3463
3501
|
var _a, _b, _c, _d;
|
|
3464
3502
|
let { pathname, search, hash } = targetLocation || globalEnv.rawWindow.location;
|
|
@@ -3481,7 +3519,7 @@ function removeMicroPathFromURL(appName, targetLocation) {
|
|
|
3481
3519
|
};
|
|
3482
3520
|
}
|
|
3483
3521
|
/**
|
|
3484
|
-
*
|
|
3522
|
+
* Format search, hash to object
|
|
3485
3523
|
*/
|
|
3486
3524
|
function getQueryObjectFromURL(search, hash) {
|
|
3487
3525
|
const queryObject = {};
|
|
@@ -3503,6 +3541,18 @@ function getNoHashMicroPathFromURL(appName, baseUrl) {
|
|
|
3503
3541
|
const formatLocation = createURL(microPath, baseUrl);
|
|
3504
3542
|
return formatLocation.origin + formatLocation.pathname + formatLocation.search;
|
|
3505
3543
|
}
|
|
3544
|
+
/**
|
|
3545
|
+
* Effect app is an app that can perform route navigation
|
|
3546
|
+
* NOTE: Invalid app action
|
|
3547
|
+
* 1. prevent update browser url, dispatch popStateEvent, reload browser
|
|
3548
|
+
* 2. It can update path with pushState/replaceState
|
|
3549
|
+
* 3. Can not update path outside (with router api)
|
|
3550
|
+
* 3. Can not update path by location
|
|
3551
|
+
*/
|
|
3552
|
+
function isEffectiveApp(appName) {
|
|
3553
|
+
const app = appInstanceMap.get(appName);
|
|
3554
|
+
return !!(app && !app.isPrefetch);
|
|
3555
|
+
}
|
|
3506
3556
|
|
|
3507
3557
|
/**
|
|
3508
3558
|
* dispatch PopStateEvent & HashChangeEvent to child app
|
|
@@ -3519,7 +3569,8 @@ function addHistoryListener(appName) {
|
|
|
3519
3569
|
* 1. unmount app & hidden keep-alive app will not receive popstate event
|
|
3520
3570
|
* 2. filter out onlyForBrowser
|
|
3521
3571
|
*/
|
|
3522
|
-
if (getActiveApps(true).includes(appName) &&
|
|
3572
|
+
if (getActiveApps({ excludeHiddenApp: true, excludePreRender: true }).includes(appName) &&
|
|
3573
|
+
!e.onlyForBrowser) {
|
|
3523
3574
|
const microPath = getMicroPathFromURL(appName);
|
|
3524
3575
|
const app = appInstanceMap.get(appName);
|
|
3525
3576
|
const proxyWindow = app.sandBox.proxyWindow;
|
|
@@ -3607,15 +3658,18 @@ function dispatchNativeHashChangeEvent(oldHref) {
|
|
|
3607
3658
|
}
|
|
3608
3659
|
/**
|
|
3609
3660
|
* dispatch popstate & hashchange event to browser
|
|
3661
|
+
* @param appName app.name
|
|
3610
3662
|
* @param onlyForBrowser only dispatch event to browser
|
|
3611
3663
|
* @param oldHref old href of rawWindow.location
|
|
3612
3664
|
*/
|
|
3613
|
-
function dispatchNativeEvent(onlyForBrowser, oldHref) {
|
|
3665
|
+
function dispatchNativeEvent(appName, onlyForBrowser, oldHref) {
|
|
3614
3666
|
// clear element scope before dispatch global event
|
|
3615
3667
|
removeDomScope();
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3668
|
+
if (isEffectiveApp(appName)) {
|
|
3669
|
+
dispatchNativePopStateEvent(onlyForBrowser);
|
|
3670
|
+
if (oldHref) {
|
|
3671
|
+
dispatchNativeHashChangeEvent(oldHref);
|
|
3672
|
+
}
|
|
3619
3673
|
}
|
|
3620
3674
|
}
|
|
3621
3675
|
|
|
@@ -3632,7 +3686,7 @@ function createMicroHistory(appName, microLocation) {
|
|
|
3632
3686
|
if (isString(rests[2]) || isURL(rests[2])) {
|
|
3633
3687
|
const targetLocation = createURL(rests[2], microLocation.href);
|
|
3634
3688
|
if (targetLocation.origin === microLocation.origin) {
|
|
3635
|
-
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rests[0]), rests[1]);
|
|
3689
|
+
navigateWithNativeEvent(appName, methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rests[0]), rests[1]);
|
|
3636
3690
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3637
3691
|
if (targetFullPath !== microLocation.fullPath) {
|
|
3638
3692
|
updateMicroLocation(appName, targetFullPath, microLocation);
|
|
@@ -3640,7 +3694,7 @@ function createMicroHistory(appName, microLocation) {
|
|
|
3640
3694
|
return void 0;
|
|
3641
3695
|
}
|
|
3642
3696
|
}
|
|
3643
|
-
nativeHistoryNavigate(methodName, rests[2], rests[0], rests[1]);
|
|
3697
|
+
nativeHistoryNavigate(appName, methodName, rests[2], rests[0], rests[1]);
|
|
3644
3698
|
};
|
|
3645
3699
|
}
|
|
3646
3700
|
const pushState = getMicroHistoryMethod('pushState');
|
|
@@ -3672,14 +3726,17 @@ function createMicroHistory(appName, microLocation) {
|
|
|
3672
3726
|
}
|
|
3673
3727
|
/**
|
|
3674
3728
|
* navigate to new path base on native method of history
|
|
3729
|
+
* @param appName app.name
|
|
3675
3730
|
* @param methodName pushState/replaceState
|
|
3676
3731
|
* @param fullPath full path
|
|
3677
3732
|
* @param state history.state, default is null
|
|
3678
3733
|
* @param title history.title, default is ''
|
|
3679
3734
|
*/
|
|
3680
|
-
function nativeHistoryNavigate(methodName, fullPath, state = null, title = '') {
|
|
3681
|
-
|
|
3682
|
-
|
|
3735
|
+
function nativeHistoryNavigate(appName, methodName, fullPath, state = null, title = '') {
|
|
3736
|
+
if (isEffectiveApp(appName)) {
|
|
3737
|
+
const method = methodName === 'pushState' ? globalEnv.rawPushState : globalEnv.rawReplaceState;
|
|
3738
|
+
method.call(globalEnv.rawWindow.history, state, title, fullPath);
|
|
3739
|
+
}
|
|
3683
3740
|
}
|
|
3684
3741
|
/**
|
|
3685
3742
|
* Navigate to new path, and dispatch native popStateEvent/hashChangeEvent to browser
|
|
@@ -3688,29 +3745,33 @@ function nativeHistoryNavigate(methodName, fullPath, state = null, title = '') {
|
|
|
3688
3745
|
* 2. proxyHistory.pushState/replaceState with limited popstateEvent
|
|
3689
3746
|
* 3. api microApp.router.push/replace
|
|
3690
3747
|
* 4. proxyLocation.hash = xxx
|
|
3748
|
+
* @param appName app.name
|
|
3691
3749
|
* @param methodName pushState/replaceState
|
|
3692
3750
|
* @param result result of add/remove microApp path on browser url
|
|
3693
3751
|
* @param onlyForBrowser only dispatch event to browser
|
|
3694
3752
|
* @param state history.state, not required
|
|
3695
3753
|
* @param title history.title, not required
|
|
3696
3754
|
*/
|
|
3697
|
-
function navigateWithNativeEvent(methodName, result, onlyForBrowser, state, title) {
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3755
|
+
function navigateWithNativeEvent(appName, methodName, result, onlyForBrowser, state, title) {
|
|
3756
|
+
if (isEffectiveApp(appName)) {
|
|
3757
|
+
const rawLocation = globalEnv.rawWindow.location;
|
|
3758
|
+
const oldFullPath = rawLocation.pathname + rawLocation.search + rawLocation.hash;
|
|
3759
|
+
const oldHref = result.isAttach2Hash && oldFullPath !== result.fullPath ? rawLocation.href : null;
|
|
3760
|
+
// navigate with native history method
|
|
3761
|
+
nativeHistoryNavigate(appName, methodName, result.fullPath, state, title);
|
|
3762
|
+
if (oldFullPath !== result.fullPath)
|
|
3763
|
+
dispatchNativeEvent(appName, onlyForBrowser, oldHref);
|
|
3764
|
+
}
|
|
3705
3765
|
}
|
|
3706
3766
|
/**
|
|
3707
3767
|
* update browser url when mount/unmount/hidden/show/attachToURL/attachAllToURL
|
|
3708
3768
|
* just attach microRoute info to browser, dispatch event to base app(exclude child)
|
|
3769
|
+
* @param appName app.name
|
|
3709
3770
|
* @param result result of add/remove microApp path on browser url
|
|
3710
3771
|
* @param state history.state
|
|
3711
3772
|
*/
|
|
3712
|
-
function attachRouteToBrowserURL(result, state) {
|
|
3713
|
-
navigateWithNativeEvent('replaceState', result, true, state);
|
|
3773
|
+
function attachRouteToBrowserURL(appName, result, state) {
|
|
3774
|
+
navigateWithNativeEvent(appName, 'replaceState', result, true, state);
|
|
3714
3775
|
}
|
|
3715
3776
|
/**
|
|
3716
3777
|
* When path is same, keep the microAppState in history.state
|
|
@@ -3740,10 +3801,13 @@ function reWriteHistoryMethod(method) {
|
|
|
3740
3801
|
* 2. Unable to catch when base app navigate with location
|
|
3741
3802
|
* 3. When in nest app, rawPushState/rawReplaceState has been modified by parent
|
|
3742
3803
|
*/
|
|
3743
|
-
getActiveApps(
|
|
3804
|
+
getActiveApps({
|
|
3805
|
+
excludeHiddenApp: true,
|
|
3806
|
+
excludePreRender: true,
|
|
3807
|
+
}).forEach(appName => {
|
|
3744
3808
|
const app = appInstanceMap.get(appName);
|
|
3745
3809
|
if (app.sandBox && app.useMemoryRouter && !getMicroPathFromURL(appName)) {
|
|
3746
|
-
attachRouteToBrowserURL(setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3810
|
+
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3747
3811
|
}
|
|
3748
3812
|
});
|
|
3749
3813
|
// fix bug for nest app
|
|
@@ -3775,7 +3839,7 @@ function createRouterApi() {
|
|
|
3775
3839
|
* @param state to.state
|
|
3776
3840
|
*/
|
|
3777
3841
|
function navigateWithRawHistory(appName, methodName, targetLocation, state) {
|
|
3778
|
-
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName, state !== null && state !== void 0 ? state : null));
|
|
3842
|
+
navigateWithNativeEvent(appName, methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName, state !== null && state !== void 0 ? state : null));
|
|
3779
3843
|
// clear element scope after navigate
|
|
3780
3844
|
removeDomScope();
|
|
3781
3845
|
}
|
|
@@ -3796,7 +3860,7 @@ function createRouterApi() {
|
|
|
3796
3860
|
return logError(`navigation failed, memory router of app ${appName} is closed`);
|
|
3797
3861
|
}
|
|
3798
3862
|
// active apps, include hidden keep-alive app
|
|
3799
|
-
if (getActiveApps().includes(appName)) {
|
|
3863
|
+
if (getActiveApps({ excludePreRender: true }).includes(appName)) {
|
|
3800
3864
|
const microLocation = app.sandBox.proxyWindow.location;
|
|
3801
3865
|
const targetLocation = createURL(to.path, microLocation.href);
|
|
3802
3866
|
// Only get path data, even if the origin is different from microApp
|
|
@@ -3879,7 +3943,7 @@ function createRouterApi() {
|
|
|
3879
3943
|
function commonHandlerForAttachToURL(appName) {
|
|
3880
3944
|
const app = appInstanceMap.get(appName);
|
|
3881
3945
|
if (app.sandBox && app.useMemoryRouter) {
|
|
3882
|
-
attachRouteToBrowserURL(setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3946
|
+
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3883
3947
|
}
|
|
3884
3948
|
}
|
|
3885
3949
|
/**
|
|
@@ -3894,10 +3958,14 @@ function createRouterApi() {
|
|
|
3894
3958
|
}
|
|
3895
3959
|
/**
|
|
3896
3960
|
* Attach all active app router info to browser url
|
|
3897
|
-
*
|
|
3961
|
+
* @param includeHiddenApp include hidden keep-alive app
|
|
3962
|
+
* @param includePreRender include preRender app
|
|
3898
3963
|
*/
|
|
3899
|
-
function attachAllToURL(includeHiddenApp = false) {
|
|
3900
|
-
getActiveApps(
|
|
3964
|
+
function attachAllToURL({ includeHiddenApp = false, includePreRender = false, }) {
|
|
3965
|
+
getActiveApps({
|
|
3966
|
+
excludeHiddenApp: !includeHiddenApp,
|
|
3967
|
+
excludePreRender: !includePreRender,
|
|
3968
|
+
}).forEach(appName => commonHandlerForAttachToURL(appName));
|
|
3901
3969
|
}
|
|
3902
3970
|
function createDefaultPageApi() {
|
|
3903
3971
|
// defaultPage data
|
|
@@ -3912,7 +3980,7 @@ function createRouterApi() {
|
|
|
3912
3980
|
function setDefaultPage(options) {
|
|
3913
3981
|
const appName = formatAppName(options.name);
|
|
3914
3982
|
if (!appName || !options.path) {
|
|
3915
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
3983
|
+
if ((process.env.NODE_ENV !== 'production')) {
|
|
3916
3984
|
if (!appName) {
|
|
3917
3985
|
logWarn(`setDefaultPage: invalid appName "${appName}"`);
|
|
3918
3986
|
}
|
|
@@ -3955,7 +4023,7 @@ function createRouterApi() {
|
|
|
3955
4023
|
}
|
|
3956
4024
|
});
|
|
3957
4025
|
}
|
|
3958
|
-
else if (process.env.NODE_ENV !== 'production') {
|
|
4026
|
+
else if ((process.env.NODE_ENV !== 'production')) {
|
|
3959
4027
|
logWarn('setBaseAppRouter: Invalid base router');
|
|
3960
4028
|
}
|
|
3961
4029
|
}
|
|
@@ -4023,13 +4091,13 @@ function createMicroLocation(appName, url) {
|
|
|
4023
4091
|
if (targetLocation.hash !== shadowLocation.hash) {
|
|
4024
4092
|
if (setMicroPathResult.isAttach2Hash)
|
|
4025
4093
|
oldHref = rawLocation.href;
|
|
4026
|
-
nativeHistoryNavigate(methodName, setMicroPathResult.fullPath);
|
|
4094
|
+
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath);
|
|
4027
4095
|
}
|
|
4028
4096
|
if (targetLocation.hash) {
|
|
4029
|
-
dispatchNativeEvent(false, oldHref);
|
|
4097
|
+
dispatchNativeEvent(appName, false, oldHref);
|
|
4030
4098
|
}
|
|
4031
4099
|
else {
|
|
4032
|
-
|
|
4100
|
+
rawReload();
|
|
4033
4101
|
}
|
|
4034
4102
|
return void 0;
|
|
4035
4103
|
/**
|
|
@@ -4038,8 +4106,8 @@ function createMicroLocation(appName, url) {
|
|
|
4038
4106
|
*/
|
|
4039
4107
|
}
|
|
4040
4108
|
else if (setMicroPathResult.isAttach2Hash) {
|
|
4041
|
-
nativeHistoryNavigate(methodName, setMicroPathResult.fullPath);
|
|
4042
|
-
|
|
4109
|
+
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath);
|
|
4110
|
+
rawReload();
|
|
4043
4111
|
return void 0;
|
|
4044
4112
|
}
|
|
4045
4113
|
value = setMicroPathResult.fullPath;
|
|
@@ -4069,7 +4137,7 @@ function createMicroLocation(appName, url) {
|
|
|
4069
4137
|
// When the browser url has a hash value, the same pathname/search will not refresh browser
|
|
4070
4138
|
if (targetLocation[key] === shadowLocation[key] && shadowLocation.hash) {
|
|
4071
4139
|
// The href has not changed, not need to dispatch hashchange event
|
|
4072
|
-
dispatchNativeEvent(false);
|
|
4140
|
+
dispatchNativeEvent(appName, false);
|
|
4073
4141
|
}
|
|
4074
4142
|
else {
|
|
4075
4143
|
/**
|
|
@@ -4078,19 +4146,24 @@ function createMicroLocation(appName, url) {
|
|
|
4078
4146
|
* pathname: /path ==> /path#hash, /path ==> /path?query
|
|
4079
4147
|
* search: ?query ==> ?query#hash
|
|
4080
4148
|
*/
|
|
4081
|
-
nativeHistoryNavigate(targetLocation[key] === shadowLocation[key] ? 'replaceState' : 'pushState', setMicroPathToURL(appName, targetLocation).fullPath);
|
|
4082
|
-
|
|
4149
|
+
nativeHistoryNavigate(appName, targetLocation[key] === shadowLocation[key] ? 'replaceState' : 'pushState', setMicroPathToURL(appName, targetLocation).fullPath);
|
|
4150
|
+
rawReload();
|
|
4083
4151
|
}
|
|
4084
4152
|
}
|
|
4153
|
+
function rawReload() {
|
|
4154
|
+
isEffectiveApp(appName) && rawLocation.reload();
|
|
4155
|
+
}
|
|
4085
4156
|
/**
|
|
4086
4157
|
* Special processing for four keys: href, pathname, search and hash
|
|
4087
4158
|
* They take values from shadowLocation, and require special operations when assigning values
|
|
4088
4159
|
*/
|
|
4089
4160
|
rawDefineProperties(microLocation, {
|
|
4090
4161
|
href: createPropertyDescriptor(() => shadowLocation.href, (value) => {
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4162
|
+
if (isEffectiveApp(appName)) {
|
|
4163
|
+
const targetPath = commonHandler(value, 'pushState');
|
|
4164
|
+
if (targetPath)
|
|
4165
|
+
rawLocation.href = targetPath;
|
|
4166
|
+
}
|
|
4094
4167
|
}),
|
|
4095
4168
|
pathname: createPropertyDescriptor(() => shadowLocation.pathname, (value) => {
|
|
4096
4169
|
const targetPath = ('/' + value).replace(/^\/+/, '/') + shadowLocation.search + shadowLocation.hash;
|
|
@@ -4105,16 +4178,18 @@ function createMicroLocation(appName, url) {
|
|
|
4105
4178
|
const targetLocation = createURL(targetPath, url);
|
|
4106
4179
|
// The same hash will not trigger popStateEvent
|
|
4107
4180
|
if (targetLocation.hash !== shadowLocation.hash) {
|
|
4108
|
-
navigateWithNativeEvent('pushState', setMicroPathToURL(appName, targetLocation), false);
|
|
4181
|
+
navigateWithNativeEvent(appName, 'pushState', setMicroPathToURL(appName, targetLocation), false);
|
|
4109
4182
|
}
|
|
4110
4183
|
}),
|
|
4111
4184
|
fullPath: createPropertyDescriptor(() => shadowLocation.pathname + shadowLocation.search + shadowLocation.hash, noop),
|
|
4112
4185
|
});
|
|
4113
4186
|
const createLocationMethod = (locationMethodName) => {
|
|
4114
4187
|
return function (value) {
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4188
|
+
if (isEffectiveApp(appName)) {
|
|
4189
|
+
const targetPath = commonHandler(value, locationMethodName === 'assign' ? 'pushState' : 'replaceState');
|
|
4190
|
+
if (targetPath)
|
|
4191
|
+
rawLocation[locationMethodName](targetPath);
|
|
4192
|
+
}
|
|
4118
4193
|
};
|
|
4119
4194
|
};
|
|
4120
4195
|
return assign(microLocation, {
|
|
@@ -4213,7 +4288,7 @@ function updateBrowserURLWithLocation(appName, microLocation, defaultPage) {
|
|
|
4213
4288
|
if (defaultPage)
|
|
4214
4289
|
updateMicroLocation(appName, defaultPage, microLocation, 'prevent');
|
|
4215
4290
|
// attach microApp route info to browser URL
|
|
4216
|
-
attachRouteToBrowserURL(setMicroPathToURL(appName, microLocation), setMicroState(appName, null));
|
|
4291
|
+
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, microLocation), setMicroState(appName, null));
|
|
4217
4292
|
// trigger guards after change browser URL
|
|
4218
4293
|
autoTriggerNavigationGuard(appName, microLocation);
|
|
4219
4294
|
}
|
|
@@ -4237,7 +4312,7 @@ function clearRouteStateFromURL(appName, url, microLocation, keepRouteState) {
|
|
|
4237
4312
|
* called on sandbox.stop or hidden of keep-alive app
|
|
4238
4313
|
*/
|
|
4239
4314
|
function removeStateAndPathFromBrowser(appName) {
|
|
4240
|
-
attachRouteToBrowserURL(removeMicroPathFromURL(appName), removeMicroState(appName, globalEnv.rawWindow.history.state));
|
|
4315
|
+
attachRouteToBrowserURL(appName, removeMicroPathFromURL(appName), removeMicroState(appName, globalEnv.rawWindow.history.state));
|
|
4241
4316
|
}
|
|
4242
4317
|
|
|
4243
4318
|
/**
|
|
@@ -4369,7 +4444,7 @@ class SandBox {
|
|
|
4369
4444
|
// create proxyWindow with Proxy(microAppWindow)
|
|
4370
4445
|
this.proxyWindow = this.createProxyWindow(appName);
|
|
4371
4446
|
// Rewrite global event listener & timeout
|
|
4372
|
-
|
|
4447
|
+
this.effectController = effect(appName, this.microAppWindow);
|
|
4373
4448
|
// inject global properties
|
|
4374
4449
|
this.initStaticGlobalKeys(this.microAppWindow, appName, url);
|
|
4375
4450
|
}
|
|
@@ -4420,10 +4495,8 @@ class SandBox {
|
|
|
4420
4495
|
*/
|
|
4421
4496
|
stop({ umdMode, keepRouteState, clearEventSource, clearData, }) {
|
|
4422
4497
|
if (this.active) {
|
|
4423
|
-
|
|
4424
|
-
this.
|
|
4425
|
-
this.microAppWindow.microApp.clearGlobalDataListener();
|
|
4426
|
-
clearData && this.microAppWindow.microApp.clearData();
|
|
4498
|
+
// clear global event, timeout, data listener
|
|
4499
|
+
this.releaseGlobalEffect(clearData);
|
|
4427
4500
|
if (this.removeHistoryListener) {
|
|
4428
4501
|
this.clearRouteState(keepRouteState);
|
|
4429
4502
|
// release listener of popstate
|
|
@@ -4456,10 +4529,33 @@ class SandBox {
|
|
|
4456
4529
|
this.active = false;
|
|
4457
4530
|
}
|
|
4458
4531
|
}
|
|
4459
|
-
|
|
4460
|
-
|
|
4532
|
+
/**
|
|
4533
|
+
* clear global event, timeout, data listener
|
|
4534
|
+
* Scenes:
|
|
4535
|
+
* 1. unmount of normal/umd app
|
|
4536
|
+
* 2. hidden keep-alive app
|
|
4537
|
+
* 3. after init prerender app
|
|
4538
|
+
* @param clearData clear data from base app
|
|
4539
|
+
*/
|
|
4540
|
+
releaseGlobalEffect(clearData = false) {
|
|
4541
|
+
this.effectController.releaseEffect();
|
|
4542
|
+
this.microAppWindow.microApp.clearDataListener();
|
|
4543
|
+
this.microAppWindow.microApp.clearGlobalDataListener();
|
|
4544
|
+
if (clearData) {
|
|
4545
|
+
microApp.clearData(this.microAppWindow.__MICRO_APP_NAME__);
|
|
4546
|
+
this.microAppWindow.microApp.clearData();
|
|
4547
|
+
}
|
|
4548
|
+
}
|
|
4549
|
+
/**
|
|
4550
|
+
* record umd snapshot before the first execution of umdHookMount
|
|
4551
|
+
* Scenes:
|
|
4552
|
+
* 1. exec umdMountHook in umd mode
|
|
4553
|
+
* 2. hidden keep-alive app
|
|
4554
|
+
* 3. after init prerender app
|
|
4555
|
+
*/
|
|
4556
|
+
recordEffectSnapshot() {
|
|
4461
4557
|
// this.microAppWindow.__MICRO_APP_UMD_MODE__ = true
|
|
4462
|
-
this.
|
|
4558
|
+
this.effectController.recordEffect();
|
|
4463
4559
|
recordDataCenterSnapshot(this.microAppWindow.microApp);
|
|
4464
4560
|
// this.recordUmdInjectedValues = new Map<PropertyKey, unknown>()
|
|
4465
4561
|
// this.injectedKeys.forEach((key: PropertyKey) => {
|
|
@@ -4467,13 +4563,17 @@ class SandBox {
|
|
|
4467
4563
|
// })
|
|
4468
4564
|
}
|
|
4469
4565
|
// rebuild umd snapshot before remount umd app
|
|
4470
|
-
|
|
4566
|
+
rebuildEffectSnapshot() {
|
|
4471
4567
|
// this.recordUmdInjectedValues!.forEach((value: unknown, key: PropertyKey) => {
|
|
4472
4568
|
// Reflect.set(this.proxyWindow, key, value)
|
|
4473
4569
|
// })
|
|
4474
|
-
this.
|
|
4570
|
+
this.effectController.rebuildEffect();
|
|
4475
4571
|
rebuildDataCenterSnapshot(this.microAppWindow.microApp);
|
|
4476
4572
|
}
|
|
4573
|
+
// set __MICRO_APP_PRE_RENDER__ state
|
|
4574
|
+
setPreRenderState(state) {
|
|
4575
|
+
this.microAppWindow.__MICRO_APP_PRE_RENDER__ = state;
|
|
4576
|
+
}
|
|
4477
4577
|
/**
|
|
4478
4578
|
* get scopeProperties and escapeProperties from plugins & adapter
|
|
4479
4579
|
* @param appName app name
|
|
@@ -4607,6 +4707,7 @@ class SandBox {
|
|
|
4607
4707
|
microAppWindow.__MICRO_APP_URL__ = url;
|
|
4608
4708
|
microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
|
|
4609
4709
|
microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
|
|
4710
|
+
microAppWindow.__MICRO_APP_PRE_RENDER__ = false;
|
|
4610
4711
|
microAppWindow.rawWindow = globalEnv.rawWindow;
|
|
4611
4712
|
microAppWindow.rawDocument = globalEnv.rawDocument;
|
|
4612
4713
|
microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
|
|
@@ -4918,7 +5019,7 @@ function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
|
|
|
4918
5019
|
// micro app instances
|
|
4919
5020
|
const appInstanceMap = new Map();
|
|
4920
5021
|
class CreateApp {
|
|
4921
|
-
constructor({ name, url, container, scopecss, useSandbox, inline, esmodule, ssrUrl, isPrefetch, }) {
|
|
5022
|
+
constructor({ name, url, container, scopecss, useSandbox, inline, esmodule, ssrUrl, isPrefetch, prefetchLevel, }) {
|
|
4922
5023
|
this.state = appStates.CREATED;
|
|
4923
5024
|
this.keepAliveState = null;
|
|
4924
5025
|
this.keepAliveContainer = null;
|
|
@@ -4928,7 +5029,6 @@ class CreateApp {
|
|
|
4928
5029
|
this.libraryName = null;
|
|
4929
5030
|
this.umdMode = false;
|
|
4930
5031
|
this.sandBox = null;
|
|
4931
|
-
this.keepRouteState = false;
|
|
4932
5032
|
this.fiber = false;
|
|
4933
5033
|
this.useMemoryRouter = true;
|
|
4934
5034
|
this.name = name;
|
|
@@ -4940,8 +5040,10 @@ class CreateApp {
|
|
|
4940
5040
|
// not exist when prefetch 👇
|
|
4941
5041
|
this.container = container !== null && container !== void 0 ? container : null;
|
|
4942
5042
|
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
4943
|
-
//
|
|
5043
|
+
// exist only prefetch 👇
|
|
4944
5044
|
this.isPrefetch = isPrefetch !== null && isPrefetch !== void 0 ? isPrefetch : false;
|
|
5045
|
+
this.isPrerender = prefetchLevel === 3;
|
|
5046
|
+
this.prefetchLevel = prefetchLevel;
|
|
4945
5047
|
// init actions
|
|
4946
5048
|
appInstanceMap.set(this.name, this);
|
|
4947
5049
|
this.source = { html: null, links: new Set(), scripts: new Set() };
|
|
@@ -4956,14 +5058,46 @@ class CreateApp {
|
|
|
4956
5058
|
/**
|
|
4957
5059
|
* When resource is loaded, mount app if it is not prefetch or unmount
|
|
4958
5060
|
*/
|
|
4959
|
-
onLoad(html) {
|
|
5061
|
+
onLoad(html, defaultPage, disablePatchRequest) {
|
|
5062
|
+
var _a;
|
|
4960
5063
|
if (++this.loadSourceLevel === 2) {
|
|
4961
5064
|
this.source.html = html;
|
|
4962
5065
|
this.state = appStates.LOADED;
|
|
4963
5066
|
if (!this.isPrefetch && appStates.UNMOUNT !== this.state) {
|
|
4964
|
-
// @ts-ignore
|
|
4965
5067
|
getRootContainer(this.container).mount(this);
|
|
4966
5068
|
}
|
|
5069
|
+
else if (this.isPrerender) {
|
|
5070
|
+
/**
|
|
5071
|
+
* PreRender is an option of prefetch, it will render app during prefetch
|
|
5072
|
+
* Limit:
|
|
5073
|
+
* 1. fiber forced on
|
|
5074
|
+
* 2. only virtual router support
|
|
5075
|
+
*
|
|
5076
|
+
* NOTE: (4P: not - update browser url, dispatch popstateEvent, reload window, dispatch lifecycle event)
|
|
5077
|
+
* 1. pushState/replaceState in child can update microLocation, but will not attach router info to browser url
|
|
5078
|
+
* 2. prevent dispatch popstate/hashchange event to browser
|
|
5079
|
+
* 3. all navigation actions of location are invalid (In the future, we can consider update microLocation without trigger browser reload)
|
|
5080
|
+
* 4. lifecycle event will not trigger when prerender
|
|
5081
|
+
*
|
|
5082
|
+
* Special scenes
|
|
5083
|
+
* 1. unmount prerender app when loading
|
|
5084
|
+
* 2. unmount prerender app when exec js
|
|
5085
|
+
* 2. unmount prerender app after exec js
|
|
5086
|
+
*/
|
|
5087
|
+
const container = pureCreateElement('div');
|
|
5088
|
+
container.setAttribute('prerender', 'true');
|
|
5089
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.setPreRenderState(true);
|
|
5090
|
+
this.mount({
|
|
5091
|
+
container,
|
|
5092
|
+
inline: this.inline,
|
|
5093
|
+
useMemoryRouter: true,
|
|
5094
|
+
baseroute: '',
|
|
5095
|
+
fiber: true,
|
|
5096
|
+
esmodule: this.esmodule,
|
|
5097
|
+
defaultPage: defaultPage !== null && defaultPage !== void 0 ? defaultPage : '',
|
|
5098
|
+
disablePatchRequest: disablePatchRequest !== null && disablePatchRequest !== void 0 ? disablePatchRequest : false,
|
|
5099
|
+
});
|
|
5100
|
+
}
|
|
4967
5101
|
}
|
|
4968
5102
|
}
|
|
4969
5103
|
/**
|
|
@@ -4980,29 +5114,86 @@ class CreateApp {
|
|
|
4980
5114
|
/**
|
|
4981
5115
|
* mount app
|
|
4982
5116
|
* @param container app container
|
|
4983
|
-
* @param inline js
|
|
5117
|
+
* @param inline run js in inline mode
|
|
5118
|
+
* @param useMemoryRouter use virtual router
|
|
5119
|
+
* @param defaultPage default page of virtual router
|
|
4984
5120
|
* @param baseroute route prefix, default is ''
|
|
4985
|
-
* @param keepRouteState keep route state when unmount, default is false
|
|
4986
5121
|
* @param disablePatchRequest prevent rewrite request method of child app
|
|
5122
|
+
* @param fiber run js in fiber mode
|
|
5123
|
+
* @param esmodule support type='module' script
|
|
4987
5124
|
*/
|
|
4988
|
-
mount({ container, inline,
|
|
4989
|
-
var _a, _b;
|
|
5125
|
+
mount({ container, inline, useMemoryRouter, defaultPage, baseroute, disablePatchRequest, fiber, esmodule, }) {
|
|
5126
|
+
var _a, _b, _c, _d, _e, _f;
|
|
5127
|
+
if (this.loadSourceLevel !== 2) {
|
|
5128
|
+
/**
|
|
5129
|
+
* unmount prefetch app when loading source, when mount again before loading end,
|
|
5130
|
+
* isPrefetch & isPrerender will be reset, and this.container sill be null
|
|
5131
|
+
* so we should set this.container
|
|
5132
|
+
*/
|
|
5133
|
+
this.container = container;
|
|
5134
|
+
// mount before prerender exec mount (loading source), set isPrerender to false
|
|
5135
|
+
this.isPrerender = false;
|
|
5136
|
+
// reset app state to LOADING
|
|
5137
|
+
this.state = appStates.LOADING;
|
|
5138
|
+
return;
|
|
5139
|
+
}
|
|
5140
|
+
/**
|
|
5141
|
+
* Mount app with prerender, this.container is empty
|
|
5142
|
+
* When rendering again, identify prerender by this.container
|
|
5143
|
+
* Transfer the contents of div to the <micro-app> tag
|
|
5144
|
+
*
|
|
5145
|
+
* Special scenes:
|
|
5146
|
+
* 1. mount before prerender exec mount (loading source)
|
|
5147
|
+
* 2. mount when prerender js executing
|
|
5148
|
+
* 3. mount after prerender js exec end
|
|
5149
|
+
*
|
|
5150
|
+
* TODO: test shadowDOM
|
|
5151
|
+
*/
|
|
5152
|
+
if (this.container instanceof HTMLDivElement &&
|
|
5153
|
+
this.container.hasAttribute('prerender')) {
|
|
5154
|
+
/**
|
|
5155
|
+
* rebuild effect event of window, document, data center
|
|
5156
|
+
* explain:
|
|
5157
|
+
* 1. rebuild before exec mount, do nothing
|
|
5158
|
+
* 2. rebuild when js executing, recovery recorded effect event, because prerender fiber mode
|
|
5159
|
+
* 3. rebuild after js exec end, normal recovery effect event
|
|
5160
|
+
*/
|
|
5161
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.rebuildEffectSnapshot();
|
|
5162
|
+
// current this.container is <div prerender='true'></div>
|
|
5163
|
+
cloneContainer(this.container, container, false);
|
|
5164
|
+
/**
|
|
5165
|
+
* set this.container to <micro-app></micro-app>
|
|
5166
|
+
* NOTE:
|
|
5167
|
+
* must before exec this.preRenderEvent?.forEach((cb) => cb())
|
|
5168
|
+
*/
|
|
5169
|
+
this.container = container;
|
|
5170
|
+
(_b = this.preRenderEvent) === null || _b === void 0 ? void 0 : _b.forEach((cb) => cb());
|
|
5171
|
+
// reset isPrerender config
|
|
5172
|
+
this.isPrerender = false;
|
|
5173
|
+
this.preRenderEvent = undefined;
|
|
5174
|
+
// attach router info to browser url
|
|
5175
|
+
router.attachToURL(this.name);
|
|
5176
|
+
return (_c = this.sandBox) === null || _c === void 0 ? void 0 : _c.setPreRenderState(false);
|
|
5177
|
+
}
|
|
4990
5178
|
this.container = container;
|
|
4991
5179
|
this.inline = inline;
|
|
4992
5180
|
this.esmodule = esmodule;
|
|
4993
|
-
this.keepRouteState = keepRouteState;
|
|
4994
5181
|
this.fiber = fiber;
|
|
4995
5182
|
// use in sandbox/effect
|
|
4996
5183
|
this.useMemoryRouter = useMemoryRouter;
|
|
4997
5184
|
// this.hiddenRouter = hiddenRouter ?? this.hiddenRouter
|
|
4998
|
-
|
|
4999
|
-
this.
|
|
5000
|
-
|
|
5185
|
+
const dispatchBeforeMount = () => {
|
|
5186
|
+
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
|
|
5187
|
+
};
|
|
5188
|
+
if (this.isPrerender) {
|
|
5189
|
+
((_d = this.preRenderEvent) !== null && _d !== void 0 ? _d : (this.preRenderEvent = [])).push(dispatchBeforeMount);
|
|
5190
|
+
}
|
|
5191
|
+
else {
|
|
5192
|
+
dispatchBeforeMount();
|
|
5001
5193
|
}
|
|
5002
|
-
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
|
|
5003
5194
|
this.state = appStates.MOUNTING;
|
|
5004
5195
|
cloneContainer(this.source.html, this.container, !this.umdMode);
|
|
5005
|
-
(
|
|
5196
|
+
(_e = this.sandBox) === null || _e === void 0 ? void 0 : _e.start({
|
|
5006
5197
|
umdMode: this.umdMode,
|
|
5007
5198
|
baseroute,
|
|
5008
5199
|
useMemoryRouter,
|
|
@@ -5014,6 +5205,7 @@ class CreateApp {
|
|
|
5014
5205
|
let hasDispatchMountedEvent = false;
|
|
5015
5206
|
// if all js are executed, param isFinished will be true
|
|
5016
5207
|
execScripts(this, (isFinished) => {
|
|
5208
|
+
var _a;
|
|
5017
5209
|
if (!this.umdMode) {
|
|
5018
5210
|
const { mount, unmount } = this.getUmdLibraryHooks();
|
|
5019
5211
|
/**
|
|
@@ -5027,7 +5219,7 @@ class CreateApp {
|
|
|
5027
5219
|
this.umdMode = true;
|
|
5028
5220
|
if (this.sandBox)
|
|
5029
5221
|
this.sandBox.proxyWindow.__MICRO_APP_UMD_MODE__ = true;
|
|
5030
|
-
// this.sandBox?.
|
|
5222
|
+
// this.sandBox?.recordEffectSnapshot()
|
|
5031
5223
|
try {
|
|
5032
5224
|
umdHookMountResult = this.umdHookMount(microApp.getData(this.name, true));
|
|
5033
5225
|
}
|
|
@@ -5038,12 +5230,19 @@ class CreateApp {
|
|
|
5038
5230
|
}
|
|
5039
5231
|
if (!hasDispatchMountedEvent && (isFinished === true || this.umdMode)) {
|
|
5040
5232
|
hasDispatchMountedEvent = true;
|
|
5041
|
-
this.handleMounted(umdHookMountResult);
|
|
5233
|
+
const dispatchMounted = () => this.handleMounted(umdHookMountResult);
|
|
5234
|
+
if (this.isPrerender) {
|
|
5235
|
+
((_a = this.preRenderEvent) !== null && _a !== void 0 ? _a : (this.preRenderEvent = [])).push(dispatchMounted);
|
|
5236
|
+
this.recordAndReleaseEffect();
|
|
5237
|
+
}
|
|
5238
|
+
else {
|
|
5239
|
+
dispatchMounted();
|
|
5240
|
+
}
|
|
5042
5241
|
}
|
|
5043
5242
|
});
|
|
5044
5243
|
}
|
|
5045
5244
|
else {
|
|
5046
|
-
(
|
|
5245
|
+
(_f = this.sandBox) === null || _f === void 0 ? void 0 : _f.rebuildEffectSnapshot();
|
|
5047
5246
|
try {
|
|
5048
5247
|
umdHookMountResult = this.umdHookMount();
|
|
5049
5248
|
}
|
|
@@ -5083,9 +5282,11 @@ class CreateApp {
|
|
|
5083
5282
|
* unmount app
|
|
5084
5283
|
* NOTE: Do not add any params on account of unmountApp
|
|
5085
5284
|
* @param destroy completely destroy, delete cache resources
|
|
5285
|
+
* @param clearData clear data of dateCenter
|
|
5286
|
+
* @param keepRouteState keep route state when unmount, default is false
|
|
5086
5287
|
* @param unmountcb callback of unmount
|
|
5087
5288
|
*/
|
|
5088
|
-
unmount({ destroy, clearData, unmountcb, }) {
|
|
5289
|
+
unmount({ destroy, clearData, keepRouteState, unmountcb, }) {
|
|
5089
5290
|
if (this.state === appStates.LOAD_FAILED) {
|
|
5090
5291
|
destroy = true;
|
|
5091
5292
|
}
|
|
@@ -5110,30 +5311,40 @@ class CreateApp {
|
|
|
5110
5311
|
callFnWithTryCatch(this.getGlobalEventListener(microGlobalEvent.ONUNMOUNT), this.name, `window.${microGlobalEvent.ONUNMOUNT}`);
|
|
5111
5312
|
// dispatch unmount event to micro app
|
|
5112
5313
|
dispatchCustomEventToMicroApp('unmount', this.name);
|
|
5113
|
-
this.handleUnmounted(destroy, clearData, umdHookUnmountResult, unmountcb);
|
|
5314
|
+
this.handleUnmounted(destroy, clearData, keepRouteState, umdHookUnmountResult, unmountcb);
|
|
5114
5315
|
}
|
|
5115
5316
|
/**
|
|
5116
5317
|
* handle for promise umdHookUnmount
|
|
5117
5318
|
* @param destroy completely destroy, delete cache resources
|
|
5319
|
+
* @param clearData clear data of dateCenter
|
|
5320
|
+
* @param keepRouteState keep route state when unmount, default is false
|
|
5118
5321
|
* @param umdHookUnmountResult result of umdHookUnmount
|
|
5119
5322
|
* @param unmountcb callback of unmount
|
|
5120
5323
|
*/
|
|
5121
|
-
handleUnmounted(destroy, clearData, umdHookUnmountResult, unmountcb) {
|
|
5324
|
+
handleUnmounted(destroy, clearData, keepRouteState, umdHookUnmountResult, unmountcb) {
|
|
5325
|
+
const unmountParam = {
|
|
5326
|
+
destroy,
|
|
5327
|
+
clearData,
|
|
5328
|
+
keepRouteState,
|
|
5329
|
+
unmountcb,
|
|
5330
|
+
};
|
|
5122
5331
|
if (isPromise(umdHookUnmountResult)) {
|
|
5123
5332
|
umdHookUnmountResult
|
|
5124
|
-
.then(() => this.actionsForUnmount(
|
|
5125
|
-
.catch(() => this.actionsForUnmount(
|
|
5333
|
+
.then(() => this.actionsForUnmount(unmountParam))
|
|
5334
|
+
.catch(() => this.actionsForUnmount(unmountParam));
|
|
5126
5335
|
}
|
|
5127
5336
|
else {
|
|
5128
|
-
this.actionsForUnmount(
|
|
5337
|
+
this.actionsForUnmount(unmountParam);
|
|
5129
5338
|
}
|
|
5130
5339
|
}
|
|
5131
5340
|
/**
|
|
5132
5341
|
* actions for unmount app
|
|
5133
5342
|
* @param destroy completely destroy, delete cache resources
|
|
5343
|
+
* @param clearData clear data of dateCenter
|
|
5344
|
+
* @param keepRouteState keep route state when unmount, default is false
|
|
5134
5345
|
* @param unmountcb callback of unmount
|
|
5135
5346
|
*/
|
|
5136
|
-
actionsForUnmount(destroy, clearData, unmountcb) {
|
|
5347
|
+
actionsForUnmount({ destroy, clearData, keepRouteState, unmountcb }) {
|
|
5137
5348
|
var _a, _b;
|
|
5138
5349
|
if (destroy) {
|
|
5139
5350
|
this.actionsForCompletelyDestroy();
|
|
@@ -5142,10 +5353,7 @@ class CreateApp {
|
|
|
5142
5353
|
cloneContainer(this.container, this.source.html, false);
|
|
5143
5354
|
}
|
|
5144
5355
|
if (this.umdMode) {
|
|
5145
|
-
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.
|
|
5146
|
-
}
|
|
5147
|
-
if (clearData || destroy) {
|
|
5148
|
-
microApp.clearData(this.name);
|
|
5356
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.recordEffectSnapshot();
|
|
5149
5357
|
}
|
|
5150
5358
|
/**
|
|
5151
5359
|
* this.container maybe contains micro-app element, stop sandbox should exec after cloneContainer
|
|
@@ -5155,7 +5363,7 @@ class CreateApp {
|
|
|
5155
5363
|
*/
|
|
5156
5364
|
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.stop({
|
|
5157
5365
|
umdMode: this.umdMode,
|
|
5158
|
-
keepRouteState:
|
|
5366
|
+
keepRouteState: keepRouteState && !destroy,
|
|
5159
5367
|
clearEventSource: !this.umdMode || destroy,
|
|
5160
5368
|
clearData: clearData || destroy,
|
|
5161
5369
|
});
|
|
@@ -5164,9 +5372,14 @@ class CreateApp {
|
|
|
5164
5372
|
}
|
|
5165
5373
|
// dispatch unmount event to base app
|
|
5166
5374
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.UNMOUNT);
|
|
5375
|
+
this.resetConfig();
|
|
5376
|
+
unmountcb && unmountcb();
|
|
5377
|
+
}
|
|
5378
|
+
resetConfig() {
|
|
5167
5379
|
this.container.innerHTML = '';
|
|
5168
5380
|
this.container = null;
|
|
5169
|
-
|
|
5381
|
+
this.isPrerender = false;
|
|
5382
|
+
this.preRenderEvent = undefined;
|
|
5170
5383
|
}
|
|
5171
5384
|
// actions for completely destroy
|
|
5172
5385
|
actionsForCompletelyDestroy() {
|
|
@@ -5192,11 +5405,13 @@ class CreateApp {
|
|
|
5192
5405
|
dispatchLifecyclesEvent(oldContainer, this.name, lifeCycles.AFTERHIDDEN);
|
|
5193
5406
|
// called after lifeCyclesEvent
|
|
5194
5407
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.removeRouteInfoForKeepAliveApp();
|
|
5408
|
+
this.recordAndReleaseEffect();
|
|
5195
5409
|
callback && callback();
|
|
5196
5410
|
}
|
|
5197
5411
|
// show app when connectedCallback called with keep-alive
|
|
5198
5412
|
showKeepAliveApp(container) {
|
|
5199
|
-
var _a;
|
|
5413
|
+
var _a, _b;
|
|
5414
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.rebuildEffectSnapshot();
|
|
5200
5415
|
// dispatch beforeShow event to micro-app
|
|
5201
5416
|
dispatchCustomEventToMicroApp('appstate-change', this.name, {
|
|
5202
5417
|
appState: 'beforeshow',
|
|
@@ -5207,7 +5422,7 @@ class CreateApp {
|
|
|
5207
5422
|
this.container = container;
|
|
5208
5423
|
this.keepAliveState = keepAliveStates.KEEP_ALIVE_SHOW;
|
|
5209
5424
|
// called before lifeCyclesEvent
|
|
5210
|
-
(
|
|
5425
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.setRouteInfoForKeepAliveApp();
|
|
5211
5426
|
// dispatch afterShow event to micro-app
|
|
5212
5427
|
dispatchCustomEventToMicroApp('appstate-change', this.name, {
|
|
5213
5428
|
appState: 'aftershow',
|
|
@@ -5253,6 +5468,17 @@ class CreateApp {
|
|
|
5253
5468
|
const listener = (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow[eventName];
|
|
5254
5469
|
return isFunction(listener) ? listener : null;
|
|
5255
5470
|
}
|
|
5471
|
+
/**
|
|
5472
|
+
* Record global effect and then release (effect: global event, timeout, data listener)
|
|
5473
|
+
* Scenes:
|
|
5474
|
+
* 1. hidden keep-alive app
|
|
5475
|
+
* 2. after init prerender app
|
|
5476
|
+
*/
|
|
5477
|
+
recordAndReleaseEffect() {
|
|
5478
|
+
var _a, _b;
|
|
5479
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.recordEffectSnapshot();
|
|
5480
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.releaseGlobalEffect();
|
|
5481
|
+
}
|
|
5256
5482
|
}
|
|
5257
5483
|
|
|
5258
5484
|
/**
|
|
@@ -5448,7 +5674,7 @@ function defineElement(tagName) {
|
|
|
5448
5674
|
this.handleAppMount(app);
|
|
5449
5675
|
}
|
|
5450
5676
|
else if (app.isPrefetch || app.getAppState() === appStates.UNMOUNT) {
|
|
5451
|
-
if (process.env.NODE_ENV !== 'production' &&
|
|
5677
|
+
if ((process.env.NODE_ENV !== 'production') &&
|
|
5452
5678
|
app.scopecss === this.isScopecss() &&
|
|
5453
5679
|
app.useSandbox === this.isSandbox()) {
|
|
5454
5680
|
/**
|
|
@@ -5561,14 +5787,12 @@ function defineElement(tagName) {
|
|
|
5561
5787
|
app.mount({
|
|
5562
5788
|
container: (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this,
|
|
5563
5789
|
inline: this.getDisposeResult('inline'),
|
|
5564
|
-
esmodule: this.getDisposeResult('esmodule'),
|
|
5565
5790
|
useMemoryRouter: !this.getDisposeResult('disable-memory-router'),
|
|
5566
|
-
baseroute: this.getBaseRouteCompatible(),
|
|
5567
|
-
keepRouteState: this.getDisposeResult('keep-router-state'),
|
|
5568
5791
|
defaultPage: this.getDefaultPageValue(),
|
|
5569
|
-
|
|
5792
|
+
baseroute: this.getBaseRouteCompatible(),
|
|
5570
5793
|
disablePatchRequest: this.getDisposeResult('disable-patch-request'),
|
|
5571
5794
|
fiber: this.getDisposeResult('fiber'),
|
|
5795
|
+
esmodule: this.getDisposeResult('esmodule'),
|
|
5572
5796
|
});
|
|
5573
5797
|
}
|
|
5574
5798
|
/**
|
|
@@ -5582,6 +5806,7 @@ function defineElement(tagName) {
|
|
|
5582
5806
|
app.unmount({
|
|
5583
5807
|
destroy,
|
|
5584
5808
|
clearData: this.getDisposeResult('clear-data'),
|
|
5809
|
+
keepRouteState: this.getDisposeResult('keep-router-state'),
|
|
5585
5810
|
unmountcb,
|
|
5586
5811
|
});
|
|
5587
5812
|
}
|
|
@@ -5729,19 +5954,37 @@ function defineElement(tagName) {
|
|
|
5729
5954
|
* 2: disableScopecss, disableSandbox, disableMemoryRouter must be same with micro-app element, if conflict, the one who executes first shall prevail
|
|
5730
5955
|
* @param apps micro apps
|
|
5731
5956
|
*/
|
|
5732
|
-
function preFetch(apps) {
|
|
5957
|
+
function preFetch(apps, delay) {
|
|
5733
5958
|
if (!isBrowser) {
|
|
5734
5959
|
return logError('preFetch is only supported in browser environment');
|
|
5735
5960
|
}
|
|
5736
5961
|
requestIdleCallback(() => {
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5962
|
+
const delayTime = delay !== null && delay !== void 0 ? delay : microApp.options.prefetchDelay;
|
|
5963
|
+
setTimeout(() => {
|
|
5964
|
+
// releasePrefetchEffect()
|
|
5965
|
+
preFetchInSerial(apps);
|
|
5966
|
+
}, isNumber(delayTime) ? delayTime : 3000);
|
|
5741
5967
|
});
|
|
5968
|
+
// const handleOnLoad = (): void => {
|
|
5969
|
+
// releasePrefetchEffect()
|
|
5970
|
+
// requestIdleCallback(() => {
|
|
5971
|
+
// preFetchInSerial(apps)
|
|
5972
|
+
// })
|
|
5973
|
+
// }
|
|
5974
|
+
// const releasePrefetchEffect = (): void => {
|
|
5975
|
+
// window.removeEventListener('load', handleOnLoad)
|
|
5976
|
+
// clearTimeout(preFetchTime)
|
|
5977
|
+
// }
|
|
5978
|
+
// window.addEventListener('load', handleOnLoad)
|
|
5979
|
+
}
|
|
5980
|
+
function preFetchInSerial(apps) {
|
|
5981
|
+
isFunction(apps) && (apps = apps());
|
|
5982
|
+
if (isArray(apps)) {
|
|
5983
|
+
apps.reduce((pre, next) => pre.then(() => preFetchAction(next)), Promise.resolve());
|
|
5984
|
+
}
|
|
5742
5985
|
}
|
|
5743
5986
|
// sequential preload app
|
|
5744
|
-
function
|
|
5987
|
+
function preFetchAction(options) {
|
|
5745
5988
|
return promiseRequestIdle((resolve) => {
|
|
5746
5989
|
var _a, _b, _c, _d, _e, _f;
|
|
5747
5990
|
if (isPlainObject(options) && navigator.onLine) {
|
|
@@ -5751,21 +5994,22 @@ function preFetchInSerial(options) {
|
|
|
5751
5994
|
const app = new CreateApp({
|
|
5752
5995
|
name: options.name,
|
|
5753
5996
|
url: options.url,
|
|
5997
|
+
isPrefetch: true,
|
|
5754
5998
|
scopecss: !((_b = (_a = options['disable-scopecss']) !== null && _a !== void 0 ? _a : options.disableScopecss) !== null && _b !== void 0 ? _b : microApp.options['disable-scopecss']),
|
|
5755
5999
|
useSandbox: !((_d = (_c = options['disable-sandbox']) !== null && _c !== void 0 ? _c : options.disableSandbox) !== null && _d !== void 0 ? _d : microApp.options['disable-sandbox']),
|
|
5756
6000
|
inline: (_e = options.inline) !== null && _e !== void 0 ? _e : microApp.options.inline,
|
|
5757
6001
|
esmodule: (_f = options.esmodule) !== null && _f !== void 0 ? _f : microApp.options.esmodule,
|
|
5758
|
-
|
|
6002
|
+
prefetchLevel: options.level && PREFETCH_LEVEL.includes(options.level) ? options.level : microApp.options.prefetchLevel && PREFETCH_LEVEL.includes(microApp.options.prefetchLevel) ? microApp.options.prefetchLevel : 2,
|
|
5759
6003
|
});
|
|
5760
6004
|
const oldOnload = app.onLoad;
|
|
5761
6005
|
const oldOnLoadError = app.onLoadError;
|
|
5762
6006
|
app.onLoad = (html) => {
|
|
5763
6007
|
resolve();
|
|
5764
|
-
oldOnload.call(app, html);
|
|
6008
|
+
oldOnload.call(app, html, options['default-page'], options['disable-patch-request']);
|
|
5765
6009
|
};
|
|
5766
|
-
app.onLoadError = (
|
|
6010
|
+
app.onLoadError = (...rests) => {
|
|
5767
6011
|
resolve();
|
|
5768
|
-
oldOnLoadError.call(app,
|
|
6012
|
+
oldOnLoadError.call(app, ...rests);
|
|
5769
6013
|
};
|
|
5770
6014
|
}
|
|
5771
6015
|
else {
|
|
@@ -5823,13 +6067,14 @@ function fetchGlobalResources(resources, suffix, sourceHandler) {
|
|
|
5823
6067
|
/**
|
|
5824
6068
|
* if app not prefetch & not unmount, then app is active
|
|
5825
6069
|
* @param excludeHiddenApp exclude hidden keep-alive app, default is false
|
|
6070
|
+
* @param excludePreRender exclude pre render app
|
|
5826
6071
|
* @returns active apps
|
|
5827
6072
|
*/
|
|
5828
|
-
function getActiveApps(excludeHiddenApp = false) {
|
|
6073
|
+
function getActiveApps({ excludeHiddenApp = false, excludePreRender = false, } = {}) {
|
|
5829
6074
|
const activeApps = [];
|
|
5830
6075
|
appInstanceMap.forEach((app, appName) => {
|
|
5831
6076
|
if (appStates.UNMOUNT !== app.getAppState() &&
|
|
5832
|
-
!app.isPrefetch &&
|
|
6077
|
+
(!app.isPrefetch || (app.isPrerender && !excludePreRender)) &&
|
|
5833
6078
|
(!excludeHiddenApp ||
|
|
5834
6079
|
keepAliveStates.KEEP_ALIVE_HIDDEN !== app.getKeepAliveState())) {
|
|
5835
6080
|
activeApps.push(appName);
|
|
@@ -5862,6 +6107,7 @@ function unmountApp(appName, options) {
|
|
|
5862
6107
|
app.unmount({
|
|
5863
6108
|
destroy: true,
|
|
5864
6109
|
clearData: true,
|
|
6110
|
+
keepRouteState: true,
|
|
5865
6111
|
unmountcb: resolve.bind(null, true)
|
|
5866
6112
|
});
|
|
5867
6113
|
}
|
|
@@ -5869,6 +6115,7 @@ function unmountApp(appName, options) {
|
|
|
5869
6115
|
app.unmount({
|
|
5870
6116
|
destroy: false,
|
|
5871
6117
|
clearData: !!options.clearData,
|
|
6118
|
+
keepRouteState: true,
|
|
5872
6119
|
unmountcb: resolve.bind(null, true)
|
|
5873
6120
|
});
|
|
5874
6121
|
}
|