@micro-zoe/micro-app 1.0.0-rc.4 → 1.0.0-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +5 -1
- package/lib/index.esm.js +390 -277
- package/lib/index.esm.js.map +1 -1
- package/lib/index.min.js +1 -1
- package/lib/index.min.js.map +1 -1
- package/lib/index.umd.js +1 -1
- package/lib/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/typings/global.d.ts +8 -8
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-rc.
|
|
1
|
+
const version = '1.0.0-rc.5';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -116,6 +116,14 @@ function isMicroAppBody(target) {
|
|
|
116
116
|
function isProxyDocument(target) {
|
|
117
117
|
return toTypeString(target) === '[object ProxyDocument]';
|
|
118
118
|
}
|
|
119
|
+
function isTargetExtension(path, suffix) {
|
|
120
|
+
try {
|
|
121
|
+
return createURL(path).pathname.split('.').pop() === suffix;
|
|
122
|
+
}
|
|
123
|
+
catch (_a) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
119
127
|
function includes(target, searchElement, fromIndex) {
|
|
120
128
|
if (target == null) {
|
|
121
129
|
throw new TypeError('includes target is null or undefined');
|
|
@@ -200,12 +208,12 @@ function formatAppURL(url, appName = null) {
|
|
|
200
208
|
return '';
|
|
201
209
|
try {
|
|
202
210
|
const { origin, pathname, search } = createURL(addProtocol(url), (window.rawWindow || window).location.href);
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const fullPath = `${origin}${pathname}
|
|
208
|
-
return /^https?:\/\//.test(fullPath) ?
|
|
211
|
+
/**
|
|
212
|
+
* keep the original url unchanged, such as .html .node .php .net .etc, search, except hash
|
|
213
|
+
* BUG FIX: Never using '/' to complete url, refer to https://github.com/micro-zoe/micro-app/issues/1147
|
|
214
|
+
*/
|
|
215
|
+
const fullPath = `${origin}${pathname}${search}`;
|
|
216
|
+
return /^https?:\/\//.test(fullPath) ? fullPath : '';
|
|
209
217
|
}
|
|
210
218
|
catch (e) {
|
|
211
219
|
logError(e, appName);
|
|
@@ -228,7 +236,9 @@ function formatAppName(name) {
|
|
|
228
236
|
return name.replace(/(^\d+)|([^\w\d-_])/gi, '');
|
|
229
237
|
}
|
|
230
238
|
/**
|
|
231
|
-
* Get valid address, such as
|
|
239
|
+
* Get valid address, such as
|
|
240
|
+
* 1. https://domain/xx/xx.html to https://domain/xx/
|
|
241
|
+
* 2. https://domain/xx to https://domain/xx/
|
|
232
242
|
* @param url app.url
|
|
233
243
|
*/
|
|
234
244
|
function getEffectivePath(url) {
|
|
@@ -561,6 +571,17 @@ function getBaseHTMLElement() {
|
|
|
561
571
|
var _a;
|
|
562
572
|
return (((_a = window.rawWindow) === null || _a === void 0 ? void 0 : _a.HTMLElement) || window.HTMLElement);
|
|
563
573
|
}
|
|
574
|
+
/**
|
|
575
|
+
* Format event name
|
|
576
|
+
* In with sandbox, child event and lifeCycles bind to microAppElement, there are two events with same name - mounted unmount, it should be handled specifically to prevent conflicts
|
|
577
|
+
* Issue: https://github.com/micro-zoe/micro-app/issues/1161
|
|
578
|
+
* @param type event name
|
|
579
|
+
* @param appName app name
|
|
580
|
+
*/
|
|
581
|
+
const formatEventList = ['mounted', 'unmount'];
|
|
582
|
+
function formatEventType(type, appName) {
|
|
583
|
+
return formatEventList.includes(type) ? `${type}-${appName}` : type;
|
|
584
|
+
}
|
|
564
585
|
|
|
565
586
|
function formatEventInfo(event, element) {
|
|
566
587
|
Object.defineProperties(event, {
|
|
@@ -604,19 +625,19 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
|
|
|
604
625
|
formatEventInfo(event, element);
|
|
605
626
|
// global hooks
|
|
606
627
|
if (isFunction((_a = microApp.options.lifeCycles) === null || _a === void 0 ? void 0 : _a[lifecycleName])) {
|
|
607
|
-
microApp.options.lifeCycles[lifecycleName](event);
|
|
628
|
+
microApp.options.lifeCycles[lifecycleName](event, appName);
|
|
608
629
|
}
|
|
609
630
|
element.dispatchEvent(event);
|
|
610
631
|
}
|
|
611
632
|
/**
|
|
612
633
|
* Dispatch custom event to micro app
|
|
613
634
|
* @param app app
|
|
614
|
-
* @param eventName event name ['unmount', 'appstate-change']
|
|
635
|
+
* @param eventName event name ['mounted', 'unmount', 'appstate-change', 'statechange']
|
|
615
636
|
* @param detail event detail
|
|
616
637
|
*/
|
|
617
638
|
function dispatchCustomEventToMicroApp(app, eventName, detail = {}) {
|
|
618
639
|
var _a;
|
|
619
|
-
const event = new CustomEvent(eventName, {
|
|
640
|
+
const event = new CustomEvent(formatEventType(eventName, app.name), {
|
|
620
641
|
detail,
|
|
621
642
|
});
|
|
622
643
|
(_a = app.sandBox) === null || _a === void 0 ? void 0 : _a.microAppWindow.dispatchEvent(event);
|
|
@@ -660,7 +681,8 @@ class HTMLLoader {
|
|
|
660
681
|
run(app, successCb) {
|
|
661
682
|
const appName = app.name;
|
|
662
683
|
const htmlUrl = app.ssrUrl || app.url;
|
|
663
|
-
const
|
|
684
|
+
const isJsResource = isTargetExtension(htmlUrl, 'js');
|
|
685
|
+
const htmlPromise = isJsResource
|
|
664
686
|
? Promise.resolve(`<micro-app-head><script src='${htmlUrl}'></script></micro-app-head><micro-app-body></micro-app-body>`)
|
|
665
687
|
: fetchSource(htmlUrl, appName, { cache: 'no-cache' });
|
|
666
688
|
htmlPromise.then((htmlStr) => {
|
|
@@ -824,7 +846,7 @@ class CSSParser {
|
|
|
824
846
|
if (!this.scopecssDisableNextLine &&
|
|
825
847
|
(!this.scopecssDisable || this.scopecssDisableSelectors.length)) {
|
|
826
848
|
cssValue = cssValue.replace(/url\(["']?([^)"']+)["']?\)/gm, (all, $1) => {
|
|
827
|
-
if (/^((data|blob)
|
|
849
|
+
if (/^((data|blob):|#|%23)/.test($1) || /^(https?:)?\/\//.test($1)) {
|
|
828
850
|
return all;
|
|
829
851
|
}
|
|
830
852
|
// ./a/b.png ../a/b.png a/b.png
|
|
@@ -1250,7 +1272,7 @@ function extractLinkFromHtml(link, parent, app, isDynamic = false) {
|
|
|
1250
1272
|
return { address: href, linkInfo };
|
|
1251
1273
|
}
|
|
1252
1274
|
}
|
|
1253
|
-
else if (rel && ['prefetch', 'preload', 'prerender'].includes(rel)) {
|
|
1275
|
+
else if (rel && ['prefetch', 'preload', 'prerender', 'modulepreload'].includes(rel)) {
|
|
1254
1276
|
// preload prefetch prerender ....
|
|
1255
1277
|
if (isDynamic) {
|
|
1256
1278
|
replaceComment = document.createComment(`link element with rel=${rel}${href ? ' & href=' + href : ''} removed by micro-app`);
|
|
@@ -1470,17 +1492,32 @@ var MicroAppConfig;
|
|
|
1470
1492
|
MicroAppConfig["SSR"] = "ssr";
|
|
1471
1493
|
MicroAppConfig["FIBER"] = "fiber";
|
|
1472
1494
|
})(MicroAppConfig || (MicroAppConfig = {}));
|
|
1495
|
+
/**
|
|
1496
|
+
* global key must be static key, they can not rewrite
|
|
1497
|
+
* e.g.
|
|
1498
|
+
* window.Promise = newValue
|
|
1499
|
+
* new Promise ==> still get old value, not newValue, because they are cached by top function
|
|
1500
|
+
* NOTE:
|
|
1501
|
+
* 1. Do not add fetch, XMLHttpRequest, EventSource
|
|
1502
|
+
*/
|
|
1503
|
+
const GLOBAL_CACHED_KEY = 'window,self,globalThis,document,Document,Array,Object,String,Boolean,Math,Number,Symbol,Date,Function,Proxy,WeakMap,WeakSet,Set,Map,Reflect,Element,Node,RegExp,Error,TypeError,JSON,isNaN,parseFloat,parseInt,performance,console,decodeURI,encodeURI,decodeURIComponent,encodeURIComponent,navigator,undefined,location,history';
|
|
1473
1504
|
// prefetch level
|
|
1474
1505
|
const PREFETCH_LEVEL = [1, 2, 3];
|
|
1475
|
-
// memory router constants
|
|
1476
|
-
// default mode, child router info will sync to browser url
|
|
1477
|
-
const DEFAULT_ROUTER_MODE = 'search';
|
|
1478
1506
|
/**
|
|
1479
|
-
*
|
|
1480
|
-
* equal to disable-memory-router
|
|
1507
|
+
* memory router modes
|
|
1481
1508
|
* NOTE:
|
|
1482
1509
|
* 1. The only difference between native and native-scope is location.origin, in native-scope mode location.origin point to child app
|
|
1510
|
+
* 2. native mode equal to disable-memory-router
|
|
1483
1511
|
*/
|
|
1512
|
+
// 临时注释,1.0版本放开,默认模式切换为state
|
|
1513
|
+
// // default mode, sync child app router info to history.state
|
|
1514
|
+
// export const DEFAULT_ROUTER_MODE = 'state'
|
|
1515
|
+
// // sync child app router info to browser url as search
|
|
1516
|
+
// export const ROUTER_MODE_SEARCH = 'search'
|
|
1517
|
+
// 临时放开,1.0版本去除
|
|
1518
|
+
const ROUTER_MODE_STATE = 'state';
|
|
1519
|
+
const DEFAULT_ROUTER_MODE = 'search';
|
|
1520
|
+
// render base on browser url, and location.origin location.href point to base app
|
|
1484
1521
|
const ROUTER_MODE_NATIVE = 'native';
|
|
1485
1522
|
// render base on browser url, but location.origin location.href point to child app
|
|
1486
1523
|
const ROUTER_MODE_NATIVE_SCOPE = 'native-scope';
|
|
@@ -1488,12 +1525,13 @@ const ROUTER_MODE_NATIVE_SCOPE = 'native-scope';
|
|
|
1488
1525
|
const ROUTER_MODE_PURE = 'pure';
|
|
1489
1526
|
const ROUTER_MODE_LIST = [
|
|
1490
1527
|
DEFAULT_ROUTER_MODE,
|
|
1528
|
+
ROUTER_MODE_STATE,
|
|
1491
1529
|
ROUTER_MODE_NATIVE,
|
|
1492
1530
|
ROUTER_MODE_NATIVE_SCOPE,
|
|
1493
1531
|
ROUTER_MODE_PURE,
|
|
1494
1532
|
];
|
|
1495
1533
|
// event bound to child app window
|
|
1496
|
-
const
|
|
1534
|
+
const BASE_SCOPE_WINDOW_EVENT = [
|
|
1497
1535
|
'popstate',
|
|
1498
1536
|
'hashchange',
|
|
1499
1537
|
'load',
|
|
@@ -1504,9 +1542,15 @@ const SCOPE_WINDOW_EVENT = [
|
|
|
1504
1542
|
'statechange',
|
|
1505
1543
|
'mounted',
|
|
1506
1544
|
];
|
|
1545
|
+
// bind event of with sandbox
|
|
1546
|
+
const SCOPE_WINDOW_EVENT_OF_WITH = BASE_SCOPE_WINDOW_EVENT;
|
|
1547
|
+
// bind event of iframe sandbox
|
|
1548
|
+
const SCOPE_WINDOW_EVENT_OF_IFRAME = BASE_SCOPE_WINDOW_EVENT.concat([
|
|
1549
|
+
'unhandledrejection',
|
|
1550
|
+
]);
|
|
1507
1551
|
// on event bound to child app window
|
|
1508
1552
|
// TODO: with和iframe处理方式不同,需修改
|
|
1509
|
-
const
|
|
1553
|
+
const BASE_SCOPE_WINDOW_ON_EVENT = [
|
|
1510
1554
|
'onpopstate',
|
|
1511
1555
|
'onhashchange',
|
|
1512
1556
|
'onload',
|
|
@@ -1514,6 +1558,12 @@ const SCOPE_WINDOW_ON_EVENT = [
|
|
|
1514
1558
|
'onunload',
|
|
1515
1559
|
'onerror'
|
|
1516
1560
|
];
|
|
1561
|
+
// bind on event of with sandbox
|
|
1562
|
+
const SCOPE_WINDOW_ON_EVENT_OF_WITH = BASE_SCOPE_WINDOW_ON_EVENT;
|
|
1563
|
+
// bind on event of iframe sandbox
|
|
1564
|
+
const SCOPE_WINDOW_ON_EVENT_OF_IFRAME = BASE_SCOPE_WINDOW_ON_EVENT.concat([
|
|
1565
|
+
'onunhandledrejection',
|
|
1566
|
+
]);
|
|
1517
1567
|
// event bound to child app document
|
|
1518
1568
|
const SCOPE_DOCUMENT_EVENT = [
|
|
1519
1569
|
'DOMContentLoaded',
|
|
@@ -1530,15 +1580,13 @@ const GLOBAL_KEY_TO_WINDOW = [
|
|
|
1530
1580
|
'globalThis',
|
|
1531
1581
|
];
|
|
1532
1582
|
const RAW_GLOBAL_TARGET = ['rawWindow', 'rawDocument'];
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
*/
|
|
1541
|
-
const GLOBAL_CACHED_KEY = 'window,self,globalThis,document,Document,Array,Object,String,Boolean,Math,Number,Symbol,Date,Function,Proxy,WeakMap,WeakSet,Set,Map,Reflect,Element,Node,RegExp,Error,TypeError,JSON,isNaN,parseFloat,parseInt,performance,console,decodeURI,encodeURI,decodeURIComponent,encodeURIComponent,navigator,undefined,location,history';
|
|
1583
|
+
const HIJACK_LOCATION_KEYS = [
|
|
1584
|
+
'host',
|
|
1585
|
+
'hostname',
|
|
1586
|
+
'port',
|
|
1587
|
+
'protocol',
|
|
1588
|
+
'origin',
|
|
1589
|
+
];
|
|
1542
1590
|
|
|
1543
1591
|
const scriptTypes = ['text/javascript', 'text/ecmascript', 'application/javascript', 'application/ecmascript', 'module', 'systemjs-module', 'systemjs-importmap'];
|
|
1544
1592
|
// whether use type='module' script
|
|
@@ -2989,7 +3037,7 @@ function patchWindowProperty(microAppWindow) {
|
|
|
2989
3037
|
const rawWindow = globalEnv.rawWindow;
|
|
2990
3038
|
Object.getOwnPropertyNames(rawWindow)
|
|
2991
3039
|
.filter((key) => {
|
|
2992
|
-
return /^on/.test(key) && !
|
|
3040
|
+
return /^on/.test(key) && !SCOPE_WINDOW_ON_EVENT_OF_WITH.includes(key);
|
|
2993
3041
|
})
|
|
2994
3042
|
.forEach((eventName) => {
|
|
2995
3043
|
const { enumerable, writable, set } = Object.getOwnPropertyDescriptor(rawWindow, eventName) || {
|
|
@@ -3138,7 +3186,7 @@ function patchWindowEffect(microAppWindow, appName) {
|
|
|
3138
3186
|
*/
|
|
3139
3187
|
function getEventTarget(type) {
|
|
3140
3188
|
var _a;
|
|
3141
|
-
if (
|
|
3189
|
+
if (SCOPE_WINDOW_EVENT_OF_WITH.includes(type) && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.container)) {
|
|
3142
3190
|
return getRootContainer(appInstanceMap.get(appName).container);
|
|
3143
3191
|
}
|
|
3144
3192
|
return rawWindow;
|
|
@@ -3151,6 +3199,7 @@ function patchWindowEffect(microAppWindow, appName) {
|
|
|
3151
3199
|
* window.addEventListener.call(非window, type, listener, options)
|
|
3152
3200
|
*/
|
|
3153
3201
|
microAppWindow.addEventListener = function (type, listener, options) {
|
|
3202
|
+
type = formatEventType(type, appName);
|
|
3154
3203
|
const listenerList = eventListenerMap.get(type);
|
|
3155
3204
|
if (listenerList) {
|
|
3156
3205
|
listenerList.add(listener);
|
|
@@ -3162,6 +3211,7 @@ function patchWindowEffect(microAppWindow, appName) {
|
|
|
3162
3211
|
rawAddEventListener.call(getEventTarget(type), type, listener, options);
|
|
3163
3212
|
};
|
|
3164
3213
|
microAppWindow.removeEventListener = function (type, listener, options) {
|
|
3214
|
+
type = formatEventType(type, appName);
|
|
3165
3215
|
const listenerList = eventListenerMap.get(type);
|
|
3166
3216
|
if ((listenerList === null || listenerList === void 0 ? void 0 : listenerList.size) && listenerList.has(listener)) {
|
|
3167
3217
|
listenerList.delete(listener);
|
|
@@ -3254,42 +3304,39 @@ function patchWindowEffect(microAppWindow, appName) {
|
|
|
3254
3304
|
}
|
|
3255
3305
|
|
|
3256
3306
|
// set micro app state to origin state
|
|
3257
|
-
function setMicroState(appName, microState) {
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3307
|
+
function setMicroState(appName, microState, targetLocation) {
|
|
3308
|
+
// TODO: 验证native模式下修改state nextjs路由是否正常
|
|
3309
|
+
const rawState = globalEnv.rawWindow.history.state;
|
|
3310
|
+
const additionalState = {
|
|
3311
|
+
__MICRO_APP_STATE__: assign({}, rawState === null || rawState === void 0 ? void 0 : rawState.__MICRO_APP_STATE__, {
|
|
3312
|
+
[appName]: {
|
|
3313
|
+
fullPath: targetLocation.pathname + targetLocation.search + targetLocation.hash,
|
|
3314
|
+
state: microState,
|
|
3315
|
+
mode: getRouterMode(appName),
|
|
3316
|
+
}
|
|
3317
|
+
})
|
|
3318
|
+
};
|
|
3319
|
+
// create new state object
|
|
3320
|
+
return assign({}, rawState, additionalState);
|
|
3269
3321
|
}
|
|
3270
3322
|
// delete micro app state form origin state
|
|
3271
3323
|
function removeMicroState(appName, rawState) {
|
|
3272
|
-
if (
|
|
3273
|
-
if (
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
delete rawState.microAppState;
|
|
3279
|
-
}
|
|
3324
|
+
if (isPlainObject(rawState === null || rawState === void 0 ? void 0 : rawState.__MICRO_APP_STATE__)) {
|
|
3325
|
+
if (!isUndefined(rawState.__MICRO_APP_STATE__[appName])) {
|
|
3326
|
+
delete rawState.__MICRO_APP_STATE__[appName];
|
|
3327
|
+
}
|
|
3328
|
+
if (!Object.keys(rawState.__MICRO_APP_STATE__).length) {
|
|
3329
|
+
delete rawState.__MICRO_APP_STATE__;
|
|
3280
3330
|
}
|
|
3281
|
-
return assign({}, rawState);
|
|
3282
3331
|
}
|
|
3283
|
-
return rawState;
|
|
3332
|
+
return assign({}, rawState);
|
|
3284
3333
|
}
|
|
3285
3334
|
// get micro app state form origin state
|
|
3286
3335
|
function getMicroState(appName) {
|
|
3287
|
-
var _a;
|
|
3336
|
+
var _a, _b;
|
|
3288
3337
|
const rawState = globalEnv.rawWindow.history.state;
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
}
|
|
3292
|
-
return rawState;
|
|
3338
|
+
// rawState?.__MICRO_APP_STATE__?.[appName]?.state || (isRouterModeCustom(appName) ? rawState : null)
|
|
3339
|
+
return ((_b = (_a = rawState === null || rawState === void 0 ? void 0 : rawState.__MICRO_APP_STATE__) === null || _a === void 0 ? void 0 : _a[appName]) === null || _b === void 0 ? void 0 : _b.state) || (isRouterModeCustom(appName) ? rawState : null);
|
|
3293
3340
|
}
|
|
3294
3341
|
const ENC_AD_RE = /&/g; // %M1
|
|
3295
3342
|
const ENC_EQ_RE = /=/g; // %M2
|
|
@@ -3325,17 +3372,30 @@ function formatQueryAppName(appName) {
|
|
|
3325
3372
|
* @param appName app.name
|
|
3326
3373
|
*/
|
|
3327
3374
|
function getMicroPathFromURL(appName) {
|
|
3328
|
-
var _a, _b;
|
|
3329
|
-
// TODO: pure模式从state中获取地址
|
|
3330
|
-
if (isRouterModePure(appName))
|
|
3331
|
-
return null;
|
|
3375
|
+
var _a, _b, _c, _d;
|
|
3332
3376
|
const rawLocation = globalEnv.rawWindow.location;
|
|
3377
|
+
const rawState = globalEnv.rawWindow.history.state;
|
|
3333
3378
|
if (isRouterModeSearch(appName)) {
|
|
3334
3379
|
const queryObject = getQueryObjectFromURL(rawLocation.search, rawLocation.hash);
|
|
3335
3380
|
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)]);
|
|
3336
3381
|
return isString(microPath) ? decodeMicroPath(microPath) : null;
|
|
3337
3382
|
}
|
|
3338
|
-
|
|
3383
|
+
/**
|
|
3384
|
+
* Get fullPath from __MICRO_APP_STATE__
|
|
3385
|
+
* NOTE:
|
|
3386
|
+
* 1. state mode: all base on __MICRO_APP_STATE__
|
|
3387
|
+
* 2. pure mode: navigate by location.xxx may contain one-time information in __MICRO_APP_STATE__
|
|
3388
|
+
* 3. native/scope mode: vue-router@4 will exec replaceState base on state before pushState, like:
|
|
3389
|
+
* history.replaceState(
|
|
3390
|
+
* assign({}, history.state, {...}),
|
|
3391
|
+
* title,
|
|
3392
|
+
* history.state.current, <---
|
|
3393
|
+
* )
|
|
3394
|
+
* when base app jump to another page from child page, it will replace child path with base app path
|
|
3395
|
+
* e.g: base-home --> child-home --> child-about(will replace with child-home before jump to base-home) --> base-home, when go back, it will back to child-home not child-about
|
|
3396
|
+
* So we take the fullPath as the standard
|
|
3397
|
+
*/
|
|
3398
|
+
return ((_d = (_c = rawState === null || rawState === void 0 ? void 0 : rawState.__MICRO_APP_STATE__) === null || _c === void 0 ? void 0 : _c[appName]) === null || _d === void 0 ? void 0 : _d.fullPath) || (isRouterModeCustom(appName) ? rawLocation.pathname + rawLocation.search + rawLocation.hash : null);
|
|
3339
3399
|
}
|
|
3340
3400
|
/**
|
|
3341
3401
|
* Attach child app fullPath to browser url
|
|
@@ -3343,10 +3403,11 @@ function getMicroPathFromURL(appName) {
|
|
|
3343
3403
|
* @param targetLocation location of child app or rawLocation of window
|
|
3344
3404
|
*/
|
|
3345
3405
|
function setMicroPathToURL(appName, targetLocation) {
|
|
3346
|
-
const
|
|
3406
|
+
const rawLocation = globalEnv.rawWindow.location;
|
|
3407
|
+
let targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3347
3408
|
let isAttach2Hash = false;
|
|
3348
3409
|
if (isRouterModeSearch(appName)) {
|
|
3349
|
-
let { pathname, search, hash } =
|
|
3410
|
+
let { pathname, search, hash } = rawLocation;
|
|
3350
3411
|
const queryObject = getQueryObjectFromURL(search, hash);
|
|
3351
3412
|
const encodedMicroPath = encodeMicroPath(targetFullPath);
|
|
3352
3413
|
/**
|
|
@@ -3356,6 +3417,7 @@ function setMicroPathToURL(appName, targetLocation) {
|
|
|
3356
3417
|
// If hash exists and search does not exist, it is considered as a hash route
|
|
3357
3418
|
if (hash && !search) {
|
|
3358
3419
|
isAttach2Hash = true;
|
|
3420
|
+
// TODO: 这里和下面的if判断可以简化一下
|
|
3359
3421
|
if (queryObject.hashQuery) {
|
|
3360
3422
|
queryObject.hashQuery[formatQueryAppName(appName)] = encodedMicroPath;
|
|
3361
3423
|
}
|
|
@@ -3383,6 +3445,9 @@ function setMicroPathToURL(appName, targetLocation) {
|
|
|
3383
3445
|
isAttach2Hash,
|
|
3384
3446
|
};
|
|
3385
3447
|
}
|
|
3448
|
+
if (isRouterModeState(appName) || isRouterModePure(appName)) {
|
|
3449
|
+
targetFullPath = rawLocation.pathname + rawLocation.search + rawLocation.hash;
|
|
3450
|
+
}
|
|
3386
3451
|
return {
|
|
3387
3452
|
fullPath: targetFullPath,
|
|
3388
3453
|
isAttach2Hash,
|
|
@@ -3391,11 +3456,10 @@ function setMicroPathToURL(appName, targetLocation) {
|
|
|
3391
3456
|
/**
|
|
3392
3457
|
* Delete child app fullPath from browser url
|
|
3393
3458
|
* @param appName app.name
|
|
3394
|
-
* @param targetLocation target Location, default is rawLocation
|
|
3395
3459
|
*/
|
|
3396
|
-
function removeMicroPathFromURL(appName
|
|
3460
|
+
function removeMicroPathFromURL(appName) {
|
|
3397
3461
|
var _a, _b, _c, _d;
|
|
3398
|
-
let { pathname, search, hash } =
|
|
3462
|
+
let { pathname, search, hash } = globalEnv.rawWindow.location;
|
|
3399
3463
|
let isAttach2Hash = false;
|
|
3400
3464
|
if (isRouterModeSearch(appName)) {
|
|
3401
3465
|
const queryObject = getQueryObjectFromURL(search, hash);
|
|
@@ -3457,25 +3521,33 @@ function isEffectiveApp(appName) {
|
|
|
3457
3521
|
*/
|
|
3458
3522
|
return !!(app && !app.isPrefetch);
|
|
3459
3523
|
}
|
|
3524
|
+
/**
|
|
3525
|
+
* get router mode of app
|
|
3526
|
+
* NOTE: app maybe undefined
|
|
3527
|
+
*/
|
|
3528
|
+
function getRouterMode(appName) {
|
|
3529
|
+
var _a;
|
|
3530
|
+
return (_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.routerMode;
|
|
3531
|
+
}
|
|
3460
3532
|
// router mode is search
|
|
3461
3533
|
function isRouterModeSearch(appName) {
|
|
3462
|
-
|
|
3463
|
-
|
|
3534
|
+
return getRouterMode(appName) === DEFAULT_ROUTER_MODE;
|
|
3535
|
+
}
|
|
3536
|
+
// router mode is state
|
|
3537
|
+
function isRouterModeState(appName) {
|
|
3538
|
+
return getRouterMode(appName) === ROUTER_MODE_STATE;
|
|
3464
3539
|
}
|
|
3465
3540
|
// router mode is history
|
|
3466
3541
|
function isRouterModeNative(appName) {
|
|
3467
|
-
|
|
3468
|
-
return !!(app && app.sandBox && app.routerMode === ROUTER_MODE_NATIVE);
|
|
3542
|
+
return getRouterMode(appName) === ROUTER_MODE_NATIVE;
|
|
3469
3543
|
}
|
|
3470
3544
|
// router mode is disable
|
|
3471
3545
|
function isRouterModeNativeScope(appName) {
|
|
3472
|
-
|
|
3473
|
-
return !!(app && app.sandBox && app.routerMode === ROUTER_MODE_NATIVE_SCOPE);
|
|
3546
|
+
return getRouterMode(appName) === ROUTER_MODE_NATIVE_SCOPE;
|
|
3474
3547
|
}
|
|
3475
3548
|
// router mode is pure
|
|
3476
3549
|
function isRouterModePure(appName) {
|
|
3477
|
-
|
|
3478
|
-
return !!(app && app.sandBox && app.routerMode === ROUTER_MODE_PURE);
|
|
3550
|
+
return getRouterMode(appName) === ROUTER_MODE_PURE;
|
|
3479
3551
|
}
|
|
3480
3552
|
/**
|
|
3481
3553
|
* router mode is history or disable
|
|
@@ -3492,7 +3564,7 @@ function isRouterModeCustom(appName) {
|
|
|
3492
3564
|
* @param inlineDisableMemoryRouter disable-memory-router set by micro-app element or prerender
|
|
3493
3565
|
* @returns router mode
|
|
3494
3566
|
*/
|
|
3495
|
-
function
|
|
3567
|
+
function initRouterMode(mode, inlineDisableMemoryRouter) {
|
|
3496
3568
|
/**
|
|
3497
3569
|
* compatible with disable-memory-router in older versions
|
|
3498
3570
|
* if disable-memory-router is true, router-mode will be disable
|
|
@@ -3527,7 +3599,21 @@ function addHistoryListener(appName) {
|
|
|
3527
3599
|
excludePreRender: true,
|
|
3528
3600
|
}).includes(appName) &&
|
|
3529
3601
|
!e.onlyForBrowser) {
|
|
3602
|
+
/**
|
|
3603
|
+
* TODO: vue-router@4 navigate async when receive popstateEvent, but child may respond to popstateEvent immediately(vue2, react), so when go back throw browser child will not unmount sync, and will respond to popstateEvent before base app, this will cause some problems
|
|
3604
|
+
* __MICRO_APP_BASE_ROUTE__不可控,用户设置的值是随机的且不一定使用,用它作为判断依据太过危险
|
|
3605
|
+
*/
|
|
3606
|
+
// const microAppWindow = appInstanceMap.get(appName)!.sandBox!.microAppWindow
|
|
3607
|
+
// const rawLocation = globalEnv.rawWindow.location
|
|
3608
|
+
// if (
|
|
3609
|
+
// !isRouterModeCustom(appName) ||
|
|
3610
|
+
// !microAppWindow.__MICRO_APP_BASE_ROUTE__ ||
|
|
3611
|
+
// // 主history、子hash,主、子都是hash如何处理
|
|
3612
|
+
// microAppWindow.__MICRO_APP_BASE_ROUTE__.includes('#') ||
|
|
3613
|
+
// `${rawLocation.pathname}/`.startsWith(('/' + microAppWindow.__MICRO_APP_BASE_ROUTE__).replace(/^\/+/, '/'))
|
|
3614
|
+
// ) {
|
|
3530
3615
|
updateMicroLocationWithEvent(appName, getMicroPathFromURL(appName));
|
|
3616
|
+
// }
|
|
3531
3617
|
}
|
|
3532
3618
|
};
|
|
3533
3619
|
rawWindow.addEventListener('popstate', popStateHandler);
|
|
@@ -3575,14 +3661,18 @@ function dispatchPopStateEventToMicroApp(appName, proxyWindow, microAppWindow) {
|
|
|
3575
3661
|
* TODO: test
|
|
3576
3662
|
* angular14 takes e.type as type judgment
|
|
3577
3663
|
* when e.type is popstate-appName popstate event will be invalid
|
|
3664
|
+
* Object.defineProperty(newPopStateEvent, 'type', {
|
|
3665
|
+
* value: 'popstate',
|
|
3666
|
+
* writable: true,
|
|
3667
|
+
* configurable: true,
|
|
3668
|
+
* enumerable: true,
|
|
3669
|
+
* })
|
|
3670
|
+
*/
|
|
3671
|
+
/**
|
|
3672
|
+
* create PopStateEvent named popstate-appName with sub app state
|
|
3673
|
+
* TODO: feeling like there's something wrong, check carefully
|
|
3674
|
+
* In native mode, getMicroState(appName) return rawWindow.history.state when use microApp.router.push/replace or other scenes when state.__MICRO_APP_STATE__[appName] is null
|
|
3578
3675
|
*/
|
|
3579
|
-
// Object.defineProperty(newPopStateEvent, 'type', {
|
|
3580
|
-
// value: 'popstate',
|
|
3581
|
-
// writable: true,
|
|
3582
|
-
// configurable: true,
|
|
3583
|
-
// enumerable: true,
|
|
3584
|
-
// })
|
|
3585
|
-
// create PopStateEvent named popstate-appName with sub app state
|
|
3586
3676
|
const newPopStateEvent = new PopStateEvent('popstate', { state: getMicroState(appName) });
|
|
3587
3677
|
microAppWindow.dispatchEvent(newPopStateEvent);
|
|
3588
3678
|
if (!isIframeSandbox(appName)) {
|
|
@@ -3661,7 +3751,7 @@ function createMicroHistory(appName, microLocation) {
|
|
|
3661
3751
|
const targetLocation = createURL(rests[2], microLocation.href);
|
|
3662
3752
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3663
3753
|
if (!isRouterModePure(appName)) {
|
|
3664
|
-
navigateWithNativeEvent(appName, methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rests[0]), rests[1]);
|
|
3754
|
+
navigateWithNativeEvent(appName, methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rests[0], targetLocation), rests[1]);
|
|
3665
3755
|
}
|
|
3666
3756
|
if (targetFullPath !== microLocation.fullPath) {
|
|
3667
3757
|
updateMicroLocation(appName, targetFullPath, microLocation);
|
|
@@ -3675,8 +3765,12 @@ function createMicroHistory(appName, microLocation) {
|
|
|
3675
3765
|
}
|
|
3676
3766
|
const pushState = getMicroHistoryMethod('pushState');
|
|
3677
3767
|
const replaceState = getMicroHistoryMethod('replaceState');
|
|
3678
|
-
if (isIframeSandbox(appName))
|
|
3679
|
-
return {
|
|
3768
|
+
if (isIframeSandbox(appName)) {
|
|
3769
|
+
return {
|
|
3770
|
+
pushState,
|
|
3771
|
+
replaceState,
|
|
3772
|
+
};
|
|
3773
|
+
}
|
|
3680
3774
|
return new Proxy(rawHistory, {
|
|
3681
3775
|
get(target, key) {
|
|
3682
3776
|
if (key === 'state') {
|
|
@@ -3739,11 +3833,7 @@ function navigateWithNativeEvent(appName, methodName, result, onlyForBrowser, st
|
|
|
3739
3833
|
const oldHref = result.isAttach2Hash && oldFullPath !== result.fullPath ? rawLocation.href : null;
|
|
3740
3834
|
// navigate with native history method
|
|
3741
3835
|
nativeHistoryNavigate(appName, methodName, result.fullPath, state, title);
|
|
3742
|
-
|
|
3743
|
-
* TODO:
|
|
3744
|
-
* 1. 如果所有模式统一发送popstate事件,则isRouterModeSearch(appName)要去掉
|
|
3745
|
-
* 2. 如果发送事件,则会导致vue router-view :key='router.path'绑定,无限卸载应用,死循环
|
|
3746
|
-
*/
|
|
3836
|
+
// just search mode will dispatch native event
|
|
3747
3837
|
if (oldFullPath !== result.fullPath && isRouterModeSearch(appName)) {
|
|
3748
3838
|
dispatchNativeEvent(appName, onlyForBrowser, oldHref);
|
|
3749
3839
|
}
|
|
@@ -3760,22 +3850,22 @@ function attachRouteToBrowserURL(appName, result, state) {
|
|
|
3760
3850
|
navigateWithNativeEvent(appName, 'replaceState', result, true, state);
|
|
3761
3851
|
}
|
|
3762
3852
|
/**
|
|
3763
|
-
* When path is same, keep the
|
|
3764
|
-
* Fix bug of missing
|
|
3853
|
+
* When path is same, keep the __MICRO_APP_STATE__ in history.state
|
|
3854
|
+
* Fix bug of missing __MICRO_APP_STATE__ when base app is next.js or angular
|
|
3765
3855
|
* @param method history.pushState/replaceState
|
|
3766
3856
|
*/
|
|
3767
3857
|
function reWriteHistoryMethod(method) {
|
|
3768
3858
|
const rawWindow = globalEnv.rawWindow;
|
|
3769
3859
|
return function (...rests) {
|
|
3770
3860
|
var _a;
|
|
3771
|
-
if (((_a = rawWindow.history.state) === null || _a === void 0 ? void 0 : _a.
|
|
3772
|
-
(!isPlainObject(rests[0]) || !rests[0].
|
|
3861
|
+
if (((_a = rawWindow.history.state) === null || _a === void 0 ? void 0 : _a.__MICRO_APP_STATE__) &&
|
|
3862
|
+
(!isPlainObject(rests[0]) || !rests[0].__MICRO_APP_STATE__) &&
|
|
3773
3863
|
(isString(rests[2]) || isURL(rests[2]))) {
|
|
3774
3864
|
const currentHref = rawWindow.location.href;
|
|
3775
3865
|
const targetLocation = createURL(rests[2], currentHref);
|
|
3776
3866
|
if (targetLocation.href === currentHref) {
|
|
3777
3867
|
rests[0] = assign({}, rests[0], {
|
|
3778
|
-
|
|
3868
|
+
__MICRO_APP_STATE__: rawWindow.history.state.__MICRO_APP_STATE__,
|
|
3779
3869
|
});
|
|
3780
3870
|
}
|
|
3781
3871
|
}
|
|
@@ -3791,9 +3881,9 @@ function reWriteHistoryMethod(method) {
|
|
|
3791
3881
|
excludeHiddenApp: true,
|
|
3792
3882
|
excludePreRender: true,
|
|
3793
3883
|
}).forEach(appName => {
|
|
3794
|
-
if (isRouterModeSearch(appName) && !getMicroPathFromURL(appName)) {
|
|
3884
|
+
if ((isRouterModeSearch(appName) || isRouterModeState(appName)) && !getMicroPathFromURL(appName)) {
|
|
3795
3885
|
const app = appInstanceMap.get(appName);
|
|
3796
|
-
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3886
|
+
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName), app.sandBox.proxyWindow.location));
|
|
3797
3887
|
}
|
|
3798
3888
|
});
|
|
3799
3889
|
// fix bug for nest app
|
|
@@ -3802,7 +3892,7 @@ function reWriteHistoryMethod(method) {
|
|
|
3802
3892
|
}
|
|
3803
3893
|
/**
|
|
3804
3894
|
* rewrite history.pushState/replaceState
|
|
3805
|
-
* used to fix the problem that the
|
|
3895
|
+
* used to fix the problem that the __MICRO_APP_STATE__ maybe missing when mainApp navigate to same path
|
|
3806
3896
|
* e.g: when nextjs, angular receive popstate event, they will use history.replaceState to update browser url with a new state object
|
|
3807
3897
|
*/
|
|
3808
3898
|
function patchHistory() {
|
|
@@ -3825,7 +3915,7 @@ function createRouterApi() {
|
|
|
3825
3915
|
* @param state to.state
|
|
3826
3916
|
*/
|
|
3827
3917
|
function navigateWithRawHistory(appName, methodName, targetLocation, state) {
|
|
3828
|
-
navigateWithNativeEvent(appName, methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName, state !== null && state !== void 0 ? state : null));
|
|
3918
|
+
navigateWithNativeEvent(appName, methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName, state !== null && state !== void 0 ? state : null, targetLocation));
|
|
3829
3919
|
// clear element scope after navigate
|
|
3830
3920
|
removeDomScope();
|
|
3831
3921
|
}
|
|
@@ -3843,23 +3933,13 @@ function createRouterApi() {
|
|
|
3843
3933
|
const currentFullPath = microLocation.pathname + microLocation.search + microLocation.hash;
|
|
3844
3934
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3845
3935
|
if (currentFullPath !== targetFullPath || getMicroPathFromURL(appName) !== targetFullPath) {
|
|
3936
|
+
// pure mode will not call history.pushState/replaceState
|
|
3846
3937
|
if (!isRouterModePure(appName)) {
|
|
3847
3938
|
const methodName = (replace && to.replace !== false) || to.replace === true ? 'replaceState' : 'pushState';
|
|
3848
3939
|
navigateWithRawHistory(appName, methodName, targetLocation, to.state);
|
|
3849
3940
|
}
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
* 1. 关闭虚拟路由的跳转地址不同:baseRoute + 子应用地址,文档中要说明
|
|
3853
|
-
* 2. 关闭虚拟路由时跳转方式不同:1、基座跳转但不发送popstate事件 2、控制子应用更新location,内部发送popstate事件。
|
|
3854
|
-
* 核心思路:减小对基座的影响(子应用跳转不向基座发送popstate事件,其他操作一致),但这是必要的吗,只是多了一个触发popstate的操作
|
|
3855
|
-
* 路由优化方案有两种:
|
|
3856
|
-
* 1、减少对基座的影响,主要是解决vue循环刷新的问题
|
|
3857
|
-
* 2、全局发送popstate事件,解决主、子都是vue3的冲突问题
|
|
3858
|
-
* 两者选一个吧,如果选2,则下面这两行代码可以去掉
|
|
3859
|
-
* NOTE1: history和search模式采用2,这样可以解决vue3的问题,custom采用1,避免vue循环刷新的问题,这样在用户出现问题时各有解决方案。但反过来说,每种方案又分别导致另外的问题,不统一,导致复杂度增高
|
|
3860
|
-
* NOTE2: 关闭虚拟路由,同时发送popstate事件还是无法解决vue3的问题(毕竟history.state理论上还是会冲突),那么就没必要发送popstate事件了。
|
|
3861
|
-
*/
|
|
3862
|
-
if (isRouterModeCustom(appName) || isRouterModePure(appName)) {
|
|
3941
|
+
// only search mode will dispatch PopStateEvent to browser
|
|
3942
|
+
if (!isRouterModeSearch(appName)) {
|
|
3863
3943
|
updateMicroLocationWithEvent(appName, targetFullPath);
|
|
3864
3944
|
}
|
|
3865
3945
|
}
|
|
@@ -3884,27 +3964,18 @@ function createRouterApi() {
|
|
|
3884
3964
|
* 2. disable memory-router
|
|
3885
3965
|
*/
|
|
3886
3966
|
/**
|
|
3887
|
-
* TODO:
|
|
3888
|
-
* 1
|
|
3967
|
+
* TODO:
|
|
3968
|
+
* 1、子应用开始渲染但是还没渲染完成,调用跳转改如何处理
|
|
3889
3969
|
* 2、iframe的沙箱还没初始化时执行跳转报错,如何处理。。。
|
|
3890
|
-
* 3、hidden app 是否支持跳转
|
|
3970
|
+
* 3、hidden app、预渲染 app 是否支持跳转 --- 支持(这里还涉及子应用内部跳转的支持)
|
|
3891
3971
|
*/
|
|
3892
3972
|
if (getActiveApps({ excludeHiddenApp: true, excludePreRender: true }).includes(appName)) {
|
|
3893
3973
|
const app = appInstanceMap.get(appName);
|
|
3894
3974
|
resolve(app.sandBox.sandboxReady.then(() => handleNavigate(appName, app, to, replace)));
|
|
3895
3975
|
}
|
|
3896
3976
|
else {
|
|
3897
|
-
reject(logError('
|
|
3977
|
+
reject(logError('导航失败,请确保子应用渲染后再调用此方法'));
|
|
3898
3978
|
}
|
|
3899
|
-
// /**
|
|
3900
|
-
// * app not exit or unmounted, update browser URL with replaceState
|
|
3901
|
-
// * use base app location.origin as baseURL
|
|
3902
|
-
// * 应用不存在或已卸载,依然使用replaceState来更新浏览器地址 -- 不合理
|
|
3903
|
-
// */
|
|
3904
|
-
// /**
|
|
3905
|
-
// * TODO: 应用还没渲染或已经卸载最好不要支持跳转了,我知道这是因为解决一些特殊场景,但这么做是非常反直觉的
|
|
3906
|
-
// * 并且在新版本中有多种路由模式,如果应用不存在,我们根本无法知道是哪种模式,那么这里的操作就无意义了。
|
|
3907
|
-
// */
|
|
3908
3979
|
// const rawLocation = globalEnv.rawWindow.location
|
|
3909
3980
|
// const targetLocation = createURL(to.path, rawLocation.origin)
|
|
3910
3981
|
// const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash
|
|
@@ -3977,9 +4048,9 @@ function createRouterApi() {
|
|
|
3977
4048
|
* 3. router mode is custom
|
|
3978
4049
|
*/
|
|
3979
4050
|
function commonHandlerForAttachToURL(appName) {
|
|
3980
|
-
if (isRouterModeSearch(appName)) {
|
|
4051
|
+
if (isRouterModeSearch(appName) || isRouterModeState(appName)) {
|
|
3981
4052
|
const app = appInstanceMap.get(appName);
|
|
3982
|
-
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
4053
|
+
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName), app.sandBox.proxyWindow.location));
|
|
3983
4054
|
}
|
|
3984
4055
|
}
|
|
3985
4056
|
/**
|
|
@@ -4078,94 +4149,6 @@ function createRouterApi() {
|
|
|
4078
4149
|
}
|
|
4079
4150
|
const { router, executeNavigationGuard, clearRouterWhenUnmount, } = createRouterApi();
|
|
4080
4151
|
|
|
4081
|
-
const escape2RawWindowKeys = [
|
|
4082
|
-
'getComputedStyle',
|
|
4083
|
-
'visualViewport',
|
|
4084
|
-
'matchMedia',
|
|
4085
|
-
// 'DOMParser',
|
|
4086
|
-
'ResizeObserver',
|
|
4087
|
-
'IntersectionObserver',
|
|
4088
|
-
];
|
|
4089
|
-
const escape2RawWindowRegExpKeys = [
|
|
4090
|
-
/animationFrame$/i,
|
|
4091
|
-
/mutationObserver$/i,
|
|
4092
|
-
/height$|width$/i,
|
|
4093
|
-
/offset$/i,
|
|
4094
|
-
// /event$/i,
|
|
4095
|
-
/selection$/i,
|
|
4096
|
-
/^range/i,
|
|
4097
|
-
/^screen/i,
|
|
4098
|
-
/^scroll/i,
|
|
4099
|
-
/X$|Y$/,
|
|
4100
|
-
];
|
|
4101
|
-
const uniqueDocumentElement = [
|
|
4102
|
-
'body',
|
|
4103
|
-
'head',
|
|
4104
|
-
'html',
|
|
4105
|
-
'title',
|
|
4106
|
-
];
|
|
4107
|
-
const hijackMicroLocationKeys = [
|
|
4108
|
-
'host',
|
|
4109
|
-
'hostname',
|
|
4110
|
-
'port',
|
|
4111
|
-
'protocol',
|
|
4112
|
-
'origin',
|
|
4113
|
-
];
|
|
4114
|
-
// 有shadowRoot则代理到shadowRoot否则代理到原生document上 (属性)
|
|
4115
|
-
const proxy2RawDocOrShadowKeys = [
|
|
4116
|
-
'childElementCount',
|
|
4117
|
-
'children',
|
|
4118
|
-
'firstElementChild',
|
|
4119
|
-
'firstChild',
|
|
4120
|
-
'lastElementChild',
|
|
4121
|
-
'activeElement',
|
|
4122
|
-
'fullscreenElement',
|
|
4123
|
-
'pictureInPictureElement',
|
|
4124
|
-
'pointerLockElement',
|
|
4125
|
-
'styleSheets',
|
|
4126
|
-
];
|
|
4127
|
-
// 有shadowRoot则代理到shadowRoot否则代理到原生document上 (方法)
|
|
4128
|
-
const proxy2RawDocOrShadowMethods = [
|
|
4129
|
-
'append',
|
|
4130
|
-
'contains',
|
|
4131
|
-
'replaceChildren',
|
|
4132
|
-
'createRange',
|
|
4133
|
-
'getSelection',
|
|
4134
|
-
'elementFromPoint',
|
|
4135
|
-
'elementsFromPoint',
|
|
4136
|
-
'getAnimations',
|
|
4137
|
-
];
|
|
4138
|
-
// 直接代理到原生document上 (属性)
|
|
4139
|
-
const proxy2RawDocumentKeys = [
|
|
4140
|
-
'characterSet',
|
|
4141
|
-
'compatMode',
|
|
4142
|
-
'contentType',
|
|
4143
|
-
'designMode',
|
|
4144
|
-
'dir',
|
|
4145
|
-
'doctype',
|
|
4146
|
-
'embeds',
|
|
4147
|
-
'fullscreenEnabled',
|
|
4148
|
-
'hidden',
|
|
4149
|
-
'implementation',
|
|
4150
|
-
'lastModified',
|
|
4151
|
-
'pictureInPictureEnabled',
|
|
4152
|
-
'plugins',
|
|
4153
|
-
'readyState',
|
|
4154
|
-
'referrer',
|
|
4155
|
-
'visibilityState',
|
|
4156
|
-
'fonts',
|
|
4157
|
-
];
|
|
4158
|
-
// 直接代理到原生document上 (方法)
|
|
4159
|
-
const proxy2RawDocumentMethods = [
|
|
4160
|
-
'execCommand',
|
|
4161
|
-
'createRange',
|
|
4162
|
-
'exitFullscreen',
|
|
4163
|
-
'exitPictureInPicture',
|
|
4164
|
-
'getElementsByTagNameNS',
|
|
4165
|
-
'hasFocus',
|
|
4166
|
-
'prepend',
|
|
4167
|
-
];
|
|
4168
|
-
|
|
4169
4152
|
// origin is readonly, so we ignore when updateMicroLocation
|
|
4170
4153
|
const locationKeys = ['href', 'pathname', 'search', 'hash', 'host', 'hostname', 'port', 'protocol', 'search'];
|
|
4171
4154
|
// origin, fullPath is necessary for guardLocation
|
|
@@ -4209,39 +4192,47 @@ function createMicroLocation(appName, url, microAppWindow, childStaticLocation,
|
|
|
4209
4192
|
if (targetLocation.origin === proxyLocation.origin) {
|
|
4210
4193
|
const setMicroPathResult = setMicroPathToURL(appName, targetLocation);
|
|
4211
4194
|
// if disable memory-router, navigate directly through rawLocation
|
|
4212
|
-
if (
|
|
4195
|
+
if (!isRouterModeCustom(appName)) {
|
|
4196
|
+
methodName = isRouterModePure(appName) ? 'replaceState' : methodName;
|
|
4213
4197
|
/**
|
|
4214
4198
|
* change hash with location.href will not trigger the browser reload
|
|
4215
4199
|
* so we use pushState & reload to imitate href behavior
|
|
4216
4200
|
* NOTE:
|
|
4217
|
-
* 1. if child app only change hash, it
|
|
4218
|
-
* 2. if address is same and has hash, it
|
|
4201
|
+
* 1. if child app only change hash, it will not reload browser
|
|
4202
|
+
* 2. if address is same and has hash, it will not add route stack
|
|
4219
4203
|
*/
|
|
4220
4204
|
if (targetLocation.pathname === proxyLocation.pathname &&
|
|
4221
4205
|
targetLocation.search === proxyLocation.search) {
|
|
4222
4206
|
let oldHref = null;
|
|
4223
|
-
if
|
|
4224
|
-
|
|
4207
|
+
// NOTE: if pathname & search is same, it should record router info to history.state in pure mode
|
|
4208
|
+
if (targetLocation.hash !== proxyLocation.hash || isRouterModePure(appName)) {
|
|
4209
|
+
// search mode only
|
|
4210
|
+
if (setMicroPathResult.isAttach2Hash) {
|
|
4225
4211
|
oldHref = rawLocation.href;
|
|
4226
|
-
|
|
4212
|
+
}
|
|
4213
|
+
// if router mode is pure and targetLocation.hash exist, it will not call nativeHistoryNavigate
|
|
4214
|
+
if (!isRouterModePure(appName) || !targetLocation.hash) {
|
|
4215
|
+
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath, !isRouterModeSearch(appName) ? setMicroState(appName, null, targetLocation) : null);
|
|
4216
|
+
}
|
|
4227
4217
|
}
|
|
4228
4218
|
if (targetLocation.hash) {
|
|
4229
|
-
|
|
4219
|
+
if (isRouterModeSearch(appName)) {
|
|
4220
|
+
dispatchNativeEvent(appName, false, oldHref);
|
|
4221
|
+
}
|
|
4222
|
+
else {
|
|
4223
|
+
updateMicroLocationWithEvent(appName, targetLocation.pathname + targetLocation.search + targetLocation.hash);
|
|
4224
|
+
}
|
|
4230
4225
|
}
|
|
4231
4226
|
else {
|
|
4232
4227
|
reload();
|
|
4233
4228
|
}
|
|
4234
4229
|
return void 0;
|
|
4235
|
-
/**
|
|
4236
|
-
* when baseApp is hash router, address change of child can not reload browser
|
|
4237
|
-
* so we imitate behavior of browser (reload) manually
|
|
4238
|
-
*/
|
|
4239
|
-
}
|
|
4240
|
-
else if (setMicroPathResult.isAttach2Hash) {
|
|
4241
|
-
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath);
|
|
4242
|
-
reload();
|
|
4243
|
-
return void 0;
|
|
4244
4230
|
}
|
|
4231
|
+
// when pathname or search change, simulate behavior of browser (reload) manually
|
|
4232
|
+
// TODO: state模式下pushState会带上上一个页面的state,会不会有问题,尤其是vue3,应不应该将主应用的state设置为null
|
|
4233
|
+
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath, !isRouterModeSearch(appName) ? setMicroState(appName, null, targetLocation) : null);
|
|
4234
|
+
reload();
|
|
4235
|
+
return void 0;
|
|
4245
4236
|
}
|
|
4246
4237
|
return setMicroPathResult.fullPath;
|
|
4247
4238
|
}
|
|
@@ -4266,7 +4257,9 @@ function createMicroLocation(appName, url, microAppWindow, childStaticLocation,
|
|
|
4266
4257
|
* pathname: /path ==> /path#hash, /path ==> /path?query
|
|
4267
4258
|
* search: ?query ==> ?query#hash
|
|
4268
4259
|
*/
|
|
4269
|
-
nativeHistoryNavigate(appName, targetLocation[key] === proxyLocation[key]
|
|
4260
|
+
nativeHistoryNavigate(appName, (targetLocation[key] === proxyLocation[key] || isRouterModePure(appName))
|
|
4261
|
+
? 'replaceState'
|
|
4262
|
+
: 'pushState', setMicroPathToURL(appName, targetLocation).fullPath, !isRouterModeSearch(appName) ? setMicroState(appName, null, targetLocation) : null);
|
|
4270
4263
|
reload();
|
|
4271
4264
|
}
|
|
4272
4265
|
}
|
|
@@ -4305,17 +4298,27 @@ function createMicroLocation(appName, url, microAppWindow, childStaticLocation,
|
|
|
4305
4298
|
return target;
|
|
4306
4299
|
if (key === 'fullPath')
|
|
4307
4300
|
return target.fullPath;
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4301
|
+
/**
|
|
4302
|
+
* Special keys: host, hostname, port, protocol, origin, href
|
|
4303
|
+
* NOTE:
|
|
4304
|
+
* 1. In native mode this keys point to browser, in other mode this keys point to child app origin
|
|
4305
|
+
* 2. In iframe sandbox, iframe.src is base app address, so origin points to the browser by default, we need to replace it with child app origin
|
|
4306
|
+
* 3. In other modes, origin points to child app
|
|
4307
|
+
*/
|
|
4308
|
+
if (HIJACK_LOCATION_KEYS.includes(key)) {
|
|
4309
|
+
if (isRouterModeNative(appName)) {
|
|
4310
|
+
return rawLocation[key];
|
|
4311
|
+
}
|
|
4312
|
+
if (isIframe) {
|
|
4315
4313
|
return childStaticLocation[key];
|
|
4316
4314
|
}
|
|
4317
|
-
|
|
4318
|
-
|
|
4315
|
+
}
|
|
4316
|
+
if (key === 'href') {
|
|
4317
|
+
if (isRouterModeNative(appName)) {
|
|
4318
|
+
return target[key].replace(target.origin, rawLocation.origin);
|
|
4319
|
+
}
|
|
4320
|
+
if (isIframe) {
|
|
4321
|
+
// target may be deleted
|
|
4319
4322
|
return target[key].replace(browserHost, childHost);
|
|
4320
4323
|
}
|
|
4321
4324
|
}
|
|
@@ -4365,7 +4368,12 @@ function createMicroLocation(appName, url, microAppWindow, childStaticLocation,
|
|
|
4365
4368
|
const targetLocation = createURL(targetPath, url);
|
|
4366
4369
|
// The same hash will not trigger popStateEvent
|
|
4367
4370
|
if (targetLocation.hash !== proxyLocation.hash) {
|
|
4368
|
-
|
|
4371
|
+
if (!isRouterModePure(appName)) {
|
|
4372
|
+
navigateWithNativeEvent(appName, 'pushState', setMicroPathToURL(appName, targetLocation), false, setMicroState(appName, null, targetLocation));
|
|
4373
|
+
}
|
|
4374
|
+
if (!isRouterModeSearch(appName)) {
|
|
4375
|
+
updateMicroLocationWithEvent(appName, targetLocation.pathname + targetLocation.search + targetLocation.hash);
|
|
4376
|
+
}
|
|
4369
4377
|
}
|
|
4370
4378
|
}
|
|
4371
4379
|
}
|
|
@@ -4432,11 +4440,6 @@ function updateMicroLocation(appName, path, microLocation, type) {
|
|
|
4432
4440
|
}
|
|
4433
4441
|
}
|
|
4434
4442
|
|
|
4435
|
-
/**
|
|
4436
|
-
* TODO: 关于关闭虚拟路由系统的custom、history模式
|
|
4437
|
-
* 1. 是否需要发送popstate事件,为了减小对基座的影响,现在不发送
|
|
4438
|
-
* 2. 关闭后导致的vue3路由冲突问题需要在文档中明确指出(2处:在关闭虚拟路由系统的配置那里着重说明,在vue常见问题中说明)
|
|
4439
|
-
*/
|
|
4440
4443
|
/**
|
|
4441
4444
|
* The router system has two operations: read and write
|
|
4442
4445
|
* Read through location and write through history & location
|
|
@@ -4461,6 +4464,9 @@ function initRouteStateWithURL(appName, microLocation, defaultPage) {
|
|
|
4461
4464
|
const microPath = getMicroPathFromURL(appName);
|
|
4462
4465
|
if (microPath) {
|
|
4463
4466
|
updateMicroLocation(appName, microPath, microLocation, 'auto');
|
|
4467
|
+
if (isRouterModePure(appName)) {
|
|
4468
|
+
removePathFromBrowser(appName);
|
|
4469
|
+
}
|
|
4464
4470
|
}
|
|
4465
4471
|
else {
|
|
4466
4472
|
updateBrowserURLWithLocation(appName, microLocation, defaultPage);
|
|
@@ -4478,7 +4484,7 @@ function updateBrowserURLWithLocation(appName, microLocation, defaultPage) {
|
|
|
4478
4484
|
updateMicroLocation(appName, defaultPage, microLocation, 'prevent');
|
|
4479
4485
|
if (!isRouterModePure(appName)) {
|
|
4480
4486
|
// attach microApp route info to browser URL
|
|
4481
|
-
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, microLocation), setMicroState(appName, null));
|
|
4487
|
+
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, microLocation), setMicroState(appName, null, microLocation));
|
|
4482
4488
|
}
|
|
4483
4489
|
// trigger guards after change browser URL
|
|
4484
4490
|
autoTriggerNavigationGuard(appName, microLocation);
|
|
@@ -4491,14 +4497,13 @@ function updateBrowserURLWithLocation(appName, microLocation, defaultPage) {
|
|
|
4491
4497
|
* @param keepRouteState keep-router-state is only used to control whether to clear the location of microApp, default is false
|
|
4492
4498
|
*/
|
|
4493
4499
|
function clearRouteStateFromURL(appName, url, microLocation, keepRouteState) {
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
}
|
|
4500
|
+
// TODO: keep-router-state 功能太弱,是否可以增加优先级,或者去掉
|
|
4501
|
+
if (!keepRouteState && !isRouterModeCustom(appName)) {
|
|
4502
|
+
const { pathname, search, hash } = createURL(url);
|
|
4503
|
+
updateMicroLocation(appName, pathname + search + hash, microLocation, 'prevent');
|
|
4504
|
+
}
|
|
4505
|
+
if (!isRouterModePure(appName)) {
|
|
4506
|
+
removePathFromBrowser(appName);
|
|
4502
4507
|
}
|
|
4503
4508
|
clearRouterWhenUnmount(appName);
|
|
4504
4509
|
}
|
|
@@ -5155,13 +5160,29 @@ class WithSandBox extends BaseSandbox {
|
|
|
5155
5160
|
WithSandBox.activeCount = 0; // number of active sandbox
|
|
5156
5161
|
|
|
5157
5162
|
function patchRouter(appName, url, microAppWindow, browserHost) {
|
|
5163
|
+
const rawHistory = globalEnv.rawWindow.history;
|
|
5158
5164
|
const childStaticLocation = createURL(url);
|
|
5159
5165
|
const childHost = childStaticLocation.protocol + '//' + childStaticLocation.host;
|
|
5160
5166
|
const childFullPath = childStaticLocation.pathname + childStaticLocation.search + childStaticLocation.hash;
|
|
5161
5167
|
// rewrite microAppWindow.history
|
|
5162
5168
|
const microHistory = microAppWindow.history;
|
|
5169
|
+
// save history.replaceState, it will be used in updateMicroLocation
|
|
5163
5170
|
microAppWindow.rawReplaceState = microHistory.replaceState;
|
|
5171
|
+
// rewrite microAppWindow.history
|
|
5164
5172
|
assign(microHistory, createMicroHistory(appName, microAppWindow.location));
|
|
5173
|
+
// scrollRestoration proxy to rawHistory
|
|
5174
|
+
rawDefineProperties(microHistory, {
|
|
5175
|
+
scrollRestoration: {
|
|
5176
|
+
configurable: true,
|
|
5177
|
+
enumerable: true,
|
|
5178
|
+
get() {
|
|
5179
|
+
return rawHistory.scrollRestoration;
|
|
5180
|
+
},
|
|
5181
|
+
set(value) {
|
|
5182
|
+
rawHistory.scrollRestoration = value;
|
|
5183
|
+
}
|
|
5184
|
+
}
|
|
5185
|
+
});
|
|
5165
5186
|
/**
|
|
5166
5187
|
* Init microLocation before exec sandbox.start
|
|
5167
5188
|
* NOTE:
|
|
@@ -5173,6 +5194,87 @@ function patchRouter(appName, url, microAppWindow, browserHost) {
|
|
|
5173
5194
|
return createMicroLocation(appName, url, microAppWindow, childStaticLocation, browserHost, childHost);
|
|
5174
5195
|
}
|
|
5175
5196
|
|
|
5197
|
+
const escape2RawWindowKeys = [
|
|
5198
|
+
'getComputedStyle',
|
|
5199
|
+
'visualViewport',
|
|
5200
|
+
'matchMedia',
|
|
5201
|
+
// 'DOMParser',
|
|
5202
|
+
'ResizeObserver',
|
|
5203
|
+
'IntersectionObserver',
|
|
5204
|
+
];
|
|
5205
|
+
const escape2RawWindowRegExpKeys = [
|
|
5206
|
+
/animationFrame$/i,
|
|
5207
|
+
/mutationObserver$/i,
|
|
5208
|
+
/height$|width$/i,
|
|
5209
|
+
/offset$/i,
|
|
5210
|
+
// /event$/i,
|
|
5211
|
+
/selection$/i,
|
|
5212
|
+
/^range/i,
|
|
5213
|
+
/^screen/i,
|
|
5214
|
+
/^scroll/i,
|
|
5215
|
+
/X$|Y$/,
|
|
5216
|
+
];
|
|
5217
|
+
const uniqueDocumentElement = [
|
|
5218
|
+
'body',
|
|
5219
|
+
'head',
|
|
5220
|
+
'html',
|
|
5221
|
+
'title',
|
|
5222
|
+
];
|
|
5223
|
+
// 有shadowRoot则代理到shadowRoot否则代理到原生document上 (属性)
|
|
5224
|
+
const proxy2RawDocOrShadowKeys = [
|
|
5225
|
+
'childElementCount',
|
|
5226
|
+
'children',
|
|
5227
|
+
'firstElementChild',
|
|
5228
|
+
'firstChild',
|
|
5229
|
+
'lastElementChild',
|
|
5230
|
+
'activeElement',
|
|
5231
|
+
'fullscreenElement',
|
|
5232
|
+
'pictureInPictureElement',
|
|
5233
|
+
'pointerLockElement',
|
|
5234
|
+
'styleSheets',
|
|
5235
|
+
];
|
|
5236
|
+
// 有shadowRoot则代理到shadowRoot否则代理到原生document上 (方法)
|
|
5237
|
+
const proxy2RawDocOrShadowMethods = [
|
|
5238
|
+
'append',
|
|
5239
|
+
'contains',
|
|
5240
|
+
'replaceChildren',
|
|
5241
|
+
'createRange',
|
|
5242
|
+
'getSelection',
|
|
5243
|
+
'elementFromPoint',
|
|
5244
|
+
'elementsFromPoint',
|
|
5245
|
+
'getAnimations',
|
|
5246
|
+
];
|
|
5247
|
+
// 直接代理到原生document上 (属性)
|
|
5248
|
+
const proxy2RawDocumentKeys = [
|
|
5249
|
+
'characterSet',
|
|
5250
|
+
'compatMode',
|
|
5251
|
+
'contentType',
|
|
5252
|
+
'designMode',
|
|
5253
|
+
'dir',
|
|
5254
|
+
'doctype',
|
|
5255
|
+
'embeds',
|
|
5256
|
+
'fullscreenEnabled',
|
|
5257
|
+
'hidden',
|
|
5258
|
+
'implementation',
|
|
5259
|
+
'lastModified',
|
|
5260
|
+
'pictureInPictureEnabled',
|
|
5261
|
+
'plugins',
|
|
5262
|
+
'readyState',
|
|
5263
|
+
'referrer',
|
|
5264
|
+
'visibilityState',
|
|
5265
|
+
'fonts',
|
|
5266
|
+
];
|
|
5267
|
+
// 直接代理到原生document上 (方法)
|
|
5268
|
+
const proxy2RawDocumentMethods = [
|
|
5269
|
+
'execCommand',
|
|
5270
|
+
'createRange',
|
|
5271
|
+
'exitFullscreen',
|
|
5272
|
+
'exitPictureInPicture',
|
|
5273
|
+
'getElementsByTagNameNS',
|
|
5274
|
+
'hasFocus',
|
|
5275
|
+
'prepend',
|
|
5276
|
+
];
|
|
5277
|
+
|
|
5176
5278
|
/**
|
|
5177
5279
|
* patch window of child app
|
|
5178
5280
|
* @param appName app name
|
|
@@ -5220,7 +5322,7 @@ function patchWindowProperty$1(appName, microAppWindow) {
|
|
|
5220
5322
|
}
|
|
5221
5323
|
return false;
|
|
5222
5324
|
});
|
|
5223
|
-
return /^on/.test(key) && !
|
|
5325
|
+
return /^on/.test(key) && !SCOPE_WINDOW_ON_EVENT_OF_IFRAME.includes(key);
|
|
5224
5326
|
})
|
|
5225
5327
|
.forEach((eventName) => {
|
|
5226
5328
|
const { enumerable, writable, set } = Object.getOwnPropertyDescriptor(microAppWindow, eventName) || {
|
|
@@ -5309,7 +5411,7 @@ function patchWindowEffect$1(microAppWindow) {
|
|
|
5309
5411
|
const eventListenerMap = new Map();
|
|
5310
5412
|
const sstEventListenerMap = new Map();
|
|
5311
5413
|
function getEventTarget(type) {
|
|
5312
|
-
return
|
|
5414
|
+
return SCOPE_WINDOW_EVENT_OF_IFRAME.includes(type) ? microAppWindow : rawWindow;
|
|
5313
5415
|
}
|
|
5314
5416
|
// TODO: listener 是否需要绑定microAppWindow,否则函数中的this指向原生window
|
|
5315
5417
|
microAppWindow.addEventListener = function (type, listener, options) {
|
|
@@ -5847,7 +5949,7 @@ function patchIframeNode(appName, microAppWindow, sandbox) {
|
|
|
5847
5949
|
configurable: true,
|
|
5848
5950
|
enumerable: true,
|
|
5849
5951
|
get() {
|
|
5850
|
-
return this.__PURE_ELEMENT__
|
|
5952
|
+
return this.__PURE_ELEMENT__ || this === microDocument
|
|
5851
5953
|
? rawOwnerDocumentDesc.get.call(this)
|
|
5852
5954
|
: microDocument;
|
|
5853
5955
|
},
|
|
@@ -6433,6 +6535,7 @@ class CreateApp {
|
|
|
6433
6535
|
// mount before prerender exec mount (loading source), set isPrerender to false
|
|
6434
6536
|
this.isPrerender = false;
|
|
6435
6537
|
// dispatch state event to micro app
|
|
6538
|
+
// TODO: statechange 还是 state-change,保持一致
|
|
6436
6539
|
dispatchCustomEventToMicroApp(this, 'statechange', {
|
|
6437
6540
|
appState: appStates.LOADING
|
|
6438
6541
|
});
|
|
@@ -6456,6 +6559,14 @@ class CreateApp {
|
|
|
6456
6559
|
if (this.isPrerender &&
|
|
6457
6560
|
isDivElement(this.container) &&
|
|
6458
6561
|
this.container.hasAttribute('prerender')) {
|
|
6562
|
+
/**
|
|
6563
|
+
* current this.container is <div prerender='true'></div>
|
|
6564
|
+
* set this.container to <micro-app></micro-app>
|
|
6565
|
+
* NOTE:
|
|
6566
|
+
* 1. must exec before this.sandBox.rebuildEffectSnapshot
|
|
6567
|
+
* 2. must exec before this.preRenderEvents?.forEach((cb) => cb())
|
|
6568
|
+
*/
|
|
6569
|
+
this.container = this.cloneContainer(container, this.container, false);
|
|
6459
6570
|
/**
|
|
6460
6571
|
* rebuild effect event of window, document, data center
|
|
6461
6572
|
* explain:
|
|
@@ -6464,14 +6575,6 @@ class CreateApp {
|
|
|
6464
6575
|
* 3. rebuild after js exec end, normal recovery effect event
|
|
6465
6576
|
*/
|
|
6466
6577
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.rebuildEffectSnapshot();
|
|
6467
|
-
// current this.container is <div prerender='true'></div>
|
|
6468
|
-
this.cloneContainer(container, this.container, false);
|
|
6469
|
-
/**
|
|
6470
|
-
* set this.container to <micro-app></micro-app>
|
|
6471
|
-
* NOTE:
|
|
6472
|
-
* must exec before this.preRenderEvents?.forEach((cb) => cb())
|
|
6473
|
-
*/
|
|
6474
|
-
this.container = container;
|
|
6475
6578
|
(_b = this.preRenderEvents) === null || _b === void 0 ? void 0 : _b.forEach((cb) => cb());
|
|
6476
6579
|
// reset isPrerender config
|
|
6477
6580
|
this.isPrerender = false;
|
|
@@ -6768,6 +6871,14 @@ class CreateApp {
|
|
|
6768
6871
|
// show app when connectedCallback called with keep-alive
|
|
6769
6872
|
showKeepAliveApp(container) {
|
|
6770
6873
|
var _a, _b;
|
|
6874
|
+
/**
|
|
6875
|
+
* NOTE:
|
|
6876
|
+
* 1. this.container must set to container(micro-app element) before exec rebuildEffectSnapshot
|
|
6877
|
+
* ISSUE: https://github.com/micro-zoe/micro-app/issues/1115
|
|
6878
|
+
* 2. rebuildEffectSnapshot must exec before dispatch beforeshow event
|
|
6879
|
+
*/
|
|
6880
|
+
const oldContainer = this.container;
|
|
6881
|
+
this.container = container;
|
|
6771
6882
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.rebuildEffectSnapshot();
|
|
6772
6883
|
// dispatch beforeShow event to micro-app
|
|
6773
6884
|
dispatchCustomEventToMicroApp(this, 'appstate-change', {
|
|
@@ -6776,7 +6887,7 @@ class CreateApp {
|
|
|
6776
6887
|
// dispatch beforeShow event to base app
|
|
6777
6888
|
dispatchLifecyclesEvent(container, this.name, lifeCycles.BEFORESHOW);
|
|
6778
6889
|
this.setKeepAliveState(keepAliveStates.KEEP_ALIVE_SHOW);
|
|
6779
|
-
this.
|
|
6890
|
+
this.cloneContainer(this.container, oldContainer, false);
|
|
6780
6891
|
/**
|
|
6781
6892
|
* TODO:
|
|
6782
6893
|
* 问题:当路由模式为custom时,keep-alive应用在重新展示,是否需要根据子应用location信息更新浏览器地址?
|
|
@@ -6826,7 +6937,7 @@ class CreateApp {
|
|
|
6826
6937
|
*/
|
|
6827
6938
|
cloneContainer(target, origin, deep) {
|
|
6828
6939
|
// 在基座接受到afterhidden方法后立即执行unmount,彻底destroy应用时,因为unmount时同步执行,所以this.container为null后才执行cloneContainer
|
|
6829
|
-
if (origin) {
|
|
6940
|
+
if (origin && target) {
|
|
6830
6941
|
target.innerHTML = '';
|
|
6831
6942
|
Array.from(deep ? this.parseHtmlString(origin.innerHTML).childNodes : origin.childNodes).forEach((node) => {
|
|
6832
6943
|
target.appendChild(node);
|
|
@@ -7846,12 +7957,12 @@ function defineElement(tagName) {
|
|
|
7846
7957
|
/**
|
|
7847
7958
|
* url is different & old app is unmounted or prefetch, create new app to replace old one
|
|
7848
7959
|
*/
|
|
7849
|
-
logWarn(`the ${oldApp.isPrefetch ? 'prefetch' : 'unmounted'} app with url
|
|
7960
|
+
logWarn(`the ${oldApp.isPrefetch ? 'prefetch' : 'unmounted'} app with url ${oldAppUrl} replaced by a new app with url ${targetUrl}`, this.appName);
|
|
7850
7961
|
}
|
|
7851
7962
|
this.handleCreateApp();
|
|
7852
7963
|
}
|
|
7853
7964
|
else {
|
|
7854
|
-
logError(`app name conflict, an app named
|
|
7965
|
+
logError(`app name conflict, an app named ${this.appName} with url ${oldAppUrl} is running`);
|
|
7855
7966
|
}
|
|
7856
7967
|
}
|
|
7857
7968
|
else {
|
|
@@ -8095,6 +8206,7 @@ function defineElement(tagName) {
|
|
|
8095
8206
|
}
|
|
8096
8207
|
else {
|
|
8097
8208
|
// get path from browser URL
|
|
8209
|
+
// TODO: 新版本路由系统要重新兼容ssr
|
|
8098
8210
|
let targetPath = getNoHashMicroPathFromURL(this.appName, baseUrl);
|
|
8099
8211
|
const defaultPagePath = this.getDefaultPage();
|
|
8100
8212
|
if (!targetPath && defaultPagePath) {
|
|
@@ -8122,8 +8234,9 @@ function defineElement(tagName) {
|
|
|
8122
8234
|
* @returns router-mode
|
|
8123
8235
|
*/
|
|
8124
8236
|
getMemoryRouterMode() {
|
|
8125
|
-
return
|
|
8237
|
+
return initRouterMode(this.getAttribute('router-mode'),
|
|
8126
8238
|
// is micro-app element set disable-memory-router, like <micro-app disable-memory-router></micro-app>
|
|
8239
|
+
// or <micro-app disable-memory-router='false'></micro-app>
|
|
8127
8240
|
this.compatibleProperties('disable-memory-router') && this.compatibleDisableProperties('disable-memory-router'));
|
|
8128
8241
|
}
|
|
8129
8242
|
/**
|
|
@@ -8272,7 +8385,7 @@ function preFetchAction(options) {
|
|
|
8272
8385
|
* 问题:
|
|
8273
8386
|
* 1、如何确保子应用进行跳转时不影响到浏览器地址??pure??
|
|
8274
8387
|
*/
|
|
8275
|
-
routerMode:
|
|
8388
|
+
routerMode: initRouterMode(options['router-mode']),
|
|
8276
8389
|
baseroute: options.baseroute,
|
|
8277
8390
|
disablePatchRequest: options['disable-patch-request'],
|
|
8278
8391
|
});
|
|
@@ -8309,7 +8422,7 @@ function getGlobalAssets(assets) {
|
|
|
8309
8422
|
// TODO: requestIdleCallback for every file
|
|
8310
8423
|
function fetchGlobalResources(resources, suffix, sourceHandler) {
|
|
8311
8424
|
if (isArray(resources)) {
|
|
8312
|
-
const effectiveResource = resources.filter((path) => isString(path) && path
|
|
8425
|
+
const effectiveResource = resources.filter((path) => isString(path) && isTargetExtension(path, suffix) && !sourceHandler.hasInfo(path));
|
|
8313
8426
|
const fetchResourcePromise = effectiveResource.map((path) => fetchSource(path));
|
|
8314
8427
|
// fetch resource with stream
|
|
8315
8428
|
promiseStream(fetchResourcePromise, (res) => {
|