@micro-zoe/micro-app 0.8.4 → 1.0.0-alpha.0
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/README.md +4 -4
- package/README.zh-cn.md +9 -15
- package/lib/index.d.ts +64 -20
- package/lib/index.esm.js +1225 -194
- 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 +2 -2
- package/typings/global.d.ts +146 -4
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '0.
|
|
1
|
+
const version = '1.0.0-alpha.0';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -7,10 +7,24 @@ const globalThis = (typeof global !== 'undefined')
|
|
|
7
7
|
: ((typeof window !== 'undefined')
|
|
8
8
|
? window
|
|
9
9
|
: ((typeof self !== 'undefined') ? self : Function('return this')()));
|
|
10
|
+
const noop = () => { };
|
|
11
|
+
const noopFalse = () => false;
|
|
12
|
+
// Array.isArray
|
|
13
|
+
const isArray = Array.isArray;
|
|
14
|
+
// Object.assign
|
|
15
|
+
const assign = Object.assign;
|
|
16
|
+
// Object prototype methods
|
|
17
|
+
const rawDefineProperty = Object.defineProperty;
|
|
18
|
+
const rawDefineProperties = Object.defineProperties;
|
|
19
|
+
const rawHasOwnProperty = Object.prototype.hasOwnProperty;
|
|
10
20
|
// is Undefined
|
|
11
21
|
function isUndefined(target) {
|
|
12
22
|
return target === undefined;
|
|
13
23
|
}
|
|
24
|
+
// is Null
|
|
25
|
+
function isNull(target) {
|
|
26
|
+
return target === null;
|
|
27
|
+
}
|
|
14
28
|
// is String
|
|
15
29
|
function isString(target) {
|
|
16
30
|
return typeof target === 'string';
|
|
@@ -23,8 +37,6 @@ function isBoolean(target) {
|
|
|
23
37
|
function isFunction(target) {
|
|
24
38
|
return typeof target === 'function';
|
|
25
39
|
}
|
|
26
|
-
// is Array
|
|
27
|
-
const isArray = Array.isArray;
|
|
28
40
|
// is PlainObject
|
|
29
41
|
function isPlainObject(target) {
|
|
30
42
|
return toString.call(target) === '[object Object]';
|
|
@@ -41,9 +53,9 @@ function isBoundFunction(target) {
|
|
|
41
53
|
function isShadowRoot(target) {
|
|
42
54
|
return typeof ShadowRoot !== 'undefined' && target instanceof ShadowRoot;
|
|
43
55
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
function isURL(target) {
|
|
57
|
+
return target instanceof URL;
|
|
58
|
+
}
|
|
47
59
|
/**
|
|
48
60
|
* format error log
|
|
49
61
|
* @param msg message
|
|
@@ -80,6 +92,16 @@ function logWarn(msg, appName = null, ...rest) {
|
|
|
80
92
|
function defer(fn, ...args) {
|
|
81
93
|
Promise.resolve().then(fn.bind(null, ...args));
|
|
82
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* create URL as MicroLocation
|
|
97
|
+
*/
|
|
98
|
+
const createURL = (function () {
|
|
99
|
+
class Location extends URL {
|
|
100
|
+
}
|
|
101
|
+
return (path, base) => {
|
|
102
|
+
return (base ? new Location('' + path, base) : new Location('' + path));
|
|
103
|
+
};
|
|
104
|
+
})();
|
|
83
105
|
/**
|
|
84
106
|
* Add address protocol
|
|
85
107
|
* @param url address
|
|
@@ -97,7 +119,7 @@ function formatAppURL(url, appName = null) {
|
|
|
97
119
|
if (!isString(url) || !url)
|
|
98
120
|
return '';
|
|
99
121
|
try {
|
|
100
|
-
const { origin, pathname, search } =
|
|
122
|
+
const { origin, pathname, search } = createURL(addProtocol(url));
|
|
101
123
|
// If it ends with .html/.node/.php/.net/.etc, don’t need to add /
|
|
102
124
|
if (/\.(\w+)$/.test(pathname)) {
|
|
103
125
|
return `${origin}${pathname}${search}`;
|
|
@@ -118,6 +140,7 @@ function formatAppURL(url, appName = null) {
|
|
|
118
140
|
* 3. event_center -> EventCenterForBaseApp -> all methods
|
|
119
141
|
* 4. preFetch
|
|
120
142
|
* 5. plugins
|
|
143
|
+
* 6. router api (push, replace)
|
|
121
144
|
*/
|
|
122
145
|
function formatAppName(name) {
|
|
123
146
|
if (!isString(name) || !name)
|
|
@@ -129,7 +152,7 @@ function formatAppName(name) {
|
|
|
129
152
|
* @param url app.url
|
|
130
153
|
*/
|
|
131
154
|
function getEffectivePath(url) {
|
|
132
|
-
const { origin, pathname } =
|
|
155
|
+
const { origin, pathname } = createURL(url);
|
|
133
156
|
if (/\.(\w+)$/.test(pathname)) {
|
|
134
157
|
const fullPath = `${origin}${pathname}`;
|
|
135
158
|
const pathArr = fullPath.split('/');
|
|
@@ -148,7 +171,7 @@ function CompletionPath(path, baseURI) {
|
|
|
148
171
|
/^((((ht|f)tps?)|file):)?\/\//.test(path) ||
|
|
149
172
|
/^(data|blob):/.test(path))
|
|
150
173
|
return path;
|
|
151
|
-
return
|
|
174
|
+
return createURL(path, getEffectivePath(addProtocol(baseURI))).toString();
|
|
152
175
|
}
|
|
153
176
|
/**
|
|
154
177
|
* Get the folder where the link resource is located,
|
|
@@ -306,6 +329,98 @@ function trim(str) {
|
|
|
306
329
|
function isFireFox() {
|
|
307
330
|
return navigator.userAgent.indexOf('Firefox') > -1;
|
|
308
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Transforms a queryString into object.
|
|
334
|
+
* @param search - search string to parse
|
|
335
|
+
* @returns a query object
|
|
336
|
+
*/
|
|
337
|
+
function parseQuery(search) {
|
|
338
|
+
const result = {};
|
|
339
|
+
const queryList = search.split('&');
|
|
340
|
+
// we will not decode the key/value to ensure that the values are consistent when update URL
|
|
341
|
+
for (const queryItem of queryList) {
|
|
342
|
+
const eqPos = queryItem.indexOf('=');
|
|
343
|
+
const key = eqPos < 0 ? queryItem : queryItem.slice(0, eqPos);
|
|
344
|
+
const value = eqPos < 0 ? null : queryItem.slice(eqPos + 1);
|
|
345
|
+
if (key in result) {
|
|
346
|
+
let currentValue = result[key];
|
|
347
|
+
if (!isArray(currentValue)) {
|
|
348
|
+
currentValue = result[key] = [currentValue];
|
|
349
|
+
}
|
|
350
|
+
currentValue.push(value);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
result[key] = value;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return result;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Transforms an object to query string
|
|
360
|
+
* @param queryObject - query object to stringify
|
|
361
|
+
* @returns query string without the leading `?`
|
|
362
|
+
*/
|
|
363
|
+
function stringifyQuery(queryObject) {
|
|
364
|
+
let result = '';
|
|
365
|
+
for (const key in queryObject) {
|
|
366
|
+
const value = queryObject[key];
|
|
367
|
+
if (isNull(value)) {
|
|
368
|
+
result += (result.length ? '&' : '') + key;
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
const valueList = isArray(value) ? value : [value];
|
|
372
|
+
valueList.forEach(value => {
|
|
373
|
+
if (!isUndefined(value)) {
|
|
374
|
+
result += (result.length ? '&' : '') + key;
|
|
375
|
+
if (!isNull(value))
|
|
376
|
+
result += '=' + value;
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return result;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Register or unregister callback/guard with Set
|
|
385
|
+
*/
|
|
386
|
+
function useSetRecord() {
|
|
387
|
+
const handlers = new Set();
|
|
388
|
+
function add(handler) {
|
|
389
|
+
handlers.add(handler);
|
|
390
|
+
return () => {
|
|
391
|
+
if (handlers.has(handler))
|
|
392
|
+
return handlers.delete(handler);
|
|
393
|
+
return false;
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
return {
|
|
397
|
+
add,
|
|
398
|
+
list: () => handlers,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* record data with Map
|
|
403
|
+
*/
|
|
404
|
+
function useMapRecord() {
|
|
405
|
+
const data = new Map();
|
|
406
|
+
function add(key, value) {
|
|
407
|
+
data.set(key, value);
|
|
408
|
+
return () => {
|
|
409
|
+
if (data.has(key))
|
|
410
|
+
return data.delete(key);
|
|
411
|
+
return false;
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
return {
|
|
415
|
+
add,
|
|
416
|
+
get: (key) => data.get(key),
|
|
417
|
+
delete: (key) => {
|
|
418
|
+
if (data.has(key))
|
|
419
|
+
return data.delete(key);
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
}
|
|
309
424
|
|
|
310
425
|
var ObservedAttrName;
|
|
311
426
|
(function (ObservedAttrName) {
|
|
@@ -315,13 +430,13 @@ var ObservedAttrName;
|
|
|
315
430
|
// app status
|
|
316
431
|
var appStates;
|
|
317
432
|
(function (appStates) {
|
|
318
|
-
appStates["
|
|
319
|
-
appStates["
|
|
320
|
-
appStates["
|
|
321
|
-
appStates["
|
|
322
|
-
appStates["MOUNTING"] = "
|
|
323
|
-
appStates["MOUNTED"] = "
|
|
324
|
-
appStates["UNMOUNT"] = "
|
|
433
|
+
appStates["CREATED"] = "created";
|
|
434
|
+
appStates["LOADING"] = "loading";
|
|
435
|
+
appStates["LOADED"] = "loaded";
|
|
436
|
+
appStates["LOAD_FAILED"] = "load_failed";
|
|
437
|
+
appStates["MOUNTING"] = "mounting";
|
|
438
|
+
appStates["MOUNTED"] = "mounted";
|
|
439
|
+
appStates["UNMOUNT"] = "unmount";
|
|
325
440
|
})(appStates || (appStates = {}));
|
|
326
441
|
// lifecycles
|
|
327
442
|
var lifeCycles;
|
|
@@ -339,16 +454,16 @@ var lifeCycles;
|
|
|
339
454
|
// keep-alive status
|
|
340
455
|
var keepAliveStates;
|
|
341
456
|
(function (keepAliveStates) {
|
|
342
|
-
keepAliveStates["KEEP_ALIVE_SHOW"] = "
|
|
343
|
-
keepAliveStates["KEEP_ALIVE_HIDDEN"] = "
|
|
457
|
+
keepAliveStates["KEEP_ALIVE_SHOW"] = "keep_alive_show";
|
|
458
|
+
keepAliveStates["KEEP_ALIVE_HIDDEN"] = "keep_alive_hidden";
|
|
344
459
|
})(keepAliveStates || (keepAliveStates = {}));
|
|
345
|
-
const globalKeyToBeCached = 'window,self,globalThis,Array,Object,String,Boolean,Math,Number,Symbol,Date,Promise,Function,Proxy,WeakMap,WeakSet,Set,Map,Reflect,Element,Node,Document,RegExp,Error,TypeError,JSON,isNaN,parseFloat,parseInt,performance,console,decodeURI,encodeURI,decodeURIComponent,encodeURIComponent,location,
|
|
460
|
+
const globalKeyToBeCached = 'window,self,globalThis,Array,Object,String,Boolean,Math,Number,Symbol,Date,Promise,Function,Proxy,WeakMap,WeakSet,Set,Map,Reflect,Element,Node,Document,RegExp,Error,TypeError,JSON,isNaN,parseFloat,parseInt,performance,console,decodeURI,encodeURI,decodeURIComponent,encodeURIComponent,navigator,undefined,location,history,EventSource,fetch,XMLHttpRequest';
|
|
346
461
|
|
|
347
462
|
/**
|
|
348
463
|
* fetch source of html, js, css
|
|
349
464
|
* @param url source path
|
|
350
465
|
* @param appName app name
|
|
351
|
-
* @param config
|
|
466
|
+
* @param config fetch options
|
|
352
467
|
*/
|
|
353
468
|
function fetchSource(url, appName = null, options = {}) {
|
|
354
469
|
if (isFunction(microApp.fetch)) {
|
|
@@ -372,7 +487,7 @@ function parseError(msg, linkPath) {
|
|
|
372
487
|
throw err;
|
|
373
488
|
}
|
|
374
489
|
/**
|
|
375
|
-
* Reference
|
|
490
|
+
* Reference https://github.com/reworkcss/css
|
|
376
491
|
* CSSParser mainly deals with 3 scenes: styleRule, @, and comment
|
|
377
492
|
* And scopecss deals with 2 scenes: selector & url
|
|
378
493
|
* And can also disable scopecss with inline comments
|
|
@@ -974,51 +1089,49 @@ function handleNewNode(parent, child, app) {
|
|
|
974
1089
|
* @param passiveChild second param of insertBefore and replaceChild
|
|
975
1090
|
*/
|
|
976
1091
|
function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild) {
|
|
1092
|
+
const hijackElement = getHijackElement(parent, app);
|
|
977
1093
|
/**
|
|
978
1094
|
* If passiveChild is not the child node, insertBefore replaceChild will have a problem, at this time, it will be degraded to appendChild
|
|
979
1095
|
* E.g: document.head.insertBefore(targetChild, document.head.childNodes[0])
|
|
980
1096
|
*/
|
|
981
|
-
if (
|
|
982
|
-
const microAppHead = app.container.querySelector('micro-app-head');
|
|
1097
|
+
if (hijackElement) {
|
|
983
1098
|
/**
|
|
984
1099
|
* 1. If passiveChild exists, it must be insertBefore or replaceChild
|
|
985
1100
|
* 2. When removeChild, targetChild may not be in microAppHead or head
|
|
986
1101
|
*/
|
|
987
|
-
if (passiveChild && !
|
|
988
|
-
return globalEnv.rawAppendChild.call(
|
|
1102
|
+
if (passiveChild && !hijackElement.contains(passiveChild)) {
|
|
1103
|
+
return globalEnv.rawAppendChild.call(hijackElement, targetChild);
|
|
989
1104
|
}
|
|
990
|
-
else if (rawMethod === globalEnv.rawRemoveChild && !
|
|
1105
|
+
else if (rawMethod === globalEnv.rawRemoveChild && !hijackElement.contains(targetChild)) {
|
|
991
1106
|
if (parent.contains(targetChild)) {
|
|
992
1107
|
return rawMethod.call(parent, targetChild);
|
|
993
1108
|
}
|
|
994
1109
|
return targetChild;
|
|
995
1110
|
}
|
|
996
|
-
|
|
997
|
-
return rawMethod.call(microAppHead, targetChild);
|
|
998
|
-
}
|
|
999
|
-
return rawMethod.call(microAppHead, targetChild, passiveChild);
|
|
1111
|
+
return invokeRawMethod(rawMethod, hijackElement, targetChild, passiveChild);
|
|
1000
1112
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
return rawMethod.call(parent, targetChild);
|
|
1009
|
-
}
|
|
1010
|
-
return targetChild;
|
|
1011
|
-
}
|
|
1012
|
-
else if (rawMethod === globalEnv.rawAppend || rawMethod === globalEnv.rawPrepend) {
|
|
1013
|
-
return rawMethod.call(microAppBody, targetChild);
|
|
1014
|
-
}
|
|
1015
|
-
return rawMethod.call(microAppBody, targetChild, passiveChild);
|
|
1113
|
+
return invokeRawMethod(rawMethod, parent, targetChild, passiveChild);
|
|
1114
|
+
}
|
|
1115
|
+
// head/body map to micro-app-head/micro-app-body
|
|
1116
|
+
function getHijackElement(node, app) {
|
|
1117
|
+
var _a, _b;
|
|
1118
|
+
if (node === document.head) {
|
|
1119
|
+
return (_a = app === null || app === void 0 ? void 0 : app.container) === null || _a === void 0 ? void 0 : _a.querySelector('micro-app-head');
|
|
1016
1120
|
}
|
|
1017
|
-
|
|
1121
|
+
if (node === document.body) {
|
|
1122
|
+
return (_b = app === null || app === void 0 ? void 0 : app.container) === null || _b === void 0 ? void 0 : _b.querySelector('micro-app-body');
|
|
1123
|
+
}
|
|
1124
|
+
return null;
|
|
1125
|
+
}
|
|
1126
|
+
function invokeRawMethod(rawMethod, parent, targetChild, passiveChild) {
|
|
1127
|
+
if (isPendMethod(rawMethod)) {
|
|
1018
1128
|
return rawMethod.call(parent, targetChild);
|
|
1019
1129
|
}
|
|
1020
1130
|
return rawMethod.call(parent, targetChild, passiveChild);
|
|
1021
1131
|
}
|
|
1132
|
+
function isPendMethod(method) {
|
|
1133
|
+
return method === globalEnv.rawAppend || method === globalEnv.rawPrepend;
|
|
1134
|
+
}
|
|
1022
1135
|
// Get the map element
|
|
1023
1136
|
function getMappingNode(node) {
|
|
1024
1137
|
var _a;
|
|
@@ -1106,27 +1219,6 @@ function patchElementPrototypeMethods() {
|
|
|
1106
1219
|
this.__MICRO_APP_NAME__ && (clonedNode.__MICRO_APP_NAME__ = this.__MICRO_APP_NAME__);
|
|
1107
1220
|
return clonedNode;
|
|
1108
1221
|
};
|
|
1109
|
-
// patch getBoundingClientRect
|
|
1110
|
-
// TODO: scenes test
|
|
1111
|
-
// Element.prototype.getBoundingClientRect = function getBoundingClientRect () {
|
|
1112
|
-
// const rawRect: DOMRect = globalEnv.rawGetBoundingClientRect.call(this)
|
|
1113
|
-
// if (this.__MICRO_APP_NAME__) {
|
|
1114
|
-
// const app = appInstanceMap.get(this.__MICRO_APP_NAME__)
|
|
1115
|
-
// if (!app?.container) {
|
|
1116
|
-
// return rawRect
|
|
1117
|
-
// }
|
|
1118
|
-
// const appBody = app.container.querySelector('micro-app-body')
|
|
1119
|
-
// const appBodyRect: DOMRect = globalEnv.rawGetBoundingClientRect.call(appBody)
|
|
1120
|
-
// const computedRect: DOMRect = new DOMRect(
|
|
1121
|
-
// rawRect.x - appBodyRect.x,
|
|
1122
|
-
// rawRect.y - appBodyRect.y,
|
|
1123
|
-
// rawRect.width,
|
|
1124
|
-
// rawRect.height,
|
|
1125
|
-
// )
|
|
1126
|
-
// return computedRect
|
|
1127
|
-
// }
|
|
1128
|
-
// return rawRect
|
|
1129
|
-
// }
|
|
1130
1222
|
}
|
|
1131
1223
|
/**
|
|
1132
1224
|
* Mark the newly created element in the micro application
|
|
@@ -1134,7 +1226,8 @@ function patchElementPrototypeMethods() {
|
|
|
1134
1226
|
*/
|
|
1135
1227
|
function markElement(element) {
|
|
1136
1228
|
const appName = getCurrentAppName();
|
|
1137
|
-
|
|
1229
|
+
if (appName)
|
|
1230
|
+
element.__MICRO_APP_NAME__ = appName;
|
|
1138
1231
|
return element;
|
|
1139
1232
|
}
|
|
1140
1233
|
// methods of document
|
|
@@ -1155,27 +1248,29 @@ function patchDocument() {
|
|
|
1155
1248
|
};
|
|
1156
1249
|
// query element👇
|
|
1157
1250
|
function querySelector(selectors) {
|
|
1158
|
-
var _a, _b, _c;
|
|
1251
|
+
var _a, _b, _c, _d;
|
|
1159
1252
|
const appName = getCurrentAppName();
|
|
1160
1253
|
if (!appName ||
|
|
1254
|
+
!((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.container) ||
|
|
1161
1255
|
!selectors ||
|
|
1162
1256
|
isUniqueElement(selectors) ||
|
|
1163
1257
|
// see https://github.com/micro-zoe/micro-app/issues/56
|
|
1164
1258
|
rawDocument !== this) {
|
|
1165
1259
|
return globalEnv.rawQuerySelector.call(this, selectors);
|
|
1166
1260
|
}
|
|
1167
|
-
return (
|
|
1261
|
+
return (_d = (_c = (_b = appInstanceMap.get(appName)) === null || _b === void 0 ? void 0 : _b.container) === null || _c === void 0 ? void 0 : _c.querySelector(selectors)) !== null && _d !== void 0 ? _d : null;
|
|
1168
1262
|
}
|
|
1169
1263
|
function querySelectorAll(selectors) {
|
|
1170
|
-
var _a, _b, _c;
|
|
1264
|
+
var _a, _b, _c, _d;
|
|
1171
1265
|
const appName = getCurrentAppName();
|
|
1172
1266
|
if (!appName ||
|
|
1267
|
+
!((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.container) ||
|
|
1173
1268
|
!selectors ||
|
|
1174
1269
|
isUniqueElement(selectors) ||
|
|
1175
1270
|
rawDocument !== this) {
|
|
1176
1271
|
return globalEnv.rawQuerySelectorAll.call(this, selectors);
|
|
1177
1272
|
}
|
|
1178
|
-
return (
|
|
1273
|
+
return (_d = (_c = (_b = appInstanceMap.get(appName)) === null || _b === void 0 ? void 0 : _b.container) === null || _c === void 0 ? void 0 : _c.querySelectorAll(selectors)) !== null && _d !== void 0 ? _d : [];
|
|
1179
1274
|
}
|
|
1180
1275
|
Document.prototype.querySelector = querySelector;
|
|
1181
1276
|
Document.prototype.querySelectorAll = querySelectorAll;
|
|
@@ -1243,10 +1338,9 @@ function patchSetAttribute() {
|
|
|
1243
1338
|
if (/^micro-app(-\S+)?/i.test(this.tagName) && key === 'data') {
|
|
1244
1339
|
if (isPlainObject(value)) {
|
|
1245
1340
|
const cloneValue = {};
|
|
1246
|
-
Object.getOwnPropertyNames(value).forEach((
|
|
1247
|
-
if (!(isString(
|
|
1248
|
-
|
|
1249
|
-
cloneValue[propertyKey] = value[propertyKey];
|
|
1341
|
+
Object.getOwnPropertyNames(value).forEach((key) => {
|
|
1342
|
+
if (!(isString(key) && key.indexOf('__') === 0)) {
|
|
1343
|
+
cloneValue[key] = value[key];
|
|
1250
1344
|
}
|
|
1251
1345
|
});
|
|
1252
1346
|
this.data = cloneValue;
|
|
@@ -1293,7 +1387,6 @@ function releasePatches() {
|
|
|
1293
1387
|
Element.prototype.append = globalEnv.rawAppend;
|
|
1294
1388
|
Element.prototype.prepend = globalEnv.rawPrepend;
|
|
1295
1389
|
Element.prototype.cloneNode = globalEnv.rawCloneNode;
|
|
1296
|
-
// Element.prototype.getBoundingClientRect = globalEnv.rawGetBoundingClientRect
|
|
1297
1390
|
}
|
|
1298
1391
|
// Set the style of micro-app-head and micro-app-body
|
|
1299
1392
|
let hasRejectMicroAppStyle = false;
|
|
@@ -1307,27 +1400,6 @@ function rejectMicroAppStyle() {
|
|
|
1307
1400
|
}
|
|
1308
1401
|
}
|
|
1309
1402
|
|
|
1310
|
-
function unmountNestedApp() {
|
|
1311
|
-
releaseUnmountOfNestedApp();
|
|
1312
|
-
appInstanceMap.forEach(app => {
|
|
1313
|
-
// @ts-ignore
|
|
1314
|
-
app.container && getRootContainer(app.container).disconnectedCallback();
|
|
1315
|
-
});
|
|
1316
|
-
!window.__MICRO_APP_UMD_MODE__ && appInstanceMap.clear();
|
|
1317
|
-
}
|
|
1318
|
-
// if micro-app run in micro application, delete all next generation application when unmount event received
|
|
1319
|
-
function listenUmountOfNestedApp() {
|
|
1320
|
-
if (window.__MICRO_APP_ENVIRONMENT__) {
|
|
1321
|
-
window.addEventListener('unmount', unmountNestedApp, false);
|
|
1322
|
-
}
|
|
1323
|
-
}
|
|
1324
|
-
// release listener
|
|
1325
|
-
function releaseUnmountOfNestedApp() {
|
|
1326
|
-
if (window.__MICRO_APP_ENVIRONMENT__) {
|
|
1327
|
-
window.removeEventListener('unmount', unmountNestedApp, false);
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
1403
|
const globalEnv = {};
|
|
1332
1404
|
/**
|
|
1333
1405
|
* Note loop nesting
|
|
@@ -1347,7 +1419,6 @@ function initGlobalEnv() {
|
|
|
1347
1419
|
const rawAppend = Element.prototype.append;
|
|
1348
1420
|
const rawPrepend = Element.prototype.prepend;
|
|
1349
1421
|
const rawCloneNode = Element.prototype.cloneNode;
|
|
1350
|
-
// const rawGetBoundingClientRect = Element.prototype.getBoundingClientRect
|
|
1351
1422
|
const rawCreateElement = Document.prototype.createElement;
|
|
1352
1423
|
const rawCreateElementNS = Document.prototype.createElementNS;
|
|
1353
1424
|
const rawCreateDocumentFragment = Document.prototype.createDocumentFragment;
|
|
@@ -1381,7 +1452,7 @@ function initGlobalEnv() {
|
|
|
1381
1452
|
const rawDocumentRemoveEventListener = rawDocument.removeEventListener;
|
|
1382
1453
|
// mark current application as base application
|
|
1383
1454
|
window.__MICRO_APP_BASE_APPLICATION__ = true;
|
|
1384
|
-
|
|
1455
|
+
assign(globalEnv, {
|
|
1385
1456
|
// source/patch
|
|
1386
1457
|
rawSetAttribute,
|
|
1387
1458
|
rawAppendChild,
|
|
@@ -1391,7 +1462,6 @@ function initGlobalEnv() {
|
|
|
1391
1462
|
rawAppend,
|
|
1392
1463
|
rawPrepend,
|
|
1393
1464
|
rawCloneNode,
|
|
1394
|
-
// rawGetBoundingClientRect,
|
|
1395
1465
|
rawCreateElement,
|
|
1396
1466
|
rawCreateElementNS,
|
|
1397
1467
|
rawCreateDocumentFragment,
|
|
@@ -1418,8 +1488,6 @@ function initGlobalEnv() {
|
|
|
1418
1488
|
});
|
|
1419
1489
|
// global effect
|
|
1420
1490
|
rejectMicroAppStyle();
|
|
1421
|
-
releaseUnmountOfNestedApp();
|
|
1422
|
-
listenUmountOfNestedApp();
|
|
1423
1491
|
}
|
|
1424
1492
|
}
|
|
1425
1493
|
|
|
@@ -1605,7 +1673,7 @@ function execScripts(scriptList, app, initHook) {
|
|
|
1605
1673
|
function runScript(url, app, info, isDynamic, callback) {
|
|
1606
1674
|
var _a;
|
|
1607
1675
|
try {
|
|
1608
|
-
const code = bindScope(url, app, info.code, info
|
|
1676
|
+
const code = bindScope(url, app, info.code, info);
|
|
1609
1677
|
if (app.inline || info.module) {
|
|
1610
1678
|
const scriptElement = pureCreateElement('script');
|
|
1611
1679
|
runCode2InlineScript(url, code, info.module, scriptElement, callback);
|
|
@@ -1658,7 +1726,7 @@ function runDynamicRemoteScript(url, info, app, originScript) {
|
|
|
1658
1726
|
app.source.scripts.set(url, info);
|
|
1659
1727
|
info.isGlobal && globalScripts.set(url, code);
|
|
1660
1728
|
try {
|
|
1661
|
-
code = bindScope(url, app, code, info
|
|
1729
|
+
code = bindScope(url, app, code, info);
|
|
1662
1730
|
if (app.inline || info.module) {
|
|
1663
1731
|
runCode2InlineScript(url, code, info.module, replaceElement, dispatchScriptOnLoadEvent);
|
|
1664
1732
|
}
|
|
@@ -1714,13 +1782,13 @@ function runCode2Function(code, info) {
|
|
|
1714
1782
|
* @param url script address
|
|
1715
1783
|
* @param app app
|
|
1716
1784
|
* @param code code
|
|
1717
|
-
* @param
|
|
1785
|
+
* @param info source script info
|
|
1718
1786
|
*/
|
|
1719
|
-
function bindScope(url, app, code,
|
|
1787
|
+
function bindScope(url, app, code, info) {
|
|
1720
1788
|
if (isPlainObject(microApp.plugins)) {
|
|
1721
|
-
code = usePlugins(url, code, app.name, microApp.plugins);
|
|
1789
|
+
code = usePlugins(url, code, app.name, microApp.plugins, info);
|
|
1722
1790
|
}
|
|
1723
|
-
if (app.sandBox && !module) {
|
|
1791
|
+
if (app.sandBox && !info.module) {
|
|
1724
1792
|
globalEnv.rawWindow.__MICRO_APP_PROXY_WINDOW__ = app.sandBox.proxyWindow;
|
|
1725
1793
|
return `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`;
|
|
1726
1794
|
}
|
|
@@ -1732,19 +1800,20 @@ function bindScope(url, app, code, module) {
|
|
|
1732
1800
|
* @param code code
|
|
1733
1801
|
* @param appName app name
|
|
1734
1802
|
* @param plugins plugin list
|
|
1803
|
+
* @param info source script info
|
|
1735
1804
|
*/
|
|
1736
|
-
function usePlugins(url, code, appName, plugins) {
|
|
1805
|
+
function usePlugins(url, code, appName, plugins, info) {
|
|
1737
1806
|
var _a;
|
|
1738
|
-
const newCode = processCode(plugins.global, code, url);
|
|
1739
|
-
return processCode((_a = plugins.modules) === null || _a === void 0 ? void 0 : _a[appName], newCode, url);
|
|
1807
|
+
const newCode = processCode(plugins.global, code, url, info);
|
|
1808
|
+
return processCode((_a = plugins.modules) === null || _a === void 0 ? void 0 : _a[appName], newCode, url, info);
|
|
1740
1809
|
}
|
|
1741
|
-
function processCode(configs, code, url) {
|
|
1810
|
+
function processCode(configs, code, url, info) {
|
|
1742
1811
|
if (!isArray(configs)) {
|
|
1743
1812
|
return code;
|
|
1744
1813
|
}
|
|
1745
1814
|
return configs.reduce((preCode, config) => {
|
|
1746
1815
|
if (isPlainObject(config) && isFunction(config.loader)) {
|
|
1747
|
-
return config.loader(preCode, url, config.options);
|
|
1816
|
+
return config.loader(preCode, url, config.options, info);
|
|
1748
1817
|
}
|
|
1749
1818
|
return preCode;
|
|
1750
1819
|
}, code);
|
|
@@ -2139,6 +2208,28 @@ function rebuildDataCenterSnapshot(microAppEventCenter) {
|
|
|
2139
2208
|
}
|
|
2140
2209
|
}
|
|
2141
2210
|
|
|
2211
|
+
function unmountNestedApp() {
|
|
2212
|
+
appInstanceMap.forEach(app => {
|
|
2213
|
+
// @ts-ignore
|
|
2214
|
+
app.container && getRootContainer(app.container).disconnectedCallback();
|
|
2215
|
+
});
|
|
2216
|
+
!window.__MICRO_APP_UMD_MODE__ && appInstanceMap.clear();
|
|
2217
|
+
}
|
|
2218
|
+
// release listener
|
|
2219
|
+
function releaseUnmountOfNestedApp() {
|
|
2220
|
+
if (window.__MICRO_APP_ENVIRONMENT__) {
|
|
2221
|
+
window.removeEventListener('unmount', unmountNestedApp, false);
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
// if micro-app run in micro application, delete all next generation application when unmount event received
|
|
2225
|
+
// unmount event will auto release by sandbox
|
|
2226
|
+
function listenUmountOfNestedApp() {
|
|
2227
|
+
if (window.__MICRO_APP_ENVIRONMENT__) {
|
|
2228
|
+
releaseUnmountOfNestedApp();
|
|
2229
|
+
window.addEventListener('unmount', unmountNestedApp, false);
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2142
2233
|
/* eslint-disable no-return-assign */
|
|
2143
2234
|
function isBoundedFunction(value) {
|
|
2144
2235
|
if (isBoolean(value.__MICRO_APP_IS_BOUND_FUNCTION__))
|
|
@@ -2178,6 +2269,21 @@ function bindFunctionToRawWindow(rawWindow, value) {
|
|
|
2178
2269
|
return value;
|
|
2179
2270
|
}
|
|
2180
2271
|
|
|
2272
|
+
// this events should be sent to the specified app
|
|
2273
|
+
const formatEventList = ['unmount', 'appstate-change'];
|
|
2274
|
+
/**
|
|
2275
|
+
* Format event name
|
|
2276
|
+
* @param eventName event name
|
|
2277
|
+
* @param appName app name
|
|
2278
|
+
*/
|
|
2279
|
+
function formatEventName$1(eventName, appName) {
|
|
2280
|
+
var _a;
|
|
2281
|
+
if (formatEventList.includes(eventName) ||
|
|
2282
|
+
((eventName === 'popstate' || eventName === 'hashchange') && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.useMemoryRouter))) {
|
|
2283
|
+
return `${eventName}-${appName}`;
|
|
2284
|
+
}
|
|
2285
|
+
return eventName;
|
|
2286
|
+
}
|
|
2181
2287
|
// document.onclick binding list, the binding function of each application is unique
|
|
2182
2288
|
const documentClickListMap = new Map();
|
|
2183
2289
|
let hasRewriteDocumentOnClick = false;
|
|
@@ -2271,19 +2377,6 @@ function releaseEffectDocumentEvent() {
|
|
|
2271
2377
|
document.addEventListener = globalEnv.rawDocumentAddEventListener;
|
|
2272
2378
|
document.removeEventListener = globalEnv.rawDocumentRemoveEventListener;
|
|
2273
2379
|
}
|
|
2274
|
-
// this events should be sent to the specified app
|
|
2275
|
-
const formatEventList = ['unmount', 'appstate-change'];
|
|
2276
|
-
/**
|
|
2277
|
-
* Format event name
|
|
2278
|
-
* @param type event name
|
|
2279
|
-
* @param microAppWindow micro window
|
|
2280
|
-
*/
|
|
2281
|
-
function formatEventType(type, microAppWindow) {
|
|
2282
|
-
if (formatEventList.includes(type)) {
|
|
2283
|
-
return `${type}-${microAppWindow.__MICRO_APP_NAME__}`;
|
|
2284
|
-
}
|
|
2285
|
-
return type;
|
|
2286
|
-
}
|
|
2287
2380
|
/**
|
|
2288
2381
|
* Rewrite side-effect events
|
|
2289
2382
|
* @param microAppWindow micro window
|
|
@@ -2296,7 +2389,7 @@ function effect(microAppWindow) {
|
|
|
2296
2389
|
const { rawWindow, rawDocument, rawWindowAddEventListener, rawWindowRemoveEventListener, rawSetInterval, rawSetTimeout, rawClearInterval, rawClearTimeout, rawDocumentRemoveEventListener, } = globalEnv;
|
|
2297
2390
|
// listener may be null, e.g test-passive
|
|
2298
2391
|
microAppWindow.addEventListener = function (type, listener, options) {
|
|
2299
|
-
type =
|
|
2392
|
+
type = formatEventName$1(type, appName);
|
|
2300
2393
|
const listenerList = eventListenerMap.get(type);
|
|
2301
2394
|
if (listenerList) {
|
|
2302
2395
|
listenerList.add(listener);
|
|
@@ -2308,7 +2401,7 @@ function effect(microAppWindow) {
|
|
|
2308
2401
|
rawWindowAddEventListener.call(rawWindow, type, listener, options);
|
|
2309
2402
|
};
|
|
2310
2403
|
microAppWindow.removeEventListener = function (type, listener, options) {
|
|
2311
|
-
type =
|
|
2404
|
+
type = formatEventName$1(type, appName);
|
|
2312
2405
|
const listenerList = eventListenerMap.get(type);
|
|
2313
2406
|
if ((listenerList === null || listenerList === void 0 ? void 0 : listenerList.size) && listenerList.has(listener)) {
|
|
2314
2407
|
listenerList.delete(listener);
|
|
@@ -2435,8 +2528,790 @@ function effect(microAppWindow) {
|
|
|
2435
2528
|
};
|
|
2436
2529
|
}
|
|
2437
2530
|
|
|
2531
|
+
// set micro app state to origin state
|
|
2532
|
+
function setMicroState(appName, rawState, microState) {
|
|
2533
|
+
const additionalState = {
|
|
2534
|
+
microAppState: assign({}, rawState === null || rawState === void 0 ? void 0 : rawState.microAppState, {
|
|
2535
|
+
[appName]: microState
|
|
2536
|
+
})
|
|
2537
|
+
};
|
|
2538
|
+
// create new state object
|
|
2539
|
+
return assign({}, rawState, additionalState);
|
|
2540
|
+
}
|
|
2541
|
+
// delete micro app state form origin state
|
|
2542
|
+
function removeMicroState(appName, rawState) {
|
|
2543
|
+
if (isPlainObject(rawState === null || rawState === void 0 ? void 0 : rawState.microAppState)) {
|
|
2544
|
+
if (!isUndefined(rawState.microAppState[appName])) {
|
|
2545
|
+
delete rawState.microAppState[appName];
|
|
2546
|
+
}
|
|
2547
|
+
if (!Object.keys(rawState.microAppState).length) {
|
|
2548
|
+
delete rawState.microAppState;
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
// 生成新的state对象
|
|
2552
|
+
return assign({}, rawState);
|
|
2553
|
+
}
|
|
2554
|
+
// get micro app state form origin state
|
|
2555
|
+
function getMicroState(appName, state) {
|
|
2556
|
+
var _a;
|
|
2557
|
+
return ((_a = state === null || state === void 0 ? void 0 : state.microAppState) === null || _a === void 0 ? void 0 : _a[appName]) || null;
|
|
2558
|
+
}
|
|
2559
|
+
const ENC_AD_RE = /&/g; // %M1
|
|
2560
|
+
const ENC_EQ_RE = /=/g; // %M2
|
|
2561
|
+
const DEC_AD_RE = /%M1/g; // &
|
|
2562
|
+
const DEC_EQ_RE = /%M2/g; // =
|
|
2563
|
+
function encodeMicroPath(path) {
|
|
2564
|
+
return encodeURIComponent(commonDecode(path).replace(ENC_AD_RE, '%M1').replace(ENC_EQ_RE, '%M2'));
|
|
2565
|
+
}
|
|
2566
|
+
function decodeMicroPath(path) {
|
|
2567
|
+
return commonDecode(path).replace(DEC_AD_RE, '&').replace(DEC_EQ_RE, '=');
|
|
2568
|
+
}
|
|
2569
|
+
function commonDecode(path) {
|
|
2570
|
+
try {
|
|
2571
|
+
const decPath = decodeURIComponent(path);
|
|
2572
|
+
if (path === decPath || DEC_AD_RE.test(decPath) || DEC_EQ_RE.test(decPath))
|
|
2573
|
+
return decPath;
|
|
2574
|
+
return commonDecode(decPath);
|
|
2575
|
+
}
|
|
2576
|
+
catch (_a) {
|
|
2577
|
+
return path;
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
// 格式化query参数key,防止与原有参数的冲突
|
|
2581
|
+
function formatQueryAppName(appName) {
|
|
2582
|
+
return `app-${appName}`;
|
|
2583
|
+
}
|
|
2584
|
+
// 根据浏览器url参数,获取当前子应用的path
|
|
2585
|
+
function getMicroPathFromURL(appName) {
|
|
2586
|
+
var _a, _b;
|
|
2587
|
+
const rawLocation = globalEnv.rawWindow.location;
|
|
2588
|
+
const queryObject = getQueryObjectFromURL(rawLocation.search, rawLocation.hash);
|
|
2589
|
+
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)]);
|
|
2590
|
+
return isString(microPath) ? decodeMicroPath(microPath) : null;
|
|
2591
|
+
}
|
|
2592
|
+
// 将name=encodeUrl地址插入到浏览器url上
|
|
2593
|
+
function setMicroPathToURL(appName, microLocation) {
|
|
2594
|
+
let { pathname, search, hash } = globalEnv.rawWindow.location;
|
|
2595
|
+
const queryObject = getQueryObjectFromURL(search, hash);
|
|
2596
|
+
const encodedMicroPath = encodeMicroPath(microLocation.pathname +
|
|
2597
|
+
microLocation.search +
|
|
2598
|
+
microLocation.hash);
|
|
2599
|
+
let isAttach2Hash = false; // 基座是否是hash模式,这个其实也不准,只是表示参数加到了hash上
|
|
2600
|
+
// hash存在且search不存在,则认为是hash路由
|
|
2601
|
+
if (hash && !search) {
|
|
2602
|
+
isAttach2Hash = true;
|
|
2603
|
+
if (queryObject.hashQuery) {
|
|
2604
|
+
queryObject.hashQuery[formatQueryAppName(appName)] = encodedMicroPath;
|
|
2605
|
+
}
|
|
2606
|
+
else {
|
|
2607
|
+
queryObject.hashQuery = {
|
|
2608
|
+
[formatQueryAppName(appName)]: encodedMicroPath
|
|
2609
|
+
};
|
|
2610
|
+
}
|
|
2611
|
+
const baseHash = hash.includes('?') ? hash.slice(0, hash.indexOf('?') + 1) : hash + '?';
|
|
2612
|
+
hash = baseHash + stringifyQuery(queryObject.hashQuery);
|
|
2613
|
+
}
|
|
2614
|
+
else {
|
|
2615
|
+
if (queryObject.searchQuery) {
|
|
2616
|
+
queryObject.searchQuery[formatQueryAppName(appName)] = encodedMicroPath;
|
|
2617
|
+
}
|
|
2618
|
+
else {
|
|
2619
|
+
queryObject.searchQuery = {
|
|
2620
|
+
[formatQueryAppName(appName)]: encodedMicroPath
|
|
2621
|
+
};
|
|
2622
|
+
}
|
|
2623
|
+
search = '?' + stringifyQuery(queryObject.searchQuery);
|
|
2624
|
+
}
|
|
2625
|
+
return {
|
|
2626
|
+
fullPath: pathname + search + hash,
|
|
2627
|
+
isAttach2Hash,
|
|
2628
|
+
};
|
|
2629
|
+
}
|
|
2630
|
+
// 将name=encodeUrl的参数从浏览器url上删除
|
|
2631
|
+
function removeMicroPathFromURL(appName, targetLocation) {
|
|
2632
|
+
var _a, _b, _c, _d;
|
|
2633
|
+
let { pathname, search, hash } = targetLocation || globalEnv.rawWindow.location;
|
|
2634
|
+
const queryObject = getQueryObjectFromURL(search, hash);
|
|
2635
|
+
let isAttach2Hash = false;
|
|
2636
|
+
if ((_a = queryObject.hashQuery) === null || _a === void 0 ? void 0 : _a[formatQueryAppName(appName)]) {
|
|
2637
|
+
isAttach2Hash = true;
|
|
2638
|
+
(_b = queryObject.hashQuery) === null || _b === void 0 ? true : delete _b[formatQueryAppName(appName)];
|
|
2639
|
+
const hashQueryStr = stringifyQuery(queryObject.hashQuery);
|
|
2640
|
+
hash = hash.slice(0, hash.indexOf('?') + Number(Boolean(hashQueryStr))) + hashQueryStr;
|
|
2641
|
+
}
|
|
2642
|
+
else if ((_c = queryObject.searchQuery) === null || _c === void 0 ? void 0 : _c[formatQueryAppName(appName)]) {
|
|
2643
|
+
(_d = queryObject.searchQuery) === null || _d === void 0 ? true : delete _d[formatQueryAppName(appName)];
|
|
2644
|
+
const searchQueryStr = stringifyQuery(queryObject.searchQuery);
|
|
2645
|
+
search = searchQueryStr ? '?' + searchQueryStr : '';
|
|
2646
|
+
}
|
|
2647
|
+
return {
|
|
2648
|
+
fullPath: pathname + search + hash,
|
|
2649
|
+
isAttach2Hash,
|
|
2650
|
+
};
|
|
2651
|
+
}
|
|
2652
|
+
/**
|
|
2653
|
+
* 根据location获取query对象
|
|
2654
|
+
*/
|
|
2655
|
+
function getQueryObjectFromURL(search, hash) {
|
|
2656
|
+
const queryObject = {};
|
|
2657
|
+
if (search !== '' && search !== '?') {
|
|
2658
|
+
queryObject.searchQuery = parseQuery(search.slice(1));
|
|
2659
|
+
}
|
|
2660
|
+
if (hash.includes('?')) {
|
|
2661
|
+
queryObject.hashQuery = parseQuery(hash.slice(hash.indexOf('?') + 1));
|
|
2662
|
+
}
|
|
2663
|
+
return queryObject;
|
|
2664
|
+
}
|
|
2665
|
+
/**
|
|
2666
|
+
* get microApp path from browser URL without hash
|
|
2667
|
+
*/
|
|
2668
|
+
function getNoHashMicroPathFromURL(appName, baseUrl) {
|
|
2669
|
+
const microPath = getMicroPathFromURL(appName);
|
|
2670
|
+
if (!microPath)
|
|
2671
|
+
return '';
|
|
2672
|
+
const formatLocation = createURL(microPath, baseUrl);
|
|
2673
|
+
return formatLocation.origin + formatLocation.pathname + formatLocation.search;
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
/**
|
|
2677
|
+
* dispatch PopStateEvent & HashChangeEvent to child app
|
|
2678
|
+
* each child app will listen for popstate event when sandbox start
|
|
2679
|
+
* and release it when sandbox stop
|
|
2680
|
+
* @param appName app name
|
|
2681
|
+
* @returns release callback
|
|
2682
|
+
*/
|
|
2683
|
+
function addHistoryListener(appName) {
|
|
2684
|
+
const rawWindow = globalEnv.rawWindow;
|
|
2685
|
+
// handle popstate event and distribute to child app
|
|
2686
|
+
const popStateHandler = (e) => {
|
|
2687
|
+
// exclude hidden keep-alive app
|
|
2688
|
+
if (getActiveApps(true).includes(appName) && !e.onlyForBrowser) {
|
|
2689
|
+
const microPath = getMicroPathFromURL(appName);
|
|
2690
|
+
const app = appInstanceMap.get(appName);
|
|
2691
|
+
const proxyWindow = app.sandBox.proxyWindow;
|
|
2692
|
+
let isHashChange = false;
|
|
2693
|
+
// for hashChangeEvent
|
|
2694
|
+
const oldHref = proxyWindow.location.href;
|
|
2695
|
+
// Do not attach micro state to url when microPath is empty
|
|
2696
|
+
if (microPath) {
|
|
2697
|
+
const oldHash = proxyWindow.location.hash;
|
|
2698
|
+
updateMicroLocation(appName, microPath, proxyWindow.location);
|
|
2699
|
+
isHashChange = proxyWindow.location.hash !== oldHash;
|
|
2700
|
+
}
|
|
2701
|
+
// dispatch formatted popStateEvent to child
|
|
2702
|
+
dispatchPopStateEventToMicroApp(appName, proxyWindow, rawWindow.history.state);
|
|
2703
|
+
// dispatch formatted hashChangeEvent to child when hash change
|
|
2704
|
+
if (isHashChange)
|
|
2705
|
+
dispatchHashChangeEventToMicroApp(appName, proxyWindow, oldHref);
|
|
2706
|
+
// clear element scope before trigger event of next app
|
|
2707
|
+
removeDomScope();
|
|
2708
|
+
}
|
|
2709
|
+
};
|
|
2710
|
+
rawWindow.addEventListener('popstate', popStateHandler);
|
|
2711
|
+
return () => {
|
|
2712
|
+
rawWindow.removeEventListener('popstate', popStateHandler);
|
|
2713
|
+
};
|
|
2714
|
+
}
|
|
2715
|
+
/**
|
|
2716
|
+
* dispatch formatted popstate event to microApp
|
|
2717
|
+
* @param appName app name
|
|
2718
|
+
* @param proxyWindow sandbox window
|
|
2719
|
+
* @param eventState history.state
|
|
2720
|
+
*/
|
|
2721
|
+
function dispatchPopStateEventToMicroApp(appName, proxyWindow, eventState) {
|
|
2722
|
+
// create PopStateEvent named popstate-appName with sub app state
|
|
2723
|
+
const newPopStateEvent = new PopStateEvent(formatEventName$1('popstate', appName), { state: getMicroState(appName, eventState) });
|
|
2724
|
+
globalEnv.rawWindow.dispatchEvent(newPopStateEvent);
|
|
2725
|
+
// call function window.onpopstate if it exists
|
|
2726
|
+
typeof proxyWindow.onpopstate === 'function' && proxyWindow.onpopstate(newPopStateEvent);
|
|
2727
|
+
}
|
|
2728
|
+
/**
|
|
2729
|
+
* dispatch formatted hashchange event to microApp
|
|
2730
|
+
* @param appName app name
|
|
2731
|
+
* @param proxyWindow sandbox window
|
|
2732
|
+
* @param oldHref old href
|
|
2733
|
+
*/
|
|
2734
|
+
function dispatchHashChangeEventToMicroApp(appName, proxyWindow, oldHref) {
|
|
2735
|
+
const newHashChangeEvent = new HashChangeEvent(formatEventName$1('hashchange', appName), {
|
|
2736
|
+
newURL: proxyWindow.location.href,
|
|
2737
|
+
oldURL: oldHref,
|
|
2738
|
+
});
|
|
2739
|
+
globalEnv.rawWindow.dispatchEvent(newHashChangeEvent);
|
|
2740
|
+
// call function window.onhashchange if it exists
|
|
2741
|
+
typeof proxyWindow.onhashchange === 'function' && proxyWindow.onhashchange(newHashChangeEvent);
|
|
2742
|
+
}
|
|
2743
|
+
/**
|
|
2744
|
+
* dispatch native PopStateEvent, simulate location behavior
|
|
2745
|
+
* @param onlyForBrowser only dispatch PopStateEvent to browser
|
|
2746
|
+
*/
|
|
2747
|
+
function dispatchNativePopStateEvent(onlyForBrowser) {
|
|
2748
|
+
const event = new PopStateEvent('popstate', { state: null });
|
|
2749
|
+
if (onlyForBrowser)
|
|
2750
|
+
event.onlyForBrowser = true;
|
|
2751
|
+
globalEnv.rawWindow.dispatchEvent(event);
|
|
2752
|
+
}
|
|
2753
|
+
/**
|
|
2754
|
+
* dispatch hashchange event to browser
|
|
2755
|
+
* @param oldHref old href of rawWindow.location
|
|
2756
|
+
*/
|
|
2757
|
+
function dispatchNativeHashChangeEvent(oldHref) {
|
|
2758
|
+
const newHashChangeEvent = new HashChangeEvent('hashchange', {
|
|
2759
|
+
newURL: globalEnv.rawWindow.location.href,
|
|
2760
|
+
oldURL: oldHref,
|
|
2761
|
+
});
|
|
2762
|
+
globalEnv.rawWindow.dispatchEvent(newHashChangeEvent);
|
|
2763
|
+
}
|
|
2764
|
+
/**
|
|
2765
|
+
* dispatch popstate & hashchange event to browser
|
|
2766
|
+
* @param onlyForBrowser only dispatch event to browser
|
|
2767
|
+
* @param oldHref old href of rawWindow.location
|
|
2768
|
+
*/
|
|
2769
|
+
function dispatchNativeEvent(onlyForBrowser, oldHref) {
|
|
2770
|
+
// clear element scope before dispatch global event
|
|
2771
|
+
removeDomScope();
|
|
2772
|
+
dispatchNativePopStateEvent(onlyForBrowser);
|
|
2773
|
+
if (oldHref) {
|
|
2774
|
+
dispatchNativeHashChangeEvent(oldHref);
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
/**
|
|
2779
|
+
* create proxyHistory for microApp
|
|
2780
|
+
* MDN https://developer.mozilla.org/en-US/docs/Web/API/History
|
|
2781
|
+
* @param appName app name
|
|
2782
|
+
* @param microLocation microApp location
|
|
2783
|
+
*/
|
|
2784
|
+
function createMicroHistory(appName, microLocation) {
|
|
2785
|
+
const rawHistory = globalEnv.rawWindow.history;
|
|
2786
|
+
function getMicroHistoryMethod(methodName) {
|
|
2787
|
+
return function (...rests) {
|
|
2788
|
+
if ((methodName === 'pushState' || methodName === 'replaceState') &&
|
|
2789
|
+
(isString(rests[2]) || isURL(rests[2]))) {
|
|
2790
|
+
const targetLocation = createURL(rests[2], microLocation.href);
|
|
2791
|
+
if (targetLocation.origin === microLocation.origin) {
|
|
2792
|
+
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rawHistory.state, rests[0]), rests[1]);
|
|
2793
|
+
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
2794
|
+
if (targetFullPath !== microLocation.fullPath) {
|
|
2795
|
+
updateMicroLocation(appName, targetFullPath, microLocation);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
else {
|
|
2799
|
+
rawHistory[methodName].apply(rawHistory, rests);
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
else {
|
|
2803
|
+
rawHistory[methodName].apply(rawHistory, rests);
|
|
2804
|
+
}
|
|
2805
|
+
};
|
|
2806
|
+
}
|
|
2807
|
+
return new Proxy(rawHistory, {
|
|
2808
|
+
get(target, key) {
|
|
2809
|
+
if (key === 'state') {
|
|
2810
|
+
return getMicroState(appName, rawHistory.state);
|
|
2811
|
+
}
|
|
2812
|
+
else if (isFunction(Reflect.get(target, key))) {
|
|
2813
|
+
return getMicroHistoryMethod(key);
|
|
2814
|
+
}
|
|
2815
|
+
return Reflect.get(target, key);
|
|
2816
|
+
},
|
|
2817
|
+
set(target, key, value) {
|
|
2818
|
+
return Reflect.set(target, key, value);
|
|
2819
|
+
}
|
|
2820
|
+
});
|
|
2821
|
+
}
|
|
2822
|
+
/**
|
|
2823
|
+
* navigate to new path base on native method of history
|
|
2824
|
+
* @param methodName pushState/replaceState
|
|
2825
|
+
* @param fullPath full path
|
|
2826
|
+
* @param state history.state, default is null
|
|
2827
|
+
* @param title history.title, default is ''
|
|
2828
|
+
*/
|
|
2829
|
+
function nativeHistoryNavigate(methodName, fullPath, state = null, title = '') {
|
|
2830
|
+
globalEnv.rawWindow.history[methodName](state, title, fullPath);
|
|
2831
|
+
}
|
|
2832
|
+
/**
|
|
2833
|
+
* Navigate to new path, and dispatch native popStateEvent/hashChangeEvent to browser
|
|
2834
|
+
* Use scenes:
|
|
2835
|
+
* 1. mount/unmount through updateBrowserURL with limited popstateEvent
|
|
2836
|
+
* 2. proxyHistory.pushState/replaceState with limited popstateEvent
|
|
2837
|
+
* 3. api microApp.router.push/replace
|
|
2838
|
+
* 4. proxyLocation.hash = xxx
|
|
2839
|
+
* @param methodName pushState/replaceState
|
|
2840
|
+
* @param result result of add/remove microApp path on browser url
|
|
2841
|
+
* @param onlyForBrowser only dispatch event to browser
|
|
2842
|
+
* @param state history.state, not required
|
|
2843
|
+
* @param title history.title, not required
|
|
2844
|
+
*/
|
|
2845
|
+
function navigateWithNativeEvent(methodName, result, onlyForBrowser, state, title) {
|
|
2846
|
+
const rawLocation = globalEnv.rawWindow.location;
|
|
2847
|
+
const oldFullPath = rawLocation.pathname + rawLocation.search + rawLocation.hash;
|
|
2848
|
+
const oldHref = result.isAttach2Hash && oldFullPath !== result.fullPath ? rawLocation.href : null;
|
|
2849
|
+
// navigate with native history method
|
|
2850
|
+
nativeHistoryNavigate(methodName, result.fullPath, state, title);
|
|
2851
|
+
if (oldFullPath !== result.fullPath)
|
|
2852
|
+
dispatchNativeEvent(onlyForBrowser, oldHref);
|
|
2853
|
+
}
|
|
2854
|
+
/**
|
|
2855
|
+
* update browser url when mount/unmount/hidden/show
|
|
2856
|
+
* @param result result of add/remove microApp path on browser url
|
|
2857
|
+
* @param state history.state
|
|
2858
|
+
*/
|
|
2859
|
+
function updateBrowserURL(result, state) {
|
|
2860
|
+
navigateWithNativeEvent('replaceState', result, true, state);
|
|
2861
|
+
}
|
|
2862
|
+
/**
|
|
2863
|
+
* When path is same, keep the microAppState in history.state
|
|
2864
|
+
* Fix bug of missing microAppState in next.js & angular
|
|
2865
|
+
* @param method history.pushState/replaceState
|
|
2866
|
+
*/
|
|
2867
|
+
function patchHistoryState(method) {
|
|
2868
|
+
const rawWindow = globalEnv.rawWindow;
|
|
2869
|
+
return function (...rests) {
|
|
2870
|
+
var _a;
|
|
2871
|
+
if (((_a = rawWindow.history.state) === null || _a === void 0 ? void 0 : _a.microAppState) &&
|
|
2872
|
+
(!isPlainObject(rests[0]) || !rests[0].microAppState) &&
|
|
2873
|
+
(isString(rests[2]) || isURL(rests[2]))) {
|
|
2874
|
+
const currentHref = rawWindow.location.href;
|
|
2875
|
+
const targetLocation = createURL(rests[2], currentHref);
|
|
2876
|
+
if (targetLocation.href === currentHref) {
|
|
2877
|
+
rests[0] = assign({}, rests[0], {
|
|
2878
|
+
microAppState: rawWindow.history.state.microAppState,
|
|
2879
|
+
});
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
method.apply(rawWindow.history, rests);
|
|
2883
|
+
};
|
|
2884
|
+
}
|
|
2885
|
+
let isReWriteHistoryState = false;
|
|
2886
|
+
/**
|
|
2887
|
+
* rewrite history.pushState/replaceState
|
|
2888
|
+
* used to fix the problem that the microAppState maybe missing when mainApp navigate to same path
|
|
2889
|
+
* e.g: when nextjs, angular receive popstate event, they will use history.replaceState to update browser url with a new state object
|
|
2890
|
+
*/
|
|
2891
|
+
function rewriteHistoryState() {
|
|
2892
|
+
// filter nest app
|
|
2893
|
+
if (!isReWriteHistoryState && !window.__MICRO_APP_ENVIRONMENT__) {
|
|
2894
|
+
isReWriteHistoryState = true;
|
|
2895
|
+
const rawWindow = globalEnv.rawWindow;
|
|
2896
|
+
rawWindow.history.pushState = patchHistoryState(rawWindow.history.pushState);
|
|
2897
|
+
rawWindow.history.replaceState = patchHistoryState(rawWindow.history.replaceState);
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
|
|
2901
|
+
function createRouterApi() {
|
|
2902
|
+
/**
|
|
2903
|
+
* common handler for router.push/router.replace method
|
|
2904
|
+
* @param appName app name
|
|
2905
|
+
* @param methodName replaceState/pushState
|
|
2906
|
+
* @param targetLocation target location
|
|
2907
|
+
* @param state to.state
|
|
2908
|
+
*/
|
|
2909
|
+
function navigateWithRawHistory(appName, methodName, targetLocation, state) {
|
|
2910
|
+
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName, globalEnv.rawWindow.history.state, state !== null && state !== void 0 ? state : null));
|
|
2911
|
+
// clear element scope after navigate
|
|
2912
|
+
removeDomScope();
|
|
2913
|
+
}
|
|
2914
|
+
/**
|
|
2915
|
+
* create method of router.push/replace
|
|
2916
|
+
* NOTE:
|
|
2917
|
+
* 1. The same fullPath will be blocked
|
|
2918
|
+
* 2. name & path is required
|
|
2919
|
+
* 3. path is fullPath except for the domain (the domain can be taken, but not valid)
|
|
2920
|
+
* @param replace use router.replace?
|
|
2921
|
+
*/
|
|
2922
|
+
function createNavigationMethod(replace) {
|
|
2923
|
+
return function (to) {
|
|
2924
|
+
const appName = formatAppName(to.name);
|
|
2925
|
+
// console.log(3333333, appInstanceMap.get(appName))
|
|
2926
|
+
if (appName && isString(to.path)) {
|
|
2927
|
+
const app = appInstanceMap.get(appName);
|
|
2928
|
+
if (app && !app.sandBox)
|
|
2929
|
+
return logError(`navigation failed, sandBox of app ${appName} is closed`);
|
|
2930
|
+
// active apps, include hidden keep-alive app
|
|
2931
|
+
if (getActiveApps().includes(appName)) {
|
|
2932
|
+
const microLocation = app.sandBox.proxyWindow.location;
|
|
2933
|
+
const targetLocation = createURL(to.path, microLocation.href);
|
|
2934
|
+
// Only get path data, even if the origin is different from microApp
|
|
2935
|
+
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
2936
|
+
if (microLocation.fullPath !== targetFullPath || getMicroPathFromURL(appName) !== targetFullPath) {
|
|
2937
|
+
const methodName = (replace && to.replace !== false) || to.replace === true ? 'replaceState' : 'pushState';
|
|
2938
|
+
navigateWithRawHistory(appName, methodName, targetLocation, to.state);
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
else {
|
|
2942
|
+
/**
|
|
2943
|
+
* app not exit or unmounted, update browser URL with replaceState
|
|
2944
|
+
* use base app location.origin as baseURL
|
|
2945
|
+
*/
|
|
2946
|
+
const rawLocation = globalEnv.rawWindow.location;
|
|
2947
|
+
const targetLocation = createURL(to.path, rawLocation.origin);
|
|
2948
|
+
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
2949
|
+
if (getMicroPathFromURL(appName) !== targetFullPath) {
|
|
2950
|
+
navigateWithRawHistory(appName, to.replace === false ? 'pushState' : 'replaceState', targetLocation, to.state);
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
else {
|
|
2955
|
+
logError(`navigation failed, name & path are required when use router.${replace ? 'replace' : 'push'}`);
|
|
2956
|
+
}
|
|
2957
|
+
};
|
|
2958
|
+
}
|
|
2959
|
+
// create method of router.go/back/forward
|
|
2960
|
+
function createRawHistoryMethod(methodName) {
|
|
2961
|
+
return function (...rests) {
|
|
2962
|
+
return globalEnv.rawWindow.history[methodName](...rests);
|
|
2963
|
+
};
|
|
2964
|
+
}
|
|
2965
|
+
const beforeGuards = useSetRecord();
|
|
2966
|
+
const afterGuards = useSetRecord();
|
|
2967
|
+
/**
|
|
2968
|
+
* run all of beforeEach/afterEach guards
|
|
2969
|
+
* NOTE:
|
|
2970
|
+
* 1. Modify browser url first, and then run guards,
|
|
2971
|
+
* consistent with the browser forward & back button
|
|
2972
|
+
* 2. Note the element binding
|
|
2973
|
+
* @param appName app name
|
|
2974
|
+
* @param to target location
|
|
2975
|
+
* @param from old location
|
|
2976
|
+
* @param guards guards list
|
|
2977
|
+
*/
|
|
2978
|
+
function runGuards(appName, to, from, guards) {
|
|
2979
|
+
// clear element scope before execute function of parent
|
|
2980
|
+
removeDomScope();
|
|
2981
|
+
for (const guard of guards) {
|
|
2982
|
+
if (isFunction(guard)) {
|
|
2983
|
+
guard(appName, to, from);
|
|
2984
|
+
}
|
|
2985
|
+
else if (isPlainObject(guard) && isFunction(guard[appName])) {
|
|
2986
|
+
guard[appName](to, from);
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
/**
|
|
2991
|
+
* global hook for router
|
|
2992
|
+
* update router information base on microLocation
|
|
2993
|
+
* @param appName app name
|
|
2994
|
+
* @param microLocation location of microApp
|
|
2995
|
+
*/
|
|
2996
|
+
function executeNavigationGuard(appName, to, from) {
|
|
2997
|
+
router.current.set(appName, to);
|
|
2998
|
+
runGuards(appName, to, from, beforeGuards.list());
|
|
2999
|
+
requestIdleCallback(() => {
|
|
3000
|
+
runGuards(appName, to, from, afterGuards.list());
|
|
3001
|
+
});
|
|
3002
|
+
}
|
|
3003
|
+
function clearRouterWhenUnmount(appName) {
|
|
3004
|
+
router.current.delete(appName);
|
|
3005
|
+
}
|
|
3006
|
+
// defaultPage data
|
|
3007
|
+
const defaultPageRecord = useMapRecord();
|
|
3008
|
+
/**
|
|
3009
|
+
* defaultPage只在子应用初始化时生效,且优先级比浏览器上的子应用路由地址低
|
|
3010
|
+
* @param appName app name
|
|
3011
|
+
* @param path page path
|
|
3012
|
+
*/
|
|
3013
|
+
function setDefaultPage(appName, path) {
|
|
3014
|
+
appName = formatAppName(appName);
|
|
3015
|
+
if (!appName)
|
|
3016
|
+
return noopFalse;
|
|
3017
|
+
return defaultPageRecord.add(appName, path);
|
|
3018
|
+
}
|
|
3019
|
+
function removeDefaultPage(appName) {
|
|
3020
|
+
appName = formatAppName(appName);
|
|
3021
|
+
if (!appName)
|
|
3022
|
+
return false;
|
|
3023
|
+
return defaultPageRecord.delete(appName);
|
|
3024
|
+
}
|
|
3025
|
+
// Router API for developer
|
|
3026
|
+
const router = {
|
|
3027
|
+
current: new Map(),
|
|
3028
|
+
encode: encodeMicroPath,
|
|
3029
|
+
decode: decodeMicroPath,
|
|
3030
|
+
push: createNavigationMethod(false),
|
|
3031
|
+
replace: createNavigationMethod(true),
|
|
3032
|
+
go: createRawHistoryMethod('go'),
|
|
3033
|
+
back: createRawHistoryMethod('back'),
|
|
3034
|
+
forward: createRawHistoryMethod('forward'),
|
|
3035
|
+
beforeEach: beforeGuards.add,
|
|
3036
|
+
afterEach: afterGuards.add,
|
|
3037
|
+
// attachToURL: 将指定的子应用路由信息添加到浏览器地址上
|
|
3038
|
+
// attachAllToURL: 将所有正在运行的子应用路由信息添加到浏览器地址上
|
|
3039
|
+
setDefaultPage,
|
|
3040
|
+
removeDefaultPage,
|
|
3041
|
+
getDefaultPage: defaultPageRecord.get,
|
|
3042
|
+
};
|
|
3043
|
+
return {
|
|
3044
|
+
router,
|
|
3045
|
+
executeNavigationGuard,
|
|
3046
|
+
clearRouterWhenUnmount,
|
|
3047
|
+
};
|
|
3048
|
+
}
|
|
3049
|
+
const { router, executeNavigationGuard, clearRouterWhenUnmount, } = createRouterApi();
|
|
3050
|
+
|
|
3051
|
+
const shadowLocationKeys = ['href', 'pathname', 'search', 'hash'];
|
|
3052
|
+
// origin is readonly, so we ignore when updateMicroLocation
|
|
3053
|
+
const locationKeys = [...shadowLocationKeys, 'host', 'hostname', 'port', 'protocol', 'search'];
|
|
3054
|
+
// origin, fullPath is necessary for guardLocation
|
|
3055
|
+
const guardLocationKeys = [...locationKeys, 'origin', 'fullPath'];
|
|
3056
|
+
/**
|
|
3057
|
+
* create guardLocation by microLocation, used for router guard
|
|
3058
|
+
*/
|
|
3059
|
+
function createGuardLocation(appName, microLocation) {
|
|
3060
|
+
const guardLocation = assign({ name: appName }, microLocation);
|
|
3061
|
+
// The prototype values on the URL needs to be manually transferred
|
|
3062
|
+
for (const key of guardLocationKeys)
|
|
3063
|
+
guardLocation[key] = microLocation[key];
|
|
3064
|
+
return guardLocation;
|
|
3065
|
+
}
|
|
3066
|
+
// for updateBrowserURLWithLocation when initial
|
|
3067
|
+
function autoTriggerNavigationGuard(appName, microLocation) {
|
|
3068
|
+
executeNavigationGuard(appName, createGuardLocation(appName, microLocation), createGuardLocation(appName, microLocation));
|
|
3069
|
+
}
|
|
3070
|
+
/**
|
|
3071
|
+
* The following scenes will trigger location update:
|
|
3072
|
+
* 1. pushState/replaceState
|
|
3073
|
+
* 2. popStateEvent
|
|
3074
|
+
* 3. query on browser url when init sub app
|
|
3075
|
+
* 4. set defaultPage when when init sub app
|
|
3076
|
+
* NOTE:
|
|
3077
|
+
* 1. update browser URL first, and then update microLocation
|
|
3078
|
+
* 2. the same fullPath will not trigger router guards
|
|
3079
|
+
* @param appName app name
|
|
3080
|
+
* @param path target path
|
|
3081
|
+
* @param base base url
|
|
3082
|
+
* @param microLocation micro app location
|
|
3083
|
+
* @param type auto prevent
|
|
3084
|
+
*/
|
|
3085
|
+
function updateMicroLocation(appName, path, microLocation, type) {
|
|
3086
|
+
const newLocation = createURL(path, microLocation.href);
|
|
3087
|
+
// record old values of microLocation to `from`
|
|
3088
|
+
const from = createGuardLocation(appName, microLocation);
|
|
3089
|
+
for (const key of locationKeys) {
|
|
3090
|
+
if (shadowLocationKeys.includes(key)) {
|
|
3091
|
+
// reference of shadowLocation
|
|
3092
|
+
microLocation.shadowLocation[key] = newLocation[key];
|
|
3093
|
+
}
|
|
3094
|
+
else {
|
|
3095
|
+
// @ts-ignore reference of microLocation
|
|
3096
|
+
microLocation[key] = newLocation[key];
|
|
3097
|
+
}
|
|
3098
|
+
}
|
|
3099
|
+
// update latest values of microLocation to `to`
|
|
3100
|
+
const to = createGuardLocation(appName, microLocation);
|
|
3101
|
+
// The hook called only when fullPath changed
|
|
3102
|
+
if (type === 'auto' || (from.fullPath !== to.fullPath && type !== 'prevent')) {
|
|
3103
|
+
executeNavigationGuard(appName, to, from);
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
/**
|
|
3107
|
+
* Create location for microApp, each microApp has only one location object, it is a reference type
|
|
3108
|
+
* MDN https://developer.mozilla.org/en-US/docs/Web/API/Location
|
|
3109
|
+
* @param appName app name
|
|
3110
|
+
* @param url app url
|
|
3111
|
+
*/
|
|
3112
|
+
function createMicroLocation(appName, url) {
|
|
3113
|
+
const rawWindow = globalEnv.rawWindow;
|
|
3114
|
+
const rawLocation = rawWindow.location;
|
|
3115
|
+
// microLocation is the location of child app, it is globally unique
|
|
3116
|
+
const microLocation = createURL(url);
|
|
3117
|
+
// shadowLocation is the current location information (href, pathname, search, hash)
|
|
3118
|
+
const shadowLocation = {
|
|
3119
|
+
href: microLocation.href,
|
|
3120
|
+
pathname: microLocation.pathname,
|
|
3121
|
+
search: microLocation.search,
|
|
3122
|
+
hash: microLocation.hash,
|
|
3123
|
+
};
|
|
3124
|
+
/**
|
|
3125
|
+
* Common handler for href, assign, replace
|
|
3126
|
+
* It is mainly used to deal with special scenes about hash
|
|
3127
|
+
* @param value target path
|
|
3128
|
+
* @param methodName pushState/replaceState
|
|
3129
|
+
* @returns origin value or formatted value
|
|
3130
|
+
*/
|
|
3131
|
+
const commonHandler = (value, methodName) => {
|
|
3132
|
+
const targetLocation = createURL(value, microLocation.href);
|
|
3133
|
+
// Even if the origin is the same, developers still have the possibility of want to jump to a new page
|
|
3134
|
+
if (targetLocation.origin === microLocation.origin) {
|
|
3135
|
+
const setMicroPathResult = setMicroPathToURL(appName, targetLocation);
|
|
3136
|
+
/**
|
|
3137
|
+
* change hash with location.href will not trigger the browser reload
|
|
3138
|
+
* so we use pushState & reload to imitate href behavior
|
|
3139
|
+
* NOTE:
|
|
3140
|
+
* 1. if child app only change hash, it should not trigger browser reload
|
|
3141
|
+
* 2. if address is same and has hash, it should not add route stack
|
|
3142
|
+
*/
|
|
3143
|
+
if (targetLocation.pathname === shadowLocation.pathname &&
|
|
3144
|
+
targetLocation.search === shadowLocation.search) {
|
|
3145
|
+
let oldHref = null;
|
|
3146
|
+
if (targetLocation.hash !== shadowLocation.hash) {
|
|
3147
|
+
if (setMicroPathResult.isAttach2Hash)
|
|
3148
|
+
oldHref = rawLocation.href;
|
|
3149
|
+
nativeHistoryNavigate(methodName, setMicroPathResult.fullPath);
|
|
3150
|
+
}
|
|
3151
|
+
if (targetLocation.hash) {
|
|
3152
|
+
dispatchNativeEvent(false, oldHref);
|
|
3153
|
+
}
|
|
3154
|
+
else {
|
|
3155
|
+
rawLocation.reload();
|
|
3156
|
+
}
|
|
3157
|
+
return void 0;
|
|
3158
|
+
/**
|
|
3159
|
+
* when baseApp is hash router, address change of child can not reload browser
|
|
3160
|
+
* so we imitate behavior of browser (reload)
|
|
3161
|
+
*/
|
|
3162
|
+
}
|
|
3163
|
+
else if (setMicroPathResult.isAttach2Hash) {
|
|
3164
|
+
nativeHistoryNavigate(methodName, setMicroPathResult.fullPath);
|
|
3165
|
+
rawLocation.reload();
|
|
3166
|
+
return void 0;
|
|
3167
|
+
}
|
|
3168
|
+
value = setMicroPathResult.fullPath;
|
|
3169
|
+
}
|
|
3170
|
+
return value;
|
|
3171
|
+
};
|
|
3172
|
+
/**
|
|
3173
|
+
* create location PropertyDescriptor (href, pathname, search, hash)
|
|
3174
|
+
* @param key property name
|
|
3175
|
+
* @param setter setter of location property
|
|
3176
|
+
*/
|
|
3177
|
+
function createPropertyDescriptor(getter, setter) {
|
|
3178
|
+
return {
|
|
3179
|
+
enumerable: true,
|
|
3180
|
+
configurable: true,
|
|
3181
|
+
get: getter,
|
|
3182
|
+
set: setter,
|
|
3183
|
+
};
|
|
3184
|
+
}
|
|
3185
|
+
/**
|
|
3186
|
+
* common handler for location.pathname & location.search
|
|
3187
|
+
* @param targetPath target fullPath
|
|
3188
|
+
* @param key pathname/search
|
|
3189
|
+
*/
|
|
3190
|
+
function handleForPathNameAndSearch(targetPath, key) {
|
|
3191
|
+
const targetLocation = createURL(targetPath, url);
|
|
3192
|
+
// When the browser url has a hash value, the same pathname/search will not refresh browser
|
|
3193
|
+
if (targetLocation[key] === shadowLocation[key] && shadowLocation.hash) {
|
|
3194
|
+
// The href has not changed, not need to dispatch hashchange event
|
|
3195
|
+
dispatchNativeEvent(false);
|
|
3196
|
+
}
|
|
3197
|
+
else {
|
|
3198
|
+
/**
|
|
3199
|
+
* When the value is the same, no new route stack will be added
|
|
3200
|
+
* Special scenes such as:
|
|
3201
|
+
* pathname: /path ==> /path#hash, /path ==> /path?query
|
|
3202
|
+
* search: ?query ==> ?query#hash
|
|
3203
|
+
*/
|
|
3204
|
+
nativeHistoryNavigate(targetLocation[key] === shadowLocation[key] ? 'replaceState' : 'pushState', setMicroPathToURL(appName, targetLocation).fullPath);
|
|
3205
|
+
rawLocation.reload();
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
/**
|
|
3209
|
+
* Special processing for four keys: href, pathname, search and hash
|
|
3210
|
+
* They take values from shadowLocation, and require special operations when assigning values
|
|
3211
|
+
*/
|
|
3212
|
+
rawDefineProperties(microLocation, {
|
|
3213
|
+
href: createPropertyDescriptor(() => shadowLocation.href, (value) => {
|
|
3214
|
+
const targetPath = commonHandler(value, 'pushState');
|
|
3215
|
+
if (targetPath)
|
|
3216
|
+
rawLocation.href = targetPath;
|
|
3217
|
+
}),
|
|
3218
|
+
pathname: createPropertyDescriptor(() => shadowLocation.pathname, (value) => {
|
|
3219
|
+
const targetPath = ('/' + value).replace(/^\/+/, '/') + shadowLocation.search + shadowLocation.hash;
|
|
3220
|
+
handleForPathNameAndSearch(targetPath, 'pathname');
|
|
3221
|
+
}),
|
|
3222
|
+
search: createPropertyDescriptor(() => shadowLocation.search, (value) => {
|
|
3223
|
+
const targetPath = shadowLocation.pathname + ('?' + value).replace(/^\?+/, '?') + shadowLocation.hash;
|
|
3224
|
+
handleForPathNameAndSearch(targetPath, 'search');
|
|
3225
|
+
}),
|
|
3226
|
+
hash: createPropertyDescriptor(() => shadowLocation.hash, (value) => {
|
|
3227
|
+
const targetPath = shadowLocation.pathname + shadowLocation.search + ('#' + value).replace(/^#+/, '#');
|
|
3228
|
+
const targetLocation = createURL(targetPath, url);
|
|
3229
|
+
// The same hash will not trigger popStateEvent
|
|
3230
|
+
if (targetLocation.hash !== shadowLocation.hash) {
|
|
3231
|
+
navigateWithNativeEvent('pushState', setMicroPathToURL(appName, targetLocation), false);
|
|
3232
|
+
}
|
|
3233
|
+
}),
|
|
3234
|
+
fullPath: createPropertyDescriptor(() => shadowLocation.pathname + shadowLocation.search + shadowLocation.hash, noop),
|
|
3235
|
+
});
|
|
3236
|
+
const createLocationMethod = (locationMethodName) => {
|
|
3237
|
+
return function (value) {
|
|
3238
|
+
const targetPath = commonHandler(value, locationMethodName === 'assign' ? 'pushState' : 'replaceState');
|
|
3239
|
+
if (targetPath)
|
|
3240
|
+
rawLocation[locationMethodName](targetPath);
|
|
3241
|
+
};
|
|
3242
|
+
};
|
|
3243
|
+
return assign(microLocation, {
|
|
3244
|
+
assign: createLocationMethod('assign'),
|
|
3245
|
+
replace: createLocationMethod('replace'),
|
|
3246
|
+
reload: (forcedReload) => rawLocation.reload(forcedReload),
|
|
3247
|
+
shadowLocation,
|
|
3248
|
+
});
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
/**
|
|
3252
|
+
* The router system has two operations: read and write
|
|
3253
|
+
* Read through location and write through history & location
|
|
3254
|
+
* @param appName app name
|
|
3255
|
+
* @param url app url
|
|
3256
|
+
* @returns MicroRouter
|
|
3257
|
+
*/
|
|
3258
|
+
function createMicroRouter(appName, url) {
|
|
3259
|
+
rewriteHistoryState();
|
|
3260
|
+
const microLocation = createMicroLocation(appName, url);
|
|
3261
|
+
return {
|
|
3262
|
+
microLocation,
|
|
3263
|
+
microHistory: createMicroHistory(appName, microLocation),
|
|
3264
|
+
};
|
|
3265
|
+
}
|
|
3266
|
+
// 当沙箱执行start, 或者隐藏的keep-alive应用重新渲染时时才根据浏览器url更新location 或者 将参数更新到url上
|
|
3267
|
+
function initRouteStateWithURL(appName, microLocation, defaultPage) {
|
|
3268
|
+
const microPath = getMicroPathFromURL(appName);
|
|
3269
|
+
if (microPath) {
|
|
3270
|
+
updateMicroLocation(appName, microPath, microLocation, 'auto');
|
|
3271
|
+
}
|
|
3272
|
+
else {
|
|
3273
|
+
updateBrowserURLWithLocation(appName, microLocation, defaultPage);
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
/**
|
|
3277
|
+
* initialize browser information according to microLocation
|
|
3278
|
+
* called on sandbox.start or reshow of keep-alive app
|
|
3279
|
+
*/
|
|
3280
|
+
function updateBrowserURLWithLocation(appName, microLocation, defaultPage) {
|
|
3281
|
+
// update microLocation with defaultPage
|
|
3282
|
+
if (defaultPage)
|
|
3283
|
+
updateMicroLocation(appName, defaultPage, microLocation, 'prevent');
|
|
3284
|
+
// attach microApp route info to browser URL
|
|
3285
|
+
updateBrowserURL(setMicroPathToURL(appName, microLocation), setMicroState(appName, globalEnv.rawWindow.history.state, null));
|
|
3286
|
+
// trigger guards after change browser URL
|
|
3287
|
+
autoTriggerNavigationGuard(appName, microLocation);
|
|
3288
|
+
}
|
|
3289
|
+
/**
|
|
3290
|
+
* In any case, microPath & microState will be removed from browser, but location will be initialized only when keep-router-state is false
|
|
3291
|
+
* @param appName app name
|
|
3292
|
+
* @param url app url
|
|
3293
|
+
* @param microLocation location of microApp
|
|
3294
|
+
* @param keepRouteState keep-router-state is only used to control whether to clear the location of microApp
|
|
3295
|
+
*/
|
|
3296
|
+
function clearRouteStateFromURL(appName, url, microLocation, keepRouteState) {
|
|
3297
|
+
if (!keepRouteState) {
|
|
3298
|
+
const { pathname, search, hash } = createURL(url);
|
|
3299
|
+
updateMicroLocation(appName, pathname + search + hash, microLocation, 'prevent');
|
|
3300
|
+
}
|
|
3301
|
+
removeStateAndPathFromBrowser(appName);
|
|
3302
|
+
clearRouterWhenUnmount(appName);
|
|
3303
|
+
}
|
|
3304
|
+
/**
|
|
3305
|
+
* remove microState from history.state and remove microPath from browserURL
|
|
3306
|
+
* called on sandbox.stop or hidden of keep-alive app
|
|
3307
|
+
*/
|
|
3308
|
+
function removeStateAndPathFromBrowser(appName) {
|
|
3309
|
+
updateBrowserURL(removeMicroPathFromURL(appName), removeMicroState(appName, globalEnv.rawWindow.history.state));
|
|
3310
|
+
}
|
|
3311
|
+
|
|
2438
3312
|
// Variables that can escape to rawWindow
|
|
2439
3313
|
const staticEscapeProperties = [
|
|
3314
|
+
'__REACT_ERROR_OVERLAY_GLOBAL_HOOK__',
|
|
2440
3315
|
'System',
|
|
2441
3316
|
'__cjsWrapper',
|
|
2442
3317
|
];
|
|
@@ -2446,7 +3321,7 @@ const escapeSetterKeyList = [
|
|
|
2446
3321
|
];
|
|
2447
3322
|
const globalPropertyList = ['window', 'self', 'globalThis'];
|
|
2448
3323
|
class SandBox {
|
|
2449
|
-
constructor(appName, url) {
|
|
3324
|
+
constructor(appName, url, useMemoryRouter = true) {
|
|
2450
3325
|
/**
|
|
2451
3326
|
* Scoped global Properties(Properties that can only get and set in microAppWindow, will not escape to rawWindow)
|
|
2452
3327
|
* https://github.com/micro-zoe/micro-app/issues/234
|
|
@@ -2466,25 +3341,32 @@ class SandBox {
|
|
|
2466
3341
|
// create proxyWindow with Proxy(microAppWindow)
|
|
2467
3342
|
this.proxyWindow = this.createProxyWindow(appName);
|
|
2468
3343
|
// inject global properties
|
|
2469
|
-
this.initMicroAppWindow(this.microAppWindow, appName, url);
|
|
3344
|
+
this.initMicroAppWindow(this.microAppWindow, appName, url, useMemoryRouter);
|
|
2470
3345
|
// Rewrite global event listener & timeout
|
|
2471
|
-
|
|
3346
|
+
assign(this, effect(this.microAppWindow));
|
|
2472
3347
|
}
|
|
2473
|
-
start(baseRoute) {
|
|
3348
|
+
start(baseRoute, useMemoryRouter = true, defaultPage = '') {
|
|
2474
3349
|
if (!this.active) {
|
|
2475
3350
|
this.active = true;
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
3351
|
+
if (useMemoryRouter) {
|
|
3352
|
+
this.initRouteState(defaultPage);
|
|
3353
|
+
// unique listener of popstate event for sub app
|
|
3354
|
+
this.removeHistoryListener = addHistoryListener(this.proxyWindow.__MICRO_APP_NAME__);
|
|
3355
|
+
}
|
|
3356
|
+
else {
|
|
3357
|
+
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseRoute;
|
|
3358
|
+
}
|
|
2479
3359
|
if (++SandBox.activeCount === 1) {
|
|
2480
3360
|
effectDocumentEvent();
|
|
2481
3361
|
patchElementPrototypeMethods();
|
|
3362
|
+
listenUmountOfNestedApp();
|
|
2482
3363
|
}
|
|
3364
|
+
// BUG FIX: bable-polyfill@6.x
|
|
3365
|
+
globalEnv.rawWindow._babelPolyfill && (globalEnv.rawWindow._babelPolyfill = false);
|
|
2483
3366
|
}
|
|
2484
3367
|
}
|
|
2485
|
-
stop() {
|
|
3368
|
+
stop(keepRouteState = false) {
|
|
2486
3369
|
if (this.active) {
|
|
2487
|
-
this.active = false;
|
|
2488
3370
|
this.releaseEffect();
|
|
2489
3371
|
this.microAppWindow.microApp.clearDataListener();
|
|
2490
3372
|
this.microAppWindow.microApp.clearGlobalDataListener();
|
|
@@ -2496,10 +3378,16 @@ class SandBox {
|
|
|
2496
3378
|
Reflect.deleteProperty(globalEnv.rawWindow, key);
|
|
2497
3379
|
});
|
|
2498
3380
|
this.escapeKeys.clear();
|
|
3381
|
+
if (this.removeHistoryListener) {
|
|
3382
|
+
this.clearRouteState(keepRouteState);
|
|
3383
|
+
// release listener of popstate
|
|
3384
|
+
this.removeHistoryListener();
|
|
3385
|
+
}
|
|
2499
3386
|
if (--SandBox.activeCount === 0) {
|
|
2500
3387
|
releaseEffectDocumentEvent();
|
|
2501
3388
|
releasePatches();
|
|
2502
3389
|
}
|
|
3390
|
+
this.active = false;
|
|
2503
3391
|
}
|
|
2504
3392
|
}
|
|
2505
3393
|
// record umd snapshot before the first execution of umdHookMount
|
|
@@ -2644,20 +3532,25 @@ class SandBox {
|
|
|
2644
3532
|
* @param appName app name
|
|
2645
3533
|
* @param url app url
|
|
2646
3534
|
*/
|
|
2647
|
-
initMicroAppWindow(microAppWindow, appName, url) {
|
|
3535
|
+
initMicroAppWindow(microAppWindow, appName, url, useMemoryRouter) {
|
|
2648
3536
|
microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
|
|
2649
3537
|
microAppWindow.__MICRO_APP_NAME__ = appName;
|
|
3538
|
+
microAppWindow.__MICRO_APP_URL__ = url;
|
|
2650
3539
|
microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
|
|
2651
3540
|
microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
|
|
2652
|
-
microAppWindow.microApp =
|
|
3541
|
+
microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
|
|
2653
3542
|
removeDomScope,
|
|
2654
3543
|
pureCreateElement,
|
|
3544
|
+
router,
|
|
2655
3545
|
});
|
|
2656
3546
|
microAppWindow.rawWindow = globalEnv.rawWindow;
|
|
2657
3547
|
microAppWindow.rawDocument = globalEnv.rawDocument;
|
|
2658
3548
|
microAppWindow.hasOwnProperty = (key) => rawHasOwnProperty.call(microAppWindow, key) || rawHasOwnProperty.call(globalEnv.rawWindow, key);
|
|
2659
3549
|
this.setMappingPropertiesWithRawDescriptor(microAppWindow);
|
|
2660
3550
|
this.setHijackProperties(microAppWindow, appName);
|
|
3551
|
+
// this.patchHijackRequest(microAppWindow, appName, url)
|
|
3552
|
+
if (useMemoryRouter)
|
|
3553
|
+
this.setRouterApi(microAppWindow, appName, url);
|
|
2661
3554
|
}
|
|
2662
3555
|
// properties associated with the native window
|
|
2663
3556
|
setMappingPropertiesWithRawDescriptor(microAppWindow) {
|
|
@@ -2691,14 +3584,16 @@ class SandBox {
|
|
|
2691
3584
|
let modifiedEval, modifiedImage;
|
|
2692
3585
|
rawDefineProperties(microAppWindow, {
|
|
2693
3586
|
document: {
|
|
3587
|
+
configurable: false,
|
|
3588
|
+
enumerable: true,
|
|
2694
3589
|
get() {
|
|
2695
3590
|
throttleDeferForSetAppName(appName);
|
|
2696
3591
|
return globalEnv.rawDocument;
|
|
2697
3592
|
},
|
|
2698
|
-
configurable: false,
|
|
2699
|
-
enumerable: true,
|
|
2700
3593
|
},
|
|
2701
3594
|
eval: {
|
|
3595
|
+
configurable: true,
|
|
3596
|
+
enumerable: false,
|
|
2702
3597
|
get() {
|
|
2703
3598
|
throttleDeferForSetAppName(appName);
|
|
2704
3599
|
return modifiedEval || eval;
|
|
@@ -2706,10 +3601,10 @@ class SandBox {
|
|
|
2706
3601
|
set: (value) => {
|
|
2707
3602
|
modifiedEval = value;
|
|
2708
3603
|
},
|
|
2709
|
-
configurable: true,
|
|
2710
|
-
enumerable: false,
|
|
2711
3604
|
},
|
|
2712
3605
|
Image: {
|
|
3606
|
+
configurable: true,
|
|
3607
|
+
enumerable: false,
|
|
2713
3608
|
get() {
|
|
2714
3609
|
throttleDeferForSetAppName(appName);
|
|
2715
3610
|
return modifiedImage || globalEnv.ImageProxy;
|
|
@@ -2717,11 +3612,101 @@ class SandBox {
|
|
|
2717
3612
|
set: (value) => {
|
|
2718
3613
|
modifiedImage = value;
|
|
2719
3614
|
},
|
|
3615
|
+
},
|
|
3616
|
+
});
|
|
3617
|
+
}
|
|
3618
|
+
// private patchHijackRequest (microAppWindow: microAppWindowType, appName: string, url: string) {
|
|
3619
|
+
// let modifiedImage: unknown
|
|
3620
|
+
// function EventSource (...rests: any[]) {
|
|
3621
|
+
// console.log(appName + ' EventSource', rests)
|
|
3622
|
+
// if (typeof rests[0] === 'string') {
|
|
3623
|
+
// rests[0] = (new URL(rests[0], url)).toString()
|
|
3624
|
+
// }
|
|
3625
|
+
// return new globalEnv.rawWindow.EventSource(...rests)
|
|
3626
|
+
// }
|
|
3627
|
+
// function patchFetch (...rests: any[]) {
|
|
3628
|
+
// console.log(appName + ' fetch', rests)
|
|
3629
|
+
// if (typeof rests[0] === 'string') {
|
|
3630
|
+
// rests[0] = (new URL(rests[0], url)).toString()
|
|
3631
|
+
// }
|
|
3632
|
+
// return globalEnv.rawWindow.fetch(...rests)
|
|
3633
|
+
// }
|
|
3634
|
+
// const rawXMLHttpRequest = globalEnv.rawWindow.XMLHttpRequest
|
|
3635
|
+
// class XMLHttpRequest extends rawXMLHttpRequest {
|
|
3636
|
+
// open (method: string, reqUrl: string) {
|
|
3637
|
+
// console.log(appName + ' XMLHttpRequest', method, reqUrl)
|
|
3638
|
+
// reqUrl = (new URL(reqUrl, url)).toString()
|
|
3639
|
+
// super.open(method, reqUrl)
|
|
3640
|
+
// }
|
|
3641
|
+
// }
|
|
3642
|
+
// rawDefineProperties(microAppWindow, {
|
|
3643
|
+
// EventSource: {
|
|
3644
|
+
// configurable: true,
|
|
3645
|
+
// enumerable: true,
|
|
3646
|
+
// get () {
|
|
3647
|
+
// return EventSource
|
|
3648
|
+
// },
|
|
3649
|
+
// set: (value) => {
|
|
3650
|
+
// modifiedImage = value
|
|
3651
|
+
// },
|
|
3652
|
+
// },
|
|
3653
|
+
// fetch: {
|
|
3654
|
+
// configurable: true,
|
|
3655
|
+
// enumerable: true,
|
|
3656
|
+
// get () {
|
|
3657
|
+
// return patchFetch
|
|
3658
|
+
// },
|
|
3659
|
+
// set: (value) => {
|
|
3660
|
+
// modifiedImage = value
|
|
3661
|
+
// },
|
|
3662
|
+
// },
|
|
3663
|
+
// XMLHttpRequest: {
|
|
3664
|
+
// configurable: true,
|
|
3665
|
+
// enumerable: true,
|
|
3666
|
+
// get () {
|
|
3667
|
+
// return XMLHttpRequest
|
|
3668
|
+
// },
|
|
3669
|
+
// set: (value) => {
|
|
3670
|
+
// modifiedImage = value
|
|
3671
|
+
// },
|
|
3672
|
+
// },
|
|
3673
|
+
// })
|
|
3674
|
+
// }
|
|
3675
|
+
// set location & history for memory router
|
|
3676
|
+
setRouterApi(microAppWindow, appName, url) {
|
|
3677
|
+
const { microLocation, microHistory } = createMicroRouter(appName, url);
|
|
3678
|
+
rawDefineProperties(microAppWindow, {
|
|
3679
|
+
location: {
|
|
3680
|
+
configurable: false,
|
|
3681
|
+
enumerable: true,
|
|
3682
|
+
get() {
|
|
3683
|
+
return microLocation;
|
|
3684
|
+
},
|
|
3685
|
+
set: (value) => {
|
|
3686
|
+
globalEnv.rawWindow.location = value;
|
|
3687
|
+
},
|
|
3688
|
+
},
|
|
3689
|
+
history: {
|
|
2720
3690
|
configurable: true,
|
|
2721
|
-
enumerable:
|
|
3691
|
+
enumerable: true,
|
|
3692
|
+
get() {
|
|
3693
|
+
return microHistory;
|
|
3694
|
+
},
|
|
2722
3695
|
},
|
|
2723
3696
|
});
|
|
2724
3697
|
}
|
|
3698
|
+
initRouteState(defaultPage) {
|
|
3699
|
+
initRouteStateWithURL(this.proxyWindow.__MICRO_APP_NAME__, this.proxyWindow.location, defaultPage);
|
|
3700
|
+
}
|
|
3701
|
+
clearRouteState(keepRouteState) {
|
|
3702
|
+
clearRouteStateFromURL(this.proxyWindow.__MICRO_APP_NAME__, this.proxyWindow.__MICRO_APP_URL__, this.proxyWindow.location, keepRouteState);
|
|
3703
|
+
}
|
|
3704
|
+
setRouteInfoForKeepAliveApp() {
|
|
3705
|
+
updateBrowserURLWithLocation(this.proxyWindow.__MICRO_APP_NAME__, this.proxyWindow.location);
|
|
3706
|
+
}
|
|
3707
|
+
removeRouteInfoForKeepAliveApp() {
|
|
3708
|
+
removeStateAndPathFromBrowser(this.proxyWindow.__MICRO_APP_NAME__);
|
|
3709
|
+
}
|
|
2725
3710
|
}
|
|
2726
3711
|
SandBox.activeCount = 0; // number of active sandbox
|
|
2727
3712
|
|
|
@@ -2755,7 +3740,7 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
|
|
|
2755
3740
|
element = getRootContainer(element);
|
|
2756
3741
|
// clear dom scope before dispatch lifeCycles event to base app, especially mounted & unmount
|
|
2757
3742
|
removeDomScope();
|
|
2758
|
-
const detail =
|
|
3743
|
+
const detail = assign({
|
|
2759
3744
|
name: appName,
|
|
2760
3745
|
container: element,
|
|
2761
3746
|
}, error && {
|
|
@@ -2780,7 +3765,7 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
|
|
|
2780
3765
|
* @param detail event detail
|
|
2781
3766
|
*/
|
|
2782
3767
|
function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
|
|
2783
|
-
const event = new CustomEvent(
|
|
3768
|
+
const event = new CustomEvent(formatEventName$1(eventName, appName), {
|
|
2784
3769
|
detail,
|
|
2785
3770
|
});
|
|
2786
3771
|
window.dispatchEvent(event);
|
|
@@ -2789,8 +3774,8 @@ function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
|
|
|
2789
3774
|
// micro app instances
|
|
2790
3775
|
const appInstanceMap = new Map();
|
|
2791
3776
|
class CreateApp {
|
|
2792
|
-
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, baseroute, }) {
|
|
2793
|
-
this.state = appStates.
|
|
3777
|
+
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, useMemoryRouter, baseroute, keepRouteState, defaultPage, }) {
|
|
3778
|
+
this.state = appStates.CREATED;
|
|
2794
3779
|
this.keepAliveState = null;
|
|
2795
3780
|
this.keepAliveContainer = null;
|
|
2796
3781
|
this.loadSourceLevel = 0;
|
|
@@ -2801,27 +3786,29 @@ class CreateApp {
|
|
|
2801
3786
|
this.isPrefetch = false;
|
|
2802
3787
|
this.prefetchResolve = null;
|
|
2803
3788
|
this.container = null;
|
|
2804
|
-
this.baseroute = '';
|
|
2805
3789
|
this.sandBox = null;
|
|
2806
3790
|
this.container = container !== null && container !== void 0 ? container : null;
|
|
2807
3791
|
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
2808
3792
|
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : '';
|
|
3793
|
+
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : false;
|
|
2809
3794
|
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
2810
3795
|
// optional during init👆
|
|
2811
3796
|
this.name = name;
|
|
2812
3797
|
this.url = url;
|
|
2813
3798
|
this.useSandbox = useSandbox;
|
|
2814
3799
|
this.scopecss = this.useSandbox && scopecss;
|
|
3800
|
+
this.useMemoryRouter = this.useSandbox && useMemoryRouter;
|
|
3801
|
+
this.defaultPage = defaultPage !== null && defaultPage !== void 0 ? defaultPage : '';
|
|
2815
3802
|
this.source = {
|
|
2816
3803
|
links: new Map(),
|
|
2817
3804
|
scripts: new Map(),
|
|
2818
3805
|
};
|
|
2819
3806
|
this.loadSourceCode();
|
|
2820
|
-
this.useSandbox && (this.sandBox = new SandBox(name, url));
|
|
3807
|
+
this.useSandbox && (this.sandBox = new SandBox(name, url, this.useMemoryRouter));
|
|
2821
3808
|
}
|
|
2822
3809
|
// Load resources
|
|
2823
3810
|
loadSourceCode() {
|
|
2824
|
-
this.state = appStates.
|
|
3811
|
+
this.state = appStates.LOADING;
|
|
2825
3812
|
extractHtml(this);
|
|
2826
3813
|
}
|
|
2827
3814
|
/**
|
|
@@ -2836,7 +3823,7 @@ class CreateApp {
|
|
|
2836
3823
|
this.prefetchResolve = null;
|
|
2837
3824
|
}
|
|
2838
3825
|
else if (appStates.UNMOUNT !== this.state) {
|
|
2839
|
-
this.state = appStates.
|
|
3826
|
+
this.state = appStates.LOADED;
|
|
2840
3827
|
this.mount();
|
|
2841
3828
|
}
|
|
2842
3829
|
}
|
|
@@ -2853,7 +3840,7 @@ class CreateApp {
|
|
|
2853
3840
|
}
|
|
2854
3841
|
if (appStates.UNMOUNT !== this.state) {
|
|
2855
3842
|
this.onerror(e);
|
|
2856
|
-
this.state = appStates.
|
|
3843
|
+
this.state = appStates.LOAD_FAILED;
|
|
2857
3844
|
}
|
|
2858
3845
|
}
|
|
2859
3846
|
/**
|
|
@@ -2861,22 +3848,26 @@ class CreateApp {
|
|
|
2861
3848
|
* @param container app container
|
|
2862
3849
|
* @param inline js runs in inline mode
|
|
2863
3850
|
* @param baseroute route prefix, default is ''
|
|
3851
|
+
* @param keepRouteState keep route state when unmount, default is false
|
|
2864
3852
|
*/
|
|
2865
|
-
mount(container, inline, baseroute) {
|
|
3853
|
+
mount(container, inline, baseroute, keepRouteState, defaultPage) {
|
|
2866
3854
|
var _a, _b, _c;
|
|
2867
|
-
if (isBoolean(inline)
|
|
3855
|
+
if (isBoolean(inline))
|
|
2868
3856
|
this.inline = inline;
|
|
2869
|
-
|
|
3857
|
+
// keepRouteState effective on unmount
|
|
3858
|
+
if (isBoolean(keepRouteState))
|
|
3859
|
+
this.keepRouteState = keepRouteState;
|
|
2870
3860
|
this.container = (_a = this.container) !== null && _a !== void 0 ? _a : container;
|
|
2871
3861
|
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : this.baseroute;
|
|
3862
|
+
this.defaultPage = defaultPage !== null && defaultPage !== void 0 ? defaultPage : this.defaultPage;
|
|
2872
3863
|
if (this.loadSourceLevel !== 2) {
|
|
2873
|
-
this.state = appStates.
|
|
3864
|
+
this.state = appStates.LOADING;
|
|
2874
3865
|
return;
|
|
2875
3866
|
}
|
|
2876
3867
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
|
|
2877
3868
|
this.state = appStates.MOUNTING;
|
|
2878
3869
|
cloneContainer(this.source.html, this.container, !this.umdMode);
|
|
2879
|
-
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.start(this.baseroute);
|
|
3870
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.start(this.baseroute, this.useMemoryRouter, this.defaultPage);
|
|
2880
3871
|
let umdHookMountResult; // result of mount function
|
|
2881
3872
|
if (!this.umdMode) {
|
|
2882
3873
|
let hasDispatchMountedEvent = false;
|
|
@@ -2941,11 +3932,12 @@ class CreateApp {
|
|
|
2941
3932
|
}
|
|
2942
3933
|
/**
|
|
2943
3934
|
* unmount app
|
|
3935
|
+
* NOTE: Do not add any params on account of unmountApp
|
|
2944
3936
|
* @param destroy completely destroy, delete cache resources
|
|
2945
3937
|
* @param unmountcb callback of unmount
|
|
2946
3938
|
*/
|
|
2947
3939
|
unmount(destroy, unmountcb) {
|
|
2948
|
-
if (this.state === appStates.
|
|
3940
|
+
if (this.state === appStates.LOAD_FAILED) {
|
|
2949
3941
|
destroy = true;
|
|
2950
3942
|
}
|
|
2951
3943
|
this.state = appStates.UNMOUNT;
|
|
@@ -2999,7 +3991,7 @@ class CreateApp {
|
|
|
2999
3991
|
cloneContainer(this.container, this.source.html, false);
|
|
3000
3992
|
}
|
|
3001
3993
|
// this.container maybe contains micro-app element, stop sandbox should exec after cloneContainer
|
|
3002
|
-
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.stop();
|
|
3994
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.stop(this.keepRouteState && !destroy);
|
|
3003
3995
|
if (!getActiveApps().length) {
|
|
3004
3996
|
releasePatchSetAttribute();
|
|
3005
3997
|
}
|
|
@@ -3018,34 +4010,40 @@ class CreateApp {
|
|
|
3018
4010
|
}
|
|
3019
4011
|
// hidden app when disconnectedCallback called with keep-alive
|
|
3020
4012
|
hiddenKeepAliveApp() {
|
|
4013
|
+
var _a;
|
|
3021
4014
|
const oldContainer = this.container;
|
|
3022
4015
|
cloneContainer(this.container, this.keepAliveContainer ? this.keepAliveContainer : (this.keepAliveContainer = document.createElement('div')), false);
|
|
3023
4016
|
this.container = this.keepAliveContainer;
|
|
3024
4017
|
this.keepAliveState = keepAliveStates.KEEP_ALIVE_HIDDEN;
|
|
3025
4018
|
// event should dispatch before clone node
|
|
3026
|
-
// dispatch
|
|
4019
|
+
// dispatch afterHidden event to micro-app
|
|
3027
4020
|
dispatchCustomEventToMicroApp('appstate-change', this.name, {
|
|
3028
4021
|
appState: 'afterhidden',
|
|
3029
4022
|
});
|
|
3030
|
-
// dispatch
|
|
4023
|
+
// dispatch afterHidden event to base app
|
|
3031
4024
|
dispatchLifecyclesEvent(oldContainer, this.name, lifeCycles.AFTERHIDDEN);
|
|
4025
|
+
// called after lifeCyclesEvent
|
|
4026
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.removeRouteInfoForKeepAliveApp();
|
|
3032
4027
|
}
|
|
3033
4028
|
// show app when connectedCallback called with keep-alive
|
|
3034
4029
|
showKeepAliveApp(container) {
|
|
3035
|
-
|
|
4030
|
+
var _a;
|
|
4031
|
+
// dispatch beforeShow event to micro-app
|
|
3036
4032
|
dispatchCustomEventToMicroApp('appstate-change', this.name, {
|
|
3037
4033
|
appState: 'beforeshow',
|
|
3038
4034
|
});
|
|
3039
|
-
// dispatch
|
|
4035
|
+
// dispatch beforeShow event to base app
|
|
3040
4036
|
dispatchLifecyclesEvent(container, this.name, lifeCycles.BEFORESHOW);
|
|
3041
4037
|
cloneContainer(this.container, container, false);
|
|
3042
4038
|
this.container = container;
|
|
3043
4039
|
this.keepAliveState = keepAliveStates.KEEP_ALIVE_SHOW;
|
|
3044
|
-
//
|
|
4040
|
+
// called before lifeCyclesEvent
|
|
4041
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.setRouteInfoForKeepAliveApp();
|
|
4042
|
+
// dispatch afterShow event to micro-app
|
|
3045
4043
|
dispatchCustomEventToMicroApp('appstate-change', this.name, {
|
|
3046
4044
|
appState: 'aftershow',
|
|
3047
4045
|
});
|
|
3048
|
-
// dispatch
|
|
4046
|
+
// dispatch afterShow event to base app
|
|
3049
4047
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.AFTERSHOW);
|
|
3050
4048
|
}
|
|
3051
4049
|
/**
|
|
@@ -3153,12 +4151,17 @@ function defineElement(tagName) {
|
|
|
3153
4151
|
}
|
|
3154
4152
|
disconnectedCallback() {
|
|
3155
4153
|
this.hasConnected = false;
|
|
3156
|
-
|
|
3157
|
-
if (
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
4154
|
+
const app = appInstanceMap.get(this.appName);
|
|
4155
|
+
if (app &&
|
|
4156
|
+
app.getAppState() !== appStates.UNMOUNT &&
|
|
4157
|
+
app.getKeepAliveState() !== keepAliveStates.KEEP_ALIVE_HIDDEN) {
|
|
4158
|
+
// keep-alive
|
|
4159
|
+
if (this.getKeepAliveModeResult()) {
|
|
4160
|
+
this.handleHiddenKeepAliveApp();
|
|
4161
|
+
}
|
|
4162
|
+
else {
|
|
4163
|
+
this.handleUnmount(this.getDestroyCompatibleResult());
|
|
4164
|
+
}
|
|
3162
4165
|
}
|
|
3163
4166
|
}
|
|
3164
4167
|
attributeChangedCallback(attr, _oldVal, newVal) {
|
|
@@ -3206,12 +4209,7 @@ function defineElement(tagName) {
|
|
|
3206
4209
|
if (this.getDisposeResult('shadowDOM') && !this.shadowRoot && isFunction(this.attachShadow)) {
|
|
3207
4210
|
this.attachShadow({ mode: 'open' });
|
|
3208
4211
|
}
|
|
3209
|
-
|
|
3210
|
-
this.ssrUrl = CompletionPath(globalEnv.rawWindow.location.pathname, this.appUrl);
|
|
3211
|
-
}
|
|
3212
|
-
else if (this.ssrUrl) {
|
|
3213
|
-
this.ssrUrl = '';
|
|
3214
|
-
}
|
|
4212
|
+
this.updateSsrUrl(this.appUrl);
|
|
3215
4213
|
if (appInstanceMap.has(this.appName)) {
|
|
3216
4214
|
const app = appInstanceMap.get(this.appName);
|
|
3217
4215
|
const existAppUrl = app.ssrUrl || app.url;
|
|
@@ -3245,15 +4243,9 @@ function defineElement(tagName) {
|
|
|
3245
4243
|
actionsForAttributeChange(formatAttrName, formatAttrUrl, existApp) {
|
|
3246
4244
|
var _a;
|
|
3247
4245
|
/**
|
|
3248
|
-
* change ssrUrl in ssr mode
|
|
3249
4246
|
* do not add judgment of formatAttrUrl === this.appUrl
|
|
3250
4247
|
*/
|
|
3251
|
-
|
|
3252
|
-
this.ssrUrl = CompletionPath(globalEnv.rawWindow.location.pathname, formatAttrUrl);
|
|
3253
|
-
}
|
|
3254
|
-
else if (this.ssrUrl) {
|
|
3255
|
-
this.ssrUrl = '';
|
|
3256
|
-
}
|
|
4248
|
+
this.updateSsrUrl(formatAttrUrl);
|
|
3257
4249
|
this.appName = formatAttrName;
|
|
3258
4250
|
this.appUrl = formatAttrUrl;
|
|
3259
4251
|
((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this).innerHTML = '';
|
|
@@ -3313,14 +4305,14 @@ function defineElement(tagName) {
|
|
|
3313
4305
|
app.isPrefetch = false;
|
|
3314
4306
|
defer(() => {
|
|
3315
4307
|
var _a;
|
|
3316
|
-
return app.mount((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this, this.getDisposeResult('inline'), this.getBaseRouteCompatible());
|
|
4308
|
+
return app.mount((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this, this.getDisposeResult('inline'), this.getBaseRouteCompatible(), this.getDisposeResult('keep-router-state'), this.getDefaultPageValue());
|
|
3317
4309
|
});
|
|
3318
4310
|
}
|
|
3319
4311
|
// create app instance
|
|
3320
4312
|
handleCreateApp() {
|
|
3321
4313
|
var _a;
|
|
3322
4314
|
/**
|
|
3323
|
-
* actions for
|
|
4315
|
+
* actions for destroy old app
|
|
3324
4316
|
* fix of unmounted umd app with disableSandbox
|
|
3325
4317
|
*/
|
|
3326
4318
|
if (appInstanceMap.has(this.appName)) {
|
|
@@ -3334,7 +4326,10 @@ function defineElement(tagName) {
|
|
|
3334
4326
|
inline: this.getDisposeResult('inline'),
|
|
3335
4327
|
scopecss: !(this.getDisposeResult('disableScopecss') || this.getDisposeResult('shadowDOM')),
|
|
3336
4328
|
useSandbox: !this.getDisposeResult('disableSandbox'),
|
|
4329
|
+
useMemoryRouter: !this.getDisposeResult('disable-memory-router'),
|
|
3337
4330
|
baseroute: this.getBaseRouteCompatible(),
|
|
4331
|
+
keepRouteState: this.getDisposeResult('keep-router-state'),
|
|
4332
|
+
defaultPage: this.getDefaultPageValue(),
|
|
3338
4333
|
});
|
|
3339
4334
|
appInstanceMap.set(this.appName, instance);
|
|
3340
4335
|
}
|
|
@@ -3342,11 +4337,12 @@ function defineElement(tagName) {
|
|
|
3342
4337
|
* unmount app
|
|
3343
4338
|
* @param destroy delete cache resources when unmount
|
|
3344
4339
|
*/
|
|
3345
|
-
handleUnmount(destroy,
|
|
4340
|
+
handleUnmount(destroy, unmountCb) {
|
|
3346
4341
|
const app = appInstanceMap.get(this.appName);
|
|
3347
4342
|
if (app &&
|
|
3348
|
-
app.getAppState() !== appStates.UNMOUNT)
|
|
3349
|
-
app.unmount(destroy,
|
|
4343
|
+
app.getAppState() !== appStates.UNMOUNT) {
|
|
4344
|
+
app.unmount(destroy, unmountCb);
|
|
4345
|
+
}
|
|
3350
4346
|
}
|
|
3351
4347
|
// hidden app when disconnectedCallback called with keep-alive
|
|
3352
4348
|
handleHiddenKeepAliveApp() {
|
|
@@ -3409,6 +4405,37 @@ function defineElement(tagName) {
|
|
|
3409
4405
|
getKeepAliveModeResult() {
|
|
3410
4406
|
return this.getDisposeResult('keep-alive') && !this.getDestroyCompatibleResult();
|
|
3411
4407
|
}
|
|
4408
|
+
/**
|
|
4409
|
+
* change ssrUrl in ssr mode
|
|
4410
|
+
*/
|
|
4411
|
+
updateSsrUrl(baseUrl) {
|
|
4412
|
+
if (this.getDisposeResult('ssr')) {
|
|
4413
|
+
if (this.getDisposeResult('disable-memory-router')) {
|
|
4414
|
+
const rawLocation = globalEnv.rawWindow.location;
|
|
4415
|
+
this.ssrUrl = CompletionPath(rawLocation.pathname + rawLocation.search, baseUrl);
|
|
4416
|
+
}
|
|
4417
|
+
else {
|
|
4418
|
+
// get path from browser URL
|
|
4419
|
+
let targetPath = getNoHashMicroPathFromURL(this.appName, baseUrl);
|
|
4420
|
+
const defaultPagePath = this.getDefaultPageValue();
|
|
4421
|
+
if (!targetPath && defaultPagePath) {
|
|
4422
|
+
const targetLocation = createURL(defaultPagePath, baseUrl);
|
|
4423
|
+
targetPath = targetLocation.origin + targetLocation.pathname + targetLocation.search;
|
|
4424
|
+
}
|
|
4425
|
+
this.ssrUrl = targetPath;
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
else if (this.ssrUrl) {
|
|
4429
|
+
this.ssrUrl = '';
|
|
4430
|
+
}
|
|
4431
|
+
}
|
|
4432
|
+
/**
|
|
4433
|
+
* get config of default page
|
|
4434
|
+
*/
|
|
4435
|
+
getDefaultPageValue() {
|
|
4436
|
+
var _a, _b, _c;
|
|
4437
|
+
return (_c = (_b = (_a = router.getDefaultPage(this.appName)) !== null && _a !== void 0 ? _a : this.getAttribute('default-page')) !== null && _b !== void 0 ? _b : this.getAttribute('defaultPage')) !== null && _c !== void 0 ? _c : '';
|
|
4438
|
+
}
|
|
3412
4439
|
/**
|
|
3413
4440
|
* Data from the base application
|
|
3414
4441
|
*/
|
|
@@ -3443,12 +4470,13 @@ function defineElement(tagName) {
|
|
|
3443
4470
|
* url: string,
|
|
3444
4471
|
* disableScopecss?: boolean,
|
|
3445
4472
|
* disableSandbox?: boolean,
|
|
4473
|
+
* disableMemoryRouter?: boolean,
|
|
3446
4474
|
* },
|
|
3447
4475
|
* ...
|
|
3448
4476
|
* ])
|
|
3449
4477
|
* Note:
|
|
3450
4478
|
* 1: preFetch is asynchronous and is performed only when the browser is idle
|
|
3451
|
-
* 2: disableScopecss, disableSandbox must be same with micro-app element, if conflict, the one who executes first shall prevail
|
|
4479
|
+
* 2: disableScopecss, disableSandbox, disableMemoryRouter must be same with micro-app element, if conflict, the one who executes first shall prevail
|
|
3452
4480
|
* @param apps micro apps
|
|
3453
4481
|
*/
|
|
3454
4482
|
function preFetch(apps) {
|
|
@@ -3466,7 +4494,7 @@ function preFetch(apps) {
|
|
|
3466
4494
|
function preFetchInSerial(prefetchApp) {
|
|
3467
4495
|
return new Promise((resolve) => {
|
|
3468
4496
|
requestIdleCallback(() => {
|
|
3469
|
-
var _a, _b;
|
|
4497
|
+
var _a, _b, _c;
|
|
3470
4498
|
if (isPlainObject(prefetchApp) && navigator.onLine) {
|
|
3471
4499
|
prefetchApp.name = formatAppName(prefetchApp.name);
|
|
3472
4500
|
prefetchApp.url = formatAppURL(prefetchApp.url, prefetchApp.name);
|
|
@@ -3476,6 +4504,7 @@ function preFetchInSerial(prefetchApp) {
|
|
|
3476
4504
|
url: prefetchApp.url,
|
|
3477
4505
|
scopecss: !((_a = prefetchApp.disableScopecss) !== null && _a !== void 0 ? _a : microApp.disableScopecss),
|
|
3478
4506
|
useSandbox: !((_b = prefetchApp.disableSandbox) !== null && _b !== void 0 ? _b : microApp.disableSandbox),
|
|
4507
|
+
useMemoryRouter: !((_c = prefetchApp.disableMemoryRouter) !== null && _c !== void 0 ? _c : microApp.disableMemoryRouter),
|
|
3479
4508
|
});
|
|
3480
4509
|
app.isPrefetch = true;
|
|
3481
4510
|
app.prefetchResolve = resolve;
|
|
@@ -3544,7 +4573,7 @@ function getAllApps() {
|
|
|
3544
4573
|
/**
|
|
3545
4574
|
* unmount app by appName
|
|
3546
4575
|
* @param appName
|
|
3547
|
-
* @param options
|
|
4576
|
+
* @param options unmountAppOptions
|
|
3548
4577
|
* @returns Promise<void>
|
|
3549
4578
|
*/
|
|
3550
4579
|
function unmountApp(appName, options) {
|
|
@@ -3618,6 +4647,7 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
3618
4647
|
super(...arguments);
|
|
3619
4648
|
this.tagName = 'micro-app';
|
|
3620
4649
|
this.preFetch = preFetch;
|
|
4650
|
+
this.router = router;
|
|
3621
4651
|
}
|
|
3622
4652
|
start(options) {
|
|
3623
4653
|
if (!isBrowser || !window.customElements) {
|
|
@@ -3647,6 +4677,7 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
3647
4677
|
this.inline = options.inline;
|
|
3648
4678
|
this.disableScopecss = options.disableScopecss;
|
|
3649
4679
|
this.disableSandbox = options.disableSandbox;
|
|
4680
|
+
this.disableMemoryRouter = options.disableMemoryRouter;
|
|
3650
4681
|
this.ssr = options.ssr;
|
|
3651
4682
|
isFunction(options.fetch) && (this.fetch = options.fetch);
|
|
3652
4683
|
isPlainObject(options.lifeCycles) && (this.lifeCycles = options.lifeCycles);
|