@micro-zoe/micro-app 1.0.0-alpha.4 → 1.0.0-alpha.7
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 +0 -4
- package/README.zh-cn.md +1 -1
- package/lib/index.d.ts +98 -29
- package/lib/index.esm.js +1316 -521
- 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 +120 -84
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-alpha.
|
|
1
|
+
const version = '1.0.0-alpha.7';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -72,6 +72,12 @@ function isShadowRoot(target) {
|
|
|
72
72
|
function isURL(target) {
|
|
73
73
|
return target instanceof URL;
|
|
74
74
|
}
|
|
75
|
+
function isElement(target) {
|
|
76
|
+
return target instanceof Element;
|
|
77
|
+
}
|
|
78
|
+
function isNode(target) {
|
|
79
|
+
return target instanceof Node;
|
|
80
|
+
}
|
|
75
81
|
// is ProxyDocument
|
|
76
82
|
function isProxyDocument(target) {
|
|
77
83
|
return toString.call(target) === '[object ProxyDocument]';
|
|
@@ -258,8 +264,19 @@ const requestIdleCallback = globalThis.requestIdleCallback ||
|
|
|
258
264
|
return Math.max(0, 50 - (Date.now() - lastTime));
|
|
259
265
|
},
|
|
260
266
|
});
|
|
261
|
-
},
|
|
267
|
+
}, 1);
|
|
262
268
|
};
|
|
269
|
+
/**
|
|
270
|
+
* Wrap requestIdleCallback with promise
|
|
271
|
+
* Exec callback when browser idle
|
|
272
|
+
*/
|
|
273
|
+
function promiseRequestIdle(callback) {
|
|
274
|
+
return new Promise((resolve) => {
|
|
275
|
+
requestIdleCallback(() => {
|
|
276
|
+
callback(resolve);
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
}
|
|
263
280
|
/**
|
|
264
281
|
* Record the currently running app.name
|
|
265
282
|
*/
|
|
@@ -433,6 +450,59 @@ function useMapRecord() {
|
|
|
433
450
|
}
|
|
434
451
|
};
|
|
435
452
|
}
|
|
453
|
+
function getAttributes(element) {
|
|
454
|
+
const attr = element.attributes;
|
|
455
|
+
const attrMap = new Map();
|
|
456
|
+
for (let i = 0; i < attr.length; i++) {
|
|
457
|
+
attrMap.set(attr[i].name, attr[i].value);
|
|
458
|
+
}
|
|
459
|
+
return attrMap;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* if fiberTasks exist, wrap callback with promiseRequestIdle
|
|
463
|
+
* if not, execute callback
|
|
464
|
+
* @param fiberTasks fiber task list
|
|
465
|
+
* @param callback action callback
|
|
466
|
+
*/
|
|
467
|
+
function injectFiberTask(fiberTasks, callback) {
|
|
468
|
+
if (fiberTasks) {
|
|
469
|
+
fiberTasks.push(() => promiseRequestIdle((resolve) => {
|
|
470
|
+
callback();
|
|
471
|
+
resolve();
|
|
472
|
+
}));
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
callback();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* serial exec fiber task of link, style, script
|
|
480
|
+
* @param tasks task array or null
|
|
481
|
+
*/
|
|
482
|
+
function serialExecFiberTasks(tasks) {
|
|
483
|
+
return (tasks === null || tasks === void 0 ? void 0 : tasks.reduce((pre, next) => pre.then(next), Promise.resolve())) || null;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* inline script start with inline-xxx
|
|
487
|
+
* @param address source address
|
|
488
|
+
*/
|
|
489
|
+
function isInlineScript(address) {
|
|
490
|
+
return address.startsWith('inline-');
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* call function with try catch
|
|
494
|
+
* @param fn target function
|
|
495
|
+
* @param appName app.name
|
|
496
|
+
* @param args arguments
|
|
497
|
+
*/
|
|
498
|
+
function callFnWithTryCatch(fn, appName, msgSuffix, ...args) {
|
|
499
|
+
try {
|
|
500
|
+
isFunction(fn) && fn(...args);
|
|
501
|
+
}
|
|
502
|
+
catch (e) {
|
|
503
|
+
logError(`an error occurred in app ${appName} ${msgSuffix} \n`, null, e);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
436
506
|
|
|
437
507
|
var ObservedAttrName;
|
|
438
508
|
(function (ObservedAttrName) {
|
|
@@ -463,12 +533,38 @@ var lifeCycles;
|
|
|
463
533
|
lifeCycles["AFTERSHOW"] = "aftershow";
|
|
464
534
|
lifeCycles["AFTERHIDDEN"] = "afterhidden";
|
|
465
535
|
})(lifeCycles || (lifeCycles = {}));
|
|
536
|
+
// global event of child app
|
|
537
|
+
var microGlobalEvent;
|
|
538
|
+
(function (microGlobalEvent) {
|
|
539
|
+
microGlobalEvent["ONMOUNT"] = "onmount";
|
|
540
|
+
microGlobalEvent["ONUNMOUNT"] = "onunmount";
|
|
541
|
+
})(microGlobalEvent || (microGlobalEvent = {}));
|
|
466
542
|
// keep-alive status
|
|
467
543
|
var keepAliveStates;
|
|
468
544
|
(function (keepAliveStates) {
|
|
469
545
|
keepAliveStates["KEEP_ALIVE_SHOW"] = "keep_alive_show";
|
|
470
546
|
keepAliveStates["KEEP_ALIVE_HIDDEN"] = "keep_alive_hidden";
|
|
471
547
|
})(keepAliveStates || (keepAliveStates = {}));
|
|
548
|
+
// micro-app config
|
|
549
|
+
var MicroAppConfig;
|
|
550
|
+
(function (MicroAppConfig) {
|
|
551
|
+
MicroAppConfig["DESTROY"] = "destroy";
|
|
552
|
+
MicroAppConfig["DESTORY"] = "destory";
|
|
553
|
+
MicroAppConfig["INLINE"] = "inline";
|
|
554
|
+
MicroAppConfig["DISABLESCOPECSS"] = "disableScopecss";
|
|
555
|
+
MicroAppConfig["DISABLESANDBOX"] = "disableSandbox";
|
|
556
|
+
MicroAppConfig["DISABLE_SCOPECSS"] = "disable-scopecss";
|
|
557
|
+
MicroAppConfig["DISABLE_SANDBOX"] = "disable-sandbox";
|
|
558
|
+
MicroAppConfig["DISABLE_MEMORY_ROUTER"] = "disable-memory-router";
|
|
559
|
+
MicroAppConfig["DISABLE_PATCH_REQUEST"] = "disable-patch-request";
|
|
560
|
+
MicroAppConfig["KEEP_ROUTER_STATE"] = "keep-router-state";
|
|
561
|
+
MicroAppConfig["HIDDEN_ROUTER"] = "hidden-router";
|
|
562
|
+
MicroAppConfig["KEEP_ALIVE"] = "keep-alive";
|
|
563
|
+
MicroAppConfig["CLEAR_DATA"] = "clear-data";
|
|
564
|
+
MicroAppConfig["ESMODULE"] = "esmodule";
|
|
565
|
+
MicroAppConfig["SSR"] = "ssr";
|
|
566
|
+
MicroAppConfig["FIBER"] = "fiber";
|
|
567
|
+
})(MicroAppConfig || (MicroAppConfig = {}));
|
|
472
568
|
/**
|
|
473
569
|
* global key must be static key, they can not rewrite
|
|
474
570
|
* e.g.
|
|
@@ -493,8 +589,8 @@ function fetchSource(url, appName = null, options = {}) {
|
|
|
493
589
|
* baseApp: <script crossorigin src="https://sgm-static.jd.com/sgm-2.8.0.js" name="SGMH5" sid="6f88a6e4ba4b4ae5acef2ec22c075085" appKey="jdb-adminb2b-pc"></script>
|
|
494
590
|
*/
|
|
495
591
|
removeDomScope();
|
|
496
|
-
if (isFunction(microApp.fetch)) {
|
|
497
|
-
return microApp.fetch(url, options, appName);
|
|
592
|
+
if (isFunction(microApp.options.fetch)) {
|
|
593
|
+
return microApp.options.fetch(url, options, appName);
|
|
498
594
|
}
|
|
499
595
|
// Don’t use globalEnv.rawWindow.fetch, will cause sgm-2.8.0.js throw error in nest app
|
|
500
596
|
return window.fetch(url, options).then((res) => {
|
|
@@ -531,7 +627,7 @@ class HTMLLoader {
|
|
|
531
627
|
});
|
|
532
628
|
}
|
|
533
629
|
formatHTML(htmlUrl, htmlStr, appName) {
|
|
534
|
-
return this.processHtml(htmlUrl, htmlStr, appName, microApp.plugins)
|
|
630
|
+
return this.processHtml(htmlUrl, htmlStr, appName, microApp.options.plugins)
|
|
535
631
|
.replace(/<head[^>]*>[\s\S]*?<\/head>/i, (match) => {
|
|
536
632
|
return match
|
|
537
633
|
.replace(/<head/i, '<micro-app-head')
|
|
@@ -553,7 +649,7 @@ class HTMLLoader {
|
|
|
553
649
|
if (mergedPlugins.length > 0) {
|
|
554
650
|
return mergedPlugins.reduce((preCode, plugin) => {
|
|
555
651
|
if (isPlainObject(plugin) && isFunction(plugin.processHtml)) {
|
|
556
|
-
return plugin.processHtml(preCode, url
|
|
652
|
+
return plugin.processHtml(preCode, url);
|
|
557
653
|
}
|
|
558
654
|
return preCode;
|
|
559
655
|
}, code);
|
|
@@ -591,11 +687,13 @@ class CSSParser {
|
|
|
591
687
|
this.scopecssDisableSelectors = []; // disable or enable scopecss for specific selectors
|
|
592
688
|
this.scopecssDisableNextLine = false; // use block comments /* scopecss-disable-next-line */ to disable scopecss on a specific line
|
|
593
689
|
// https://developer.mozilla.org/en-US/docs/Web/API/CSSMediaRule
|
|
594
|
-
this.mediaRule = this.
|
|
690
|
+
this.mediaRule = this.createMatcherForRuleWithChildRule(/^@media *([^{]+)/, '@media');
|
|
595
691
|
// https://developer.mozilla.org/en-US/docs/Web/API/CSSSupportsRule
|
|
596
|
-
this.supportsRule = this.
|
|
597
|
-
this.documentRule = this.
|
|
598
|
-
this.hostRule = this.
|
|
692
|
+
this.supportsRule = this.createMatcherForRuleWithChildRule(/^@supports *([^{]+)/, '@supports');
|
|
693
|
+
this.documentRule = this.createMatcherForRuleWithChildRule(/^@([-\w]+)?document *([^{]+)/, '@document');
|
|
694
|
+
this.hostRule = this.createMatcherForRuleWithChildRule(/^@host\s*/, '@host');
|
|
695
|
+
// :global is CSS Modules rule, it will be converted to normal syntax
|
|
696
|
+
// private globalRule = this.createMatcherForRuleWithChildRule(/^:global([^{]*)/, ':global')
|
|
599
697
|
// https://developer.mozilla.org/en-US/docs/Web/API/CSSImportRule
|
|
600
698
|
this.importRule = this.createMatcherForNoneBraceAtRule('import');
|
|
601
699
|
// Removed in most browsers
|
|
@@ -716,6 +814,13 @@ class CSSParser {
|
|
|
716
814
|
this.hostRule() ||
|
|
717
815
|
this.fontFaceRule();
|
|
718
816
|
}
|
|
817
|
+
// :global is CSS Modules rule, it will be converted to normal syntax
|
|
818
|
+
// private matchGlobalRule (): boolean | void {
|
|
819
|
+
// if (this.cssText[0] !== ':') return false
|
|
820
|
+
// // reset scopecssDisableNextLine
|
|
821
|
+
// this.scopecssDisableNextLine = false
|
|
822
|
+
// return this.globalRule()
|
|
823
|
+
// }
|
|
719
824
|
// https://developer.mozilla.org/en-US/docs/Web/API/CSSKeyframesRule
|
|
720
825
|
keyframesRule() {
|
|
721
826
|
if (!this.commonMatch(/^@([-\w]+)?keyframes\s*/))
|
|
@@ -769,17 +874,17 @@ class CSSParser {
|
|
|
769
874
|
return false;
|
|
770
875
|
return this.commonHandlerForAtRuleWithSelfRule('font-face');
|
|
771
876
|
}
|
|
772
|
-
// common matcher for @media, @supports, @document, @host
|
|
773
|
-
|
|
877
|
+
// common matcher for @media, @supports, @document, @host, :global
|
|
878
|
+
createMatcherForRuleWithChildRule(reg, name) {
|
|
774
879
|
return () => {
|
|
775
880
|
if (!this.commonMatch(reg))
|
|
776
881
|
return false;
|
|
777
882
|
if (!this.matchOpenBrace())
|
|
778
|
-
return parseError(
|
|
883
|
+
return parseError(`${name} missing '{'`, this.linkPath);
|
|
779
884
|
this.matchComments();
|
|
780
885
|
this.matchRules();
|
|
781
886
|
if (!this.matchCloseBrace())
|
|
782
|
-
return parseError(
|
|
887
|
+
return parseError(`${name} missing '}'`, this.linkPath);
|
|
783
888
|
this.matchLeadingSpaces();
|
|
784
889
|
return true;
|
|
785
890
|
};
|
|
@@ -906,20 +1011,20 @@ let parser;
|
|
|
906
1011
|
* @param styleElement target style element
|
|
907
1012
|
* @param appName app name
|
|
908
1013
|
*/
|
|
909
|
-
function scopedCSS(styleElement, app) {
|
|
1014
|
+
function scopedCSS(styleElement, app, linkPath) {
|
|
910
1015
|
if (app.scopecss) {
|
|
911
|
-
const prefix =
|
|
1016
|
+
const prefix = createPrefix(app.name);
|
|
912
1017
|
if (!parser)
|
|
913
1018
|
parser = new CSSParser();
|
|
914
1019
|
if (styleElement.textContent) {
|
|
915
|
-
commonAction(styleElement, app.name, prefix, app.url,
|
|
1020
|
+
commonAction(styleElement, app.name, prefix, app.url, linkPath);
|
|
916
1021
|
}
|
|
917
1022
|
else {
|
|
918
1023
|
const observer = new MutationObserver(function () {
|
|
919
1024
|
observer.disconnect();
|
|
920
1025
|
// styled-component will be ignore
|
|
921
1026
|
if (styleElement.textContent && !styleElement.hasAttribute('data-styled')) {
|
|
922
|
-
commonAction(styleElement, app.name, prefix, app.url,
|
|
1027
|
+
commonAction(styleElement, app.name, prefix, app.url, linkPath);
|
|
923
1028
|
}
|
|
924
1029
|
});
|
|
925
1030
|
observer.observe(styleElement, { childList: true });
|
|
@@ -927,6 +1032,10 @@ function scopedCSS(styleElement, app) {
|
|
|
927
1032
|
}
|
|
928
1033
|
return styleElement;
|
|
929
1034
|
}
|
|
1035
|
+
function createPrefix(appName, reg = false) {
|
|
1036
|
+
const regCharacter = reg ? '\\' : '';
|
|
1037
|
+
return `${microApp.tagName}${regCharacter}[name=${appName}${regCharacter}]`;
|
|
1038
|
+
}
|
|
930
1039
|
|
|
931
1040
|
function eventHandler(event, element) {
|
|
932
1041
|
Object.defineProperties(event, {
|
|
@@ -968,8 +1077,76 @@ function dispatchOnErrorEvent(element) {
|
|
|
968
1077
|
}
|
|
969
1078
|
}
|
|
970
1079
|
|
|
971
|
-
|
|
972
|
-
|
|
1080
|
+
/**
|
|
1081
|
+
* SourceCenter is a resource management center
|
|
1082
|
+
* All html, js, css will be recorded and processed here
|
|
1083
|
+
* NOTE:
|
|
1084
|
+
* 1. All resources are global and shared between apps
|
|
1085
|
+
* 2. Pay attention to the case of html with parameters
|
|
1086
|
+
* 3. The resource is first processed by the plugin
|
|
1087
|
+
*/
|
|
1088
|
+
function createSourceCenter() {
|
|
1089
|
+
const linkList = new Map();
|
|
1090
|
+
const scriptList = new Map();
|
|
1091
|
+
// setInterval(() => {
|
|
1092
|
+
// console.log(linkList, scriptList)
|
|
1093
|
+
// }, 10000);
|
|
1094
|
+
function createSourceHandler(targetList) {
|
|
1095
|
+
return {
|
|
1096
|
+
setInfo(address, info) {
|
|
1097
|
+
targetList.set(address, info);
|
|
1098
|
+
},
|
|
1099
|
+
getInfo(address) {
|
|
1100
|
+
var _a;
|
|
1101
|
+
return (_a = targetList.get(address)) !== null && _a !== void 0 ? _a : null;
|
|
1102
|
+
},
|
|
1103
|
+
hasInfo(address) {
|
|
1104
|
+
return targetList.has(address);
|
|
1105
|
+
},
|
|
1106
|
+
deleteInfo(address) {
|
|
1107
|
+
return targetList.delete(address);
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
return {
|
|
1112
|
+
link: createSourceHandler(linkList),
|
|
1113
|
+
script: Object.assign(Object.assign({}, createSourceHandler(scriptList)), { deleteInlineInfo(addressList) {
|
|
1114
|
+
addressList.forEach((address) => {
|
|
1115
|
+
if (isInlineScript(address)) {
|
|
1116
|
+
scriptList.delete(address);
|
|
1117
|
+
}
|
|
1118
|
+
});
|
|
1119
|
+
} }),
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
var sourceCenter = createSourceCenter();
|
|
1123
|
+
|
|
1124
|
+
/**
|
|
1125
|
+
*
|
|
1126
|
+
* @param appName app.name
|
|
1127
|
+
* @param linkInfo linkInfo of current address
|
|
1128
|
+
*/
|
|
1129
|
+
function getExistParseCode(appName, prefix, linkInfo) {
|
|
1130
|
+
const appSpace = linkInfo.appSpace;
|
|
1131
|
+
for (const item in appSpace) {
|
|
1132
|
+
if (item !== appName) {
|
|
1133
|
+
const appSpaceData = appSpace[item];
|
|
1134
|
+
if (appSpaceData.parsedCode) {
|
|
1135
|
+
return appSpaceData.parsedCode.replaceAll(new RegExp(createPrefix(item, true), 'g'), prefix);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
// transfer the attributes on the link to convertStyle
|
|
1141
|
+
function setConvertStyleAttr(convertStyle, attrs) {
|
|
1142
|
+
attrs.forEach((value, key) => {
|
|
1143
|
+
if (key === 'rel')
|
|
1144
|
+
return;
|
|
1145
|
+
if (key === 'href')
|
|
1146
|
+
key = 'data-origin-href';
|
|
1147
|
+
convertStyle.setAttribute(key, value);
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
973
1150
|
/**
|
|
974
1151
|
* Extract link elements
|
|
975
1152
|
* @param link link element
|
|
@@ -984,22 +1161,29 @@ function extractLinkFromHtml(link, parent, app, isDynamic = false) {
|
|
|
984
1161
|
let replaceComment = null;
|
|
985
1162
|
if (rel === 'stylesheet' && href) {
|
|
986
1163
|
href = CompletionPath(href, app.url);
|
|
1164
|
+
let linkInfo = sourceCenter.link.getInfo(href);
|
|
1165
|
+
const appSpaceData = {
|
|
1166
|
+
attrs: getAttributes(link),
|
|
1167
|
+
};
|
|
1168
|
+
if (!linkInfo) {
|
|
1169
|
+
linkInfo = {
|
|
1170
|
+
code: '',
|
|
1171
|
+
appSpace: {
|
|
1172
|
+
[app.name]: appSpaceData,
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
else {
|
|
1177
|
+
linkInfo.appSpace[app.name] = linkInfo.appSpace[app.name] || appSpaceData;
|
|
1178
|
+
}
|
|
1179
|
+
sourceCenter.link.setInfo(href, linkInfo);
|
|
987
1180
|
if (!isDynamic) {
|
|
1181
|
+
app.source.links.add(href);
|
|
988
1182
|
replaceComment = document.createComment(`link element with href=${href} move to micro-app-head as style element`);
|
|
989
|
-
app.
|
|
990
|
-
code: '',
|
|
991
|
-
placeholder: replaceComment,
|
|
992
|
-
isGlobal: link.hasAttribute('global'),
|
|
993
|
-
});
|
|
1183
|
+
linkInfo.appSpace[app.name].placeholder = replaceComment;
|
|
994
1184
|
}
|
|
995
1185
|
else {
|
|
996
|
-
return {
|
|
997
|
-
url: href,
|
|
998
|
-
info: {
|
|
999
|
-
code: '',
|
|
1000
|
-
isGlobal: link.hasAttribute('global'),
|
|
1001
|
-
}
|
|
1002
|
-
};
|
|
1186
|
+
return { address: href, linkInfo };
|
|
1003
1187
|
}
|
|
1004
1188
|
}
|
|
1005
1189
|
else if (rel && ['prefetch', 'preload', 'prerender', 'icon', 'apple-touch-icon'].includes(rel)) {
|
|
@@ -1028,79 +1212,138 @@ function extractLinkFromHtml(link, parent, app, isDynamic = false) {
|
|
|
1028
1212
|
* @param app app
|
|
1029
1213
|
* @param microAppHead micro-app-head
|
|
1030
1214
|
*/
|
|
1031
|
-
function fetchLinksFromHtml(wrapElement, app, microAppHead) {
|
|
1032
|
-
const
|
|
1033
|
-
const fetchLinkPromise =
|
|
1034
|
-
|
|
1215
|
+
function fetchLinksFromHtml(wrapElement, app, microAppHead, fiberStyleResult) {
|
|
1216
|
+
const styleList = Array.from(app.source.links);
|
|
1217
|
+
const fetchLinkPromise = styleList.map((address) => {
|
|
1218
|
+
const linkInfo = sourceCenter.link.getInfo(address);
|
|
1219
|
+
return linkInfo.code ? linkInfo.code : fetchSource(address, app.name);
|
|
1035
1220
|
});
|
|
1221
|
+
const fiberLinkTasks = app.isPrefetch || app.fiber ? [] : null;
|
|
1036
1222
|
promiseStream(fetchLinkPromise, (res) => {
|
|
1037
|
-
|
|
1223
|
+
injectFiberTask(fiberLinkTasks, () => fetchLinkSuccess(styleList[res.index], res.data, microAppHead, app));
|
|
1038
1224
|
}, (err) => {
|
|
1039
1225
|
logError(err, app.name);
|
|
1040
1226
|
}, () => {
|
|
1041
|
-
|
|
1227
|
+
if (fiberLinkTasks) {
|
|
1228
|
+
/**
|
|
1229
|
+
* 1. If fiberLinkTasks is not null, fiberStyleResult is not null
|
|
1230
|
+
* 2. Download link source while processing style
|
|
1231
|
+
* 3. Process style first, and then process link
|
|
1232
|
+
*/
|
|
1233
|
+
fiberStyleResult.then(() => {
|
|
1234
|
+
fiberLinkTasks.push(() => Promise.resolve(app.onLoad(wrapElement)));
|
|
1235
|
+
serialExecFiberTasks(fiberLinkTasks);
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
app.onLoad(wrapElement);
|
|
1240
|
+
}
|
|
1042
1241
|
});
|
|
1043
1242
|
}
|
|
1044
1243
|
/**
|
|
1045
|
-
*
|
|
1046
|
-
*
|
|
1047
|
-
*
|
|
1048
|
-
*
|
|
1244
|
+
* Fetch link succeeded, replace placeholder with style tag
|
|
1245
|
+
* NOTE:
|
|
1246
|
+
* 1. Only exec when init, no longer exec when remount
|
|
1247
|
+
* 2. Only handler html link element, not dynamic link or style
|
|
1248
|
+
* 3. The same prefix can reuse parsedCode
|
|
1249
|
+
* 4. Async exec with requestIdleCallback in prefetch or fiber
|
|
1250
|
+
* 5. appSpace[app.name].placeholder/attrs must exist
|
|
1251
|
+
* @param address resource address
|
|
1252
|
+
* @param code link source code
|
|
1049
1253
|
* @param microAppHead micro-app-head
|
|
1050
|
-
* @param app app
|
|
1254
|
+
* @param app app instance
|
|
1051
1255
|
*/
|
|
1052
|
-
function fetchLinkSuccess(
|
|
1053
|
-
|
|
1054
|
-
|
|
1256
|
+
function fetchLinkSuccess(address, code, microAppHead, app) {
|
|
1257
|
+
/**
|
|
1258
|
+
* linkInfo must exist, but linkInfo.code not
|
|
1259
|
+
* so we set code to linkInfo.code
|
|
1260
|
+
*/
|
|
1261
|
+
const linkInfo = sourceCenter.link.getInfo(address);
|
|
1262
|
+
linkInfo.code = code;
|
|
1263
|
+
const appSpaceData = linkInfo.appSpace[app.name];
|
|
1264
|
+
const placeholder = appSpaceData.placeholder;
|
|
1265
|
+
/**
|
|
1266
|
+
* When prefetch app is replaced by a new app in the processing phase, since the linkInfo is common, when the linkInfo of the prefetch app is processed, it may have already been processed.
|
|
1267
|
+
* This causes placeholder to be possibly null
|
|
1268
|
+
* e.g.
|
|
1269
|
+
* 1. prefetch app.url different from <micro-app></micro-app>
|
|
1270
|
+
* 2. prefetch param different from <micro-app></micro-app>
|
|
1271
|
+
*/
|
|
1272
|
+
if (placeholder) {
|
|
1273
|
+
const convertStyle = pureCreateElement('style');
|
|
1274
|
+
handleConvertStyle(app, address, convertStyle, linkInfo, appSpaceData.attrs);
|
|
1275
|
+
if (placeholder.parentNode) {
|
|
1276
|
+
placeholder.parentNode.replaceChild(convertStyle, placeholder);
|
|
1277
|
+
}
|
|
1278
|
+
else {
|
|
1279
|
+
microAppHead.appendChild(convertStyle);
|
|
1280
|
+
}
|
|
1281
|
+
// clear placeholder
|
|
1282
|
+
appSpaceData.placeholder = null;
|
|
1055
1283
|
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Get parsedCode, update convertStyle
|
|
1287
|
+
* Actions:
|
|
1288
|
+
* 1. get scope css (through scopedCSS or oldData)
|
|
1289
|
+
* 2. record parsedCode
|
|
1290
|
+
* 3. set parsedCode to convertStyle if need
|
|
1291
|
+
* @param app app instance
|
|
1292
|
+
* @param address resource address
|
|
1293
|
+
* @param convertStyle converted style
|
|
1294
|
+
* @param linkInfo linkInfo in sourceCenter
|
|
1295
|
+
* @param attrs attrs of link
|
|
1296
|
+
*/
|
|
1297
|
+
function handleConvertStyle(app, address, convertStyle, linkInfo, attrs) {
|
|
1298
|
+
if (app.scopecss) {
|
|
1299
|
+
const appSpaceData = linkInfo.appSpace[app.name];
|
|
1300
|
+
appSpaceData.prefix = appSpaceData.prefix || createPrefix(app.name);
|
|
1301
|
+
if (!appSpaceData.parsedCode) {
|
|
1302
|
+
const existParsedCode = getExistParseCode(app.name, appSpaceData.prefix, linkInfo);
|
|
1303
|
+
if (!existParsedCode) {
|
|
1304
|
+
convertStyle.textContent = linkInfo.code;
|
|
1305
|
+
scopedCSS(convertStyle, app, address);
|
|
1306
|
+
}
|
|
1307
|
+
else {
|
|
1308
|
+
convertStyle.textContent = existParsedCode;
|
|
1309
|
+
}
|
|
1310
|
+
appSpaceData.parsedCode = convertStyle.textContent;
|
|
1311
|
+
}
|
|
1312
|
+
else {
|
|
1313
|
+
convertStyle.textContent = appSpaceData.parsedCode;
|
|
1314
|
+
}
|
|
1062
1315
|
}
|
|
1063
1316
|
else {
|
|
1064
|
-
|
|
1317
|
+
convertStyle.textContent = linkInfo.code;
|
|
1065
1318
|
}
|
|
1066
|
-
|
|
1067
|
-
info.code = data;
|
|
1319
|
+
setConvertStyleAttr(convertStyle, attrs);
|
|
1068
1320
|
}
|
|
1069
1321
|
/**
|
|
1070
|
-
*
|
|
1071
|
-
* @param
|
|
1072
|
-
* @param info info
|
|
1322
|
+
* Handle css of dynamic link
|
|
1323
|
+
* @param address link address
|
|
1073
1324
|
* @param app app
|
|
1325
|
+
* @param linkInfo linkInfo
|
|
1074
1326
|
* @param originLink origin link element
|
|
1075
|
-
* @param replaceStyle style element which replaced origin link
|
|
1076
1327
|
*/
|
|
1077
|
-
function formatDynamicLink(
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1328
|
+
function formatDynamicLink(address, app, linkInfo, originLink) {
|
|
1329
|
+
const convertStyle = pureCreateElement('style');
|
|
1330
|
+
const handleDynamicLink = () => {
|
|
1331
|
+
handleConvertStyle(app, address, convertStyle, linkInfo, linkInfo.appSpace[app.name].attrs);
|
|
1332
|
+
dispatchOnLoadEvent(originLink);
|
|
1333
|
+
};
|
|
1334
|
+
if (linkInfo.code) {
|
|
1335
|
+
defer(handleDynamicLink);
|
|
1083
1336
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1337
|
+
else {
|
|
1338
|
+
fetchSource(address, app.name).then((data) => {
|
|
1339
|
+
linkInfo.code = data;
|
|
1340
|
+
handleDynamicLink();
|
|
1341
|
+
}).catch((err) => {
|
|
1342
|
+
logError(err, app.name);
|
|
1343
|
+
dispatchOnErrorEvent(originLink);
|
|
1344
|
+
});
|
|
1092
1345
|
}
|
|
1093
|
-
|
|
1094
|
-
info.code = data;
|
|
1095
|
-
app.source.links.set(url, info);
|
|
1096
|
-
info.isGlobal && globalLinks.set(url, data);
|
|
1097
|
-
replaceStyle.textContent = data;
|
|
1098
|
-
scopedCSS(replaceStyle, app);
|
|
1099
|
-
dispatchOnLoadEvent(originLink);
|
|
1100
|
-
}).catch((err) => {
|
|
1101
|
-
logError(err, app.name);
|
|
1102
|
-
dispatchOnErrorEvent(originLink);
|
|
1103
|
-
});
|
|
1346
|
+
return convertStyle;
|
|
1104
1347
|
}
|
|
1105
1348
|
|
|
1106
1349
|
class Adapter {
|
|
@@ -1169,17 +1412,25 @@ function fixReactHMRConflict(app) {
|
|
|
1169
1412
|
function throttleDeferForParentNode(proxyDocument) {
|
|
1170
1413
|
const html = globalEnv.rawDocument.firstElementChild;
|
|
1171
1414
|
if (html && html.parentNode !== proxyDocument) {
|
|
1172
|
-
|
|
1415
|
+
setParentNode(html, proxyDocument);
|
|
1173
1416
|
defer(() => {
|
|
1174
|
-
|
|
1417
|
+
setParentNode(html, globalEnv.rawDocument);
|
|
1175
1418
|
});
|
|
1176
1419
|
}
|
|
1177
1420
|
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1421
|
+
/**
|
|
1422
|
+
* Modify the point of parentNode
|
|
1423
|
+
* @param target target Node
|
|
1424
|
+
* @param value parentNode
|
|
1425
|
+
*/
|
|
1426
|
+
function setParentNode(target, value) {
|
|
1427
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, 'parentNode');
|
|
1428
|
+
if (!descriptor || descriptor.configurable) {
|
|
1429
|
+
rawDefineProperty(target, 'parentNode', {
|
|
1430
|
+
value,
|
|
1431
|
+
configurable: true,
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1183
1434
|
}
|
|
1184
1435
|
|
|
1185
1436
|
// Record element and map element
|
|
@@ -1208,14 +1459,16 @@ function handleNewNode(parent, child, app) {
|
|
|
1208
1459
|
dynamicElementInMicroAppMap.set(child, linkReplaceComment);
|
|
1209
1460
|
return linkReplaceComment;
|
|
1210
1461
|
}
|
|
1211
|
-
else if (child.hasAttribute('ignore') ||
|
|
1462
|
+
else if (child.hasAttribute('ignore') ||
|
|
1463
|
+
checkIgnoreUrl(child.getAttribute('href'), app.name) ||
|
|
1464
|
+
(child.href &&
|
|
1465
|
+
isFunction(microApp.options.excludeAssetFilter) &&
|
|
1466
|
+
microApp.options.excludeAssetFilter(child.href))) {
|
|
1212
1467
|
return child;
|
|
1213
1468
|
}
|
|
1214
|
-
const {
|
|
1215
|
-
if (
|
|
1216
|
-
const replaceStyle =
|
|
1217
|
-
replaceStyle.__MICRO_APP_LINK_PATH__ = url;
|
|
1218
|
-
formatDynamicLink(url, info, app, child, replaceStyle);
|
|
1469
|
+
const { address, linkInfo, replaceComment } = extractLinkFromHtml(child, parent, app, true);
|
|
1470
|
+
if (address && linkInfo) {
|
|
1471
|
+
const replaceStyle = formatDynamicLink(address, app, linkInfo, child);
|
|
1219
1472
|
dynamicElementInMicroAppMap.set(child, replaceStyle);
|
|
1220
1473
|
return replaceStyle;
|
|
1221
1474
|
}
|
|
@@ -1226,18 +1479,17 @@ function handleNewNode(parent, child, app) {
|
|
|
1226
1479
|
return child;
|
|
1227
1480
|
}
|
|
1228
1481
|
else if (child instanceof HTMLScriptElement) {
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
}
|
|
1482
|
+
if (child.src &&
|
|
1483
|
+
isFunction(microApp.options.excludeAssetFilter) &&
|
|
1484
|
+
microApp.options.excludeAssetFilter(child.src)) {
|
|
1485
|
+
return child;
|
|
1486
|
+
}
|
|
1487
|
+
const { replaceComment, address, scriptInfo } = extractScriptElement(child, parent, app, true) || {};
|
|
1488
|
+
if (address && scriptInfo) {
|
|
1489
|
+
// remote script or inline script
|
|
1490
|
+
const replaceElement = scriptInfo.isExternal ? runDynamicRemoteScript(address, app, scriptInfo, child) : runDynamicInlineScript(address, app, scriptInfo);
|
|
1491
|
+
dynamicElementInMicroAppMap.set(child, replaceElement);
|
|
1492
|
+
return replaceElement;
|
|
1241
1493
|
}
|
|
1242
1494
|
else if (replaceComment) {
|
|
1243
1495
|
dynamicElementInMicroAppMap.set(child, replaceComment);
|
|
@@ -1256,20 +1508,40 @@ function handleNewNode(parent, child, app) {
|
|
|
1256
1508
|
* @param passiveChild second param of insertBefore and replaceChild
|
|
1257
1509
|
*/
|
|
1258
1510
|
function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild) {
|
|
1259
|
-
const
|
|
1511
|
+
const hijackParent = getHijackParent(parent, app);
|
|
1260
1512
|
/**
|
|
1261
1513
|
* If passiveChild is not the child node, insertBefore replaceChild will have a problem, at this time, it will be degraded to appendChild
|
|
1262
1514
|
* E.g: document.head.insertBefore(targetChild, document.head.childNodes[0])
|
|
1263
1515
|
*/
|
|
1264
|
-
if (
|
|
1516
|
+
if (hijackParent) {
|
|
1517
|
+
/**
|
|
1518
|
+
* WARNING:
|
|
1519
|
+
* Verifying that the parentNode of the targetChild points to document.body will cause other problems ?
|
|
1520
|
+
*/
|
|
1521
|
+
if (hijackParent.tagName === 'MICRO-APP-BODY' && rawMethod !== globalEnv.rawRemoveChild) {
|
|
1522
|
+
const descriptor = Object.getOwnPropertyDescriptor(targetChild, 'parentNode');
|
|
1523
|
+
if (!descriptor || descriptor.configurable) {
|
|
1524
|
+
rawDefineProperty(targetChild, 'parentNode', {
|
|
1525
|
+
configurable: true,
|
|
1526
|
+
get() {
|
|
1527
|
+
/**
|
|
1528
|
+
* When operate child from parentNode async, Element.prototype may reset
|
|
1529
|
+
* e.g.
|
|
1530
|
+
* target.parentNode.remove(target)
|
|
1531
|
+
*/
|
|
1532
|
+
return Element.prototype.removeChild === globalEnv.rawRemoveChild ? hijackParent : document.body;
|
|
1533
|
+
},
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1265
1537
|
/**
|
|
1266
1538
|
* 1. If passiveChild exists, it must be insertBefore or replaceChild
|
|
1267
1539
|
* 2. When removeChild, targetChild may not be in microAppHead or head
|
|
1268
1540
|
*/
|
|
1269
|
-
if (passiveChild && !
|
|
1270
|
-
return globalEnv.rawAppendChild.call(
|
|
1541
|
+
if (passiveChild && !hijackParent.contains(passiveChild)) {
|
|
1542
|
+
return globalEnv.rawAppendChild.call(hijackParent, targetChild);
|
|
1271
1543
|
}
|
|
1272
|
-
else if (rawMethod === globalEnv.rawRemoveChild && !
|
|
1544
|
+
else if (rawMethod === globalEnv.rawRemoveChild && !hijackParent.contains(targetChild)) {
|
|
1273
1545
|
if (parent.contains(targetChild)) {
|
|
1274
1546
|
return rawMethod.call(parent, targetChild);
|
|
1275
1547
|
}
|
|
@@ -1281,12 +1553,12 @@ function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild
|
|
|
1281
1553
|
rawMethod === globalEnv.rawAppendChild) {
|
|
1282
1554
|
fixReactHMRConflict(app);
|
|
1283
1555
|
}
|
|
1284
|
-
return invokeRawMethod(rawMethod,
|
|
1556
|
+
return invokeRawMethod(rawMethod, hijackParent, targetChild, passiveChild);
|
|
1285
1557
|
}
|
|
1286
1558
|
return invokeRawMethod(rawMethod, parent, targetChild, passiveChild);
|
|
1287
1559
|
}
|
|
1288
1560
|
// head/body map to micro-app-head/micro-app-body
|
|
1289
|
-
function
|
|
1561
|
+
function getHijackParent(node, app) {
|
|
1290
1562
|
var _a, _b;
|
|
1291
1563
|
if (node === document.head) {
|
|
1292
1564
|
return (_a = app === null || app === void 0 ? void 0 : app.container) === null || _a === void 0 ? void 0 : _a.querySelector('micro-app-head');
|
|
@@ -1319,13 +1591,13 @@ function getMappingNode(node) {
|
|
|
1319
1591
|
*/
|
|
1320
1592
|
function commonElementHandler(parent, newChild, passiveChild, rawMethod) {
|
|
1321
1593
|
const currentAppName = getCurrentAppName();
|
|
1322
|
-
if (newChild
|
|
1594
|
+
if (isNode(newChild) &&
|
|
1323
1595
|
(newChild.__MICRO_APP_NAME__ ||
|
|
1324
1596
|
(currentAppName && !newChild.__PURE_ELEMENT__))) {
|
|
1325
1597
|
newChild.__MICRO_APP_NAME__ = newChild.__MICRO_APP_NAME__ || currentAppName;
|
|
1326
1598
|
const app = appInstanceMap.get(newChild.__MICRO_APP_NAME__);
|
|
1327
1599
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1328
|
-
if (newChild
|
|
1600
|
+
if (isElement(newChild)) {
|
|
1329
1601
|
if (/^(img|script)$/i.test(newChild.tagName)) {
|
|
1330
1602
|
if (newChild.hasAttribute('src')) {
|
|
1331
1603
|
globalEnv.rawSetAttribute.call(newChild, 'src', CompletionPath(newChild.getAttribute('src'), app.url));
|
|
@@ -1345,7 +1617,7 @@ function commonElementHandler(parent, newChild, passiveChild, rawMethod) {
|
|
|
1345
1617
|
}
|
|
1346
1618
|
}
|
|
1347
1619
|
else if (rawMethod === globalEnv.rawAppend || rawMethod === globalEnv.rawPrepend) {
|
|
1348
|
-
if (!(newChild
|
|
1620
|
+
if (!isNode(newChild) && currentAppName) {
|
|
1349
1621
|
const app = appInstanceMap.get(currentAppName);
|
|
1350
1622
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1351
1623
|
if (parent === document.head) {
|
|
@@ -1705,8 +1977,80 @@ function initGlobalEnv() {
|
|
|
1705
1977
|
}
|
|
1706
1978
|
}
|
|
1707
1979
|
|
|
1708
|
-
|
|
1709
|
-
|
|
1980
|
+
const scriptTypes = ['text/javascript', 'text/ecmascript', 'application/javascript', 'application/ecmascript', 'module', 'systemjs-module', 'systemjs-importmap'];
|
|
1981
|
+
// whether use type='module' script
|
|
1982
|
+
function isTypeModule(app, scriptInfo) {
|
|
1983
|
+
return scriptInfo.appSpace[app.name].module && (!app.useSandbox || app.esmodule);
|
|
1984
|
+
}
|
|
1985
|
+
// special script element
|
|
1986
|
+
function isSpecialScript(app, scriptInfo) {
|
|
1987
|
+
const attrs = scriptInfo.appSpace[app.name].attrs;
|
|
1988
|
+
return attrs.has('id');
|
|
1989
|
+
}
|
|
1990
|
+
/**
|
|
1991
|
+
* whether to run js in inline mode
|
|
1992
|
+
* scene:
|
|
1993
|
+
* 1. inline config for app
|
|
1994
|
+
* 2. inline attr in script element
|
|
1995
|
+
* 3. module script
|
|
1996
|
+
* 4. script with special attr
|
|
1997
|
+
*/
|
|
1998
|
+
function isInlineMode(app, scriptInfo) {
|
|
1999
|
+
return (app.inline ||
|
|
2000
|
+
scriptInfo.appSpace[app.name].inline ||
|
|
2001
|
+
isTypeModule(app, scriptInfo) ||
|
|
2002
|
+
isSpecialScript(app, scriptInfo));
|
|
2003
|
+
}
|
|
2004
|
+
// Convert string code to function
|
|
2005
|
+
function code2Function(code) {
|
|
2006
|
+
return new Function(code);
|
|
2007
|
+
}
|
|
2008
|
+
/**
|
|
2009
|
+
* If the appSpace of the current js address has other app, try to reuse parsedFunction of other app
|
|
2010
|
+
* @param appName app.name
|
|
2011
|
+
* @param scriptInfo scriptInfo of current address
|
|
2012
|
+
* @param currentCode pure code of current address
|
|
2013
|
+
*/
|
|
2014
|
+
function getExistParseResult(appName, scriptInfo, currentCode) {
|
|
2015
|
+
const appSpace = scriptInfo.appSpace;
|
|
2016
|
+
for (const item in appSpace) {
|
|
2017
|
+
if (item !== appName) {
|
|
2018
|
+
const appSpaceData = appSpace[item];
|
|
2019
|
+
if (appSpaceData.parsedCode === currentCode && appSpaceData.parsedFunction) {
|
|
2020
|
+
return appSpaceData.parsedFunction;
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
/**
|
|
2026
|
+
* get parsedFunction from exist data or parsedCode
|
|
2027
|
+
* @returns parsedFunction
|
|
2028
|
+
*/
|
|
2029
|
+
function getParsedFunction(app, scriptInfo, parsedCode) {
|
|
2030
|
+
return getExistParseResult(app.name, scriptInfo, parsedCode) || code2Function(parsedCode);
|
|
2031
|
+
}
|
|
2032
|
+
// Prevent randomly created strings from repeating
|
|
2033
|
+
function getUniqueNonceSrc() {
|
|
2034
|
+
const nonceStr = createNonceSrc();
|
|
2035
|
+
if (sourceCenter.script.hasInfo(nonceStr)) {
|
|
2036
|
+
return getUniqueNonceSrc();
|
|
2037
|
+
}
|
|
2038
|
+
return nonceStr;
|
|
2039
|
+
}
|
|
2040
|
+
// transfer the attributes on the script to convertScript
|
|
2041
|
+
function setConvertScriptAttr(convertScript, attrs) {
|
|
2042
|
+
attrs.forEach((value, key) => {
|
|
2043
|
+
if ((key === 'type' && value === 'module') || key === 'defer' || key === 'async')
|
|
2044
|
+
return;
|
|
2045
|
+
if (key === 'src')
|
|
2046
|
+
key = 'data-origin-src';
|
|
2047
|
+
convertScript.setAttribute(key, value);
|
|
2048
|
+
});
|
|
2049
|
+
}
|
|
2050
|
+
// wrap code in sandbox
|
|
2051
|
+
function isWrapInSandBox(app, scriptInfo) {
|
|
2052
|
+
return app.useSandbox && !isTypeModule(app, scriptInfo);
|
|
2053
|
+
}
|
|
1710
2054
|
/**
|
|
1711
2055
|
* Extract script elements
|
|
1712
2056
|
* @param script script element
|
|
@@ -1717,14 +2061,15 @@ const globalScripts = new Map();
|
|
|
1717
2061
|
function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
1718
2062
|
let replaceComment = null;
|
|
1719
2063
|
let src = script.getAttribute('src');
|
|
1720
|
-
if (src)
|
|
2064
|
+
if (src)
|
|
1721
2065
|
src = CompletionPath(src, app.url);
|
|
1722
|
-
}
|
|
1723
2066
|
if (script.hasAttribute('exclude') || checkExcludeUrl(src, app.name)) {
|
|
1724
2067
|
replaceComment = document.createComment('script element with exclude attribute removed by micro-app');
|
|
1725
2068
|
}
|
|
1726
|
-
else if ((script.type &&
|
|
1727
|
-
|
|
2069
|
+
else if ((script.type &&
|
|
2070
|
+
!scriptTypes.includes(script.type)) ||
|
|
2071
|
+
script.hasAttribute('ignore') ||
|
|
2072
|
+
checkIgnoreUrl(src, app.name)) {
|
|
1728
2073
|
return null;
|
|
1729
2074
|
}
|
|
1730
2075
|
else if ((globalEnv.supportModuleScript && script.noModule) ||
|
|
@@ -1732,39 +2077,74 @@ function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
|
1732
2077
|
replaceComment = document.createComment(`${script.noModule ? 'noModule' : 'module'} script ignored by micro-app`);
|
|
1733
2078
|
}
|
|
1734
2079
|
else if (src) { // remote script
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
isExternal: true,
|
|
1738
|
-
isDynamic: isDynamic,
|
|
2080
|
+
let scriptInfo = sourceCenter.script.getInfo(src);
|
|
2081
|
+
const appSpaceData = {
|
|
1739
2082
|
async: script.hasAttribute('async'),
|
|
1740
2083
|
defer: script.defer || script.type === 'module',
|
|
1741
2084
|
module: script.type === 'module',
|
|
1742
|
-
|
|
2085
|
+
inline: script.hasAttribute('inline'),
|
|
2086
|
+
pure: script.hasAttribute('pure'),
|
|
2087
|
+
attrs: getAttributes(script),
|
|
1743
2088
|
};
|
|
2089
|
+
if (!scriptInfo) {
|
|
2090
|
+
scriptInfo = {
|
|
2091
|
+
code: '',
|
|
2092
|
+
isExternal: true,
|
|
2093
|
+
appSpace: {
|
|
2094
|
+
[app.name]: appSpaceData,
|
|
2095
|
+
}
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
else {
|
|
2099
|
+
/**
|
|
2100
|
+
* Reuse when appSpace exists
|
|
2101
|
+
* NOTE:
|
|
2102
|
+
* 1. The same static script, appSpace must be the same (in fact, it may be different when url change)
|
|
2103
|
+
* 2. The same dynamic script, appSpace may be the same, but we still reuse appSpace, which should pay attention
|
|
2104
|
+
*/
|
|
2105
|
+
scriptInfo.appSpace[app.name] = scriptInfo.appSpace[app.name] || appSpaceData;
|
|
2106
|
+
}
|
|
2107
|
+
sourceCenter.script.setInfo(src, scriptInfo);
|
|
1744
2108
|
if (!isDynamic) {
|
|
1745
|
-
app.source.scripts.
|
|
2109
|
+
app.source.scripts.add(src);
|
|
1746
2110
|
replaceComment = document.createComment(`script with src='${src}' extract by micro-app`);
|
|
1747
2111
|
}
|
|
1748
2112
|
else {
|
|
1749
|
-
return {
|
|
2113
|
+
return { address: src, scriptInfo };
|
|
1750
2114
|
}
|
|
1751
2115
|
}
|
|
1752
2116
|
else if (script.textContent) { // inline script
|
|
1753
|
-
|
|
1754
|
-
|
|
2117
|
+
/**
|
|
2118
|
+
* NOTE:
|
|
2119
|
+
* 1. Each inline script is unique
|
|
2120
|
+
* 2. Every dynamic created inline script will be re-executed
|
|
2121
|
+
* ACTION:
|
|
2122
|
+
* 1. Delete dynamic inline script info after exec
|
|
2123
|
+
* 2. Delete static inline script info when destroy
|
|
2124
|
+
*/
|
|
2125
|
+
const nonceStr = getUniqueNonceSrc();
|
|
2126
|
+
const scriptInfo = {
|
|
1755
2127
|
code: script.textContent,
|
|
1756
2128
|
isExternal: false,
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
2129
|
+
appSpace: {
|
|
2130
|
+
[app.name]: {
|
|
2131
|
+
async: false,
|
|
2132
|
+
defer: script.type === 'module',
|
|
2133
|
+
module: script.type === 'module',
|
|
2134
|
+
inline: script.hasAttribute('inline'),
|
|
2135
|
+
pure: script.hasAttribute('pure'),
|
|
2136
|
+
attrs: getAttributes(script),
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
1761
2139
|
};
|
|
1762
2140
|
if (!isDynamic) {
|
|
1763
|
-
app.source.scripts.
|
|
2141
|
+
app.source.scripts.add(nonceStr);
|
|
2142
|
+
sourceCenter.script.setInfo(nonceStr, scriptInfo);
|
|
1764
2143
|
replaceComment = document.createComment('inline script extract by micro-app');
|
|
1765
2144
|
}
|
|
1766
2145
|
else {
|
|
1767
|
-
|
|
2146
|
+
// Because each dynamic script is unique, it is not put into sourceCenter
|
|
2147
|
+
return { address: nonceStr, scriptInfo };
|
|
1768
2148
|
}
|
|
1769
2149
|
}
|
|
1770
2150
|
else if (!isDynamic) {
|
|
@@ -1787,38 +2167,38 @@ function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
|
1787
2167
|
*/
|
|
1788
2168
|
function getAssetsPlugins(appName) {
|
|
1789
2169
|
var _a, _b, _c;
|
|
1790
|
-
const globalPlugins = ((_a = microApp.plugins) === null || _a === void 0 ? void 0 : _a.global) || [];
|
|
1791
|
-
const modulePlugins = ((_c = (_b = microApp.plugins) === null || _b === void 0 ? void 0 : _b.modules) === null || _c === void 0 ? void 0 : _c[appName]) || [];
|
|
2170
|
+
const globalPlugins = ((_a = microApp.options.plugins) === null || _a === void 0 ? void 0 : _a.global) || [];
|
|
2171
|
+
const modulePlugins = ((_c = (_b = microApp.options.plugins) === null || _b === void 0 ? void 0 : _b.modules) === null || _c === void 0 ? void 0 : _c[appName]) || [];
|
|
1792
2172
|
return [...globalPlugins, ...modulePlugins];
|
|
1793
2173
|
}
|
|
1794
2174
|
/**
|
|
1795
|
-
* whether the
|
|
1796
|
-
* @param
|
|
2175
|
+
* whether the address needs to be excluded
|
|
2176
|
+
* @param address css or js link
|
|
1797
2177
|
* @param plugins microApp plugins
|
|
1798
2178
|
*/
|
|
1799
|
-
function checkExcludeUrl(
|
|
1800
|
-
if (!
|
|
2179
|
+
function checkExcludeUrl(address, appName) {
|
|
2180
|
+
if (!address)
|
|
1801
2181
|
return false;
|
|
1802
2182
|
const plugins = getAssetsPlugins(appName) || [];
|
|
1803
2183
|
return plugins.some(plugin => {
|
|
1804
2184
|
if (!plugin.excludeChecker)
|
|
1805
2185
|
return false;
|
|
1806
|
-
return plugin.excludeChecker(
|
|
2186
|
+
return plugin.excludeChecker(address);
|
|
1807
2187
|
});
|
|
1808
2188
|
}
|
|
1809
2189
|
/**
|
|
1810
|
-
* whether the
|
|
1811
|
-
* @param
|
|
2190
|
+
* whether the address needs to be ignore
|
|
2191
|
+
* @param address css or js link
|
|
1812
2192
|
* @param plugins microApp plugins
|
|
1813
2193
|
*/
|
|
1814
|
-
function checkIgnoreUrl(
|
|
1815
|
-
if (!
|
|
2194
|
+
function checkIgnoreUrl(address, appName) {
|
|
2195
|
+
if (!address)
|
|
1816
2196
|
return false;
|
|
1817
2197
|
const plugins = getAssetsPlugins(appName) || [];
|
|
1818
2198
|
return plugins.some(plugin => {
|
|
1819
2199
|
if (!plugin.ignoreChecker)
|
|
1820
2200
|
return false;
|
|
1821
|
-
return plugin.ignoreChecker(
|
|
2201
|
+
return plugin.ignoreChecker(address);
|
|
1822
2202
|
});
|
|
1823
2203
|
}
|
|
1824
2204
|
/**
|
|
@@ -1827,28 +2207,31 @@ function checkIgnoreUrl(url, appName) {
|
|
|
1827
2207
|
* @param app app
|
|
1828
2208
|
*/
|
|
1829
2209
|
function fetchScriptsFromHtml(wrapElement, app) {
|
|
1830
|
-
const
|
|
2210
|
+
const scriptList = Array.from(app.source.scripts);
|
|
1831
2211
|
const fetchScriptPromise = [];
|
|
1832
2212
|
const fetchScriptPromiseInfo = [];
|
|
1833
|
-
for (const
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
else if ((!info.defer && !info.async) || app.isPrefetch) {
|
|
1840
|
-
fetchScriptPromise.push(fetchSource(url, app.name));
|
|
1841
|
-
fetchScriptPromiseInfo.push([url, info]);
|
|
1842
|
-
}
|
|
2213
|
+
for (const address of scriptList) {
|
|
2214
|
+
const scriptInfo = sourceCenter.script.getInfo(address);
|
|
2215
|
+
const appSpaceData = scriptInfo.appSpace[app.name];
|
|
2216
|
+
if ((!appSpaceData.defer && !appSpaceData.async) || app.isPrefetch) {
|
|
2217
|
+
fetchScriptPromise.push(scriptInfo.code ? scriptInfo.code : fetchSource(address, app.name));
|
|
2218
|
+
fetchScriptPromiseInfo.push([address, scriptInfo]);
|
|
1843
2219
|
}
|
|
1844
2220
|
}
|
|
2221
|
+
const fiberScriptTasks = app.isPrefetch || app.fiber ? [] : null;
|
|
1845
2222
|
if (fetchScriptPromise.length) {
|
|
1846
2223
|
promiseStream(fetchScriptPromise, (res) => {
|
|
1847
|
-
fetchScriptSuccess(fetchScriptPromiseInfo[res.index][0], fetchScriptPromiseInfo[res.index][1], res.data);
|
|
2224
|
+
injectFiberTask(fiberScriptTasks, () => fetchScriptSuccess(fetchScriptPromiseInfo[res.index][0], fetchScriptPromiseInfo[res.index][1], res.data, app));
|
|
1848
2225
|
}, (err) => {
|
|
1849
2226
|
logError(err, app.name);
|
|
1850
2227
|
}, () => {
|
|
1851
|
-
|
|
2228
|
+
if (fiberScriptTasks) {
|
|
2229
|
+
fiberScriptTasks.push(() => Promise.resolve(app.onLoad(wrapElement)));
|
|
2230
|
+
serialExecFiberTasks(fiberScriptTasks);
|
|
2231
|
+
}
|
|
2232
|
+
else {
|
|
2233
|
+
app.onLoad(wrapElement);
|
|
2234
|
+
}
|
|
1852
2235
|
});
|
|
1853
2236
|
}
|
|
1854
2237
|
else {
|
|
@@ -1857,169 +2240,224 @@ function fetchScriptsFromHtml(wrapElement, app) {
|
|
|
1857
2240
|
}
|
|
1858
2241
|
/**
|
|
1859
2242
|
* fetch js succeeded, record the code value
|
|
1860
|
-
* @param
|
|
1861
|
-
* @param
|
|
2243
|
+
* @param address script address
|
|
2244
|
+
* @param scriptInfo resource script info
|
|
1862
2245
|
* @param data code
|
|
1863
2246
|
*/
|
|
1864
|
-
function fetchScriptSuccess(
|
|
1865
|
-
|
|
1866
|
-
|
|
2247
|
+
function fetchScriptSuccess(address, scriptInfo, code, app) {
|
|
2248
|
+
// reset scriptInfo.code
|
|
2249
|
+
scriptInfo.code = code;
|
|
2250
|
+
/**
|
|
2251
|
+
* Pre parse script for prefetch, improve rendering performance
|
|
2252
|
+
* NOTE:
|
|
2253
|
+
* 1. if global parseResult exist, skip this step
|
|
2254
|
+
* 2. if app is inline or script is esmodule, skip this step
|
|
2255
|
+
* 3. if global parseResult not exist, the current script occupies the position, when js is reused, parseResult is reference
|
|
2256
|
+
*/
|
|
2257
|
+
if (app.isPrefetch) {
|
|
2258
|
+
const appSpaceData = scriptInfo.appSpace[app.name];
|
|
2259
|
+
/**
|
|
2260
|
+
* When prefetch app is replaced by a new app in the processing phase, since the scriptInfo is common, when the scriptInfo of the prefetch app is processed, it may have already been processed.
|
|
2261
|
+
* This causes parsedCode to already exist when preloading ends
|
|
2262
|
+
* e.g.
|
|
2263
|
+
* 1. prefetch app.url different from <micro-app></micro-app>
|
|
2264
|
+
* 2. prefetch param different from <micro-app></micro-app>
|
|
2265
|
+
*/
|
|
2266
|
+
if (!appSpaceData.parsedCode) {
|
|
2267
|
+
appSpaceData.parsedCode = bindScope(address, app, code, scriptInfo);
|
|
2268
|
+
appSpaceData.wrapInSandBox = isWrapInSandBox(app, scriptInfo);
|
|
2269
|
+
if (!isInlineMode(app, scriptInfo)) {
|
|
2270
|
+
try {
|
|
2271
|
+
appSpaceData.parsedFunction = getParsedFunction(app, scriptInfo, appSpaceData.parsedCode);
|
|
2272
|
+
}
|
|
2273
|
+
catch (err) {
|
|
2274
|
+
logWarn('Something went wrong while handling preloaded resources', app.name, '\n', err);
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
1867
2278
|
}
|
|
1868
|
-
info.code = data;
|
|
1869
2279
|
}
|
|
1870
2280
|
/**
|
|
1871
2281
|
* Execute js in the mount lifecycle
|
|
1872
|
-
* @param scriptList script list
|
|
1873
2282
|
* @param app app
|
|
1874
2283
|
* @param initHook callback for umd mode
|
|
1875
2284
|
*/
|
|
1876
|
-
function execScripts(
|
|
1877
|
-
const
|
|
2285
|
+
function execScripts(app, initHook) {
|
|
2286
|
+
const fiberScriptTasks = app.fiber ? [] : null;
|
|
2287
|
+
const scriptList = Array.from(app.source.scripts);
|
|
1878
2288
|
const deferScriptPromise = [];
|
|
1879
2289
|
const deferScriptInfo = [];
|
|
1880
|
-
for (const
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
else {
|
|
1888
|
-
deferScriptPromise.push(info.code);
|
|
1889
|
-
}
|
|
1890
|
-
deferScriptInfo.push([url, info]);
|
|
1891
|
-
info.module && (initHook.moduleCount = initHook.moduleCount ? ++initHook.moduleCount : 1);
|
|
2290
|
+
for (const address of scriptList) {
|
|
2291
|
+
const scriptInfo = sourceCenter.script.getInfo(address);
|
|
2292
|
+
const appSpaceData = scriptInfo.appSpace[app.name];
|
|
2293
|
+
// Notice the second render
|
|
2294
|
+
if (appSpaceData.defer || appSpaceData.async) {
|
|
2295
|
+
if (scriptInfo.isExternal && !scriptInfo.code) {
|
|
2296
|
+
deferScriptPromise.push(fetchSource(address, app.name));
|
|
1892
2297
|
}
|
|
1893
2298
|
else {
|
|
1894
|
-
|
|
1895
|
-
initHook(false);
|
|
2299
|
+
deferScriptPromise.push(scriptInfo.code);
|
|
1896
2300
|
}
|
|
2301
|
+
deferScriptInfo.push([address, scriptInfo]);
|
|
2302
|
+
isTypeModule(app, scriptInfo) && (initHook.moduleCount = initHook.moduleCount ? ++initHook.moduleCount : 1);
|
|
2303
|
+
}
|
|
2304
|
+
else {
|
|
2305
|
+
injectFiberTask(fiberScriptTasks, () => {
|
|
2306
|
+
runScript(address, app, scriptInfo);
|
|
2307
|
+
initHook(false);
|
|
2308
|
+
});
|
|
1897
2309
|
}
|
|
1898
2310
|
}
|
|
1899
2311
|
if (deferScriptPromise.length) {
|
|
1900
2312
|
promiseStream(deferScriptPromise, (res) => {
|
|
1901
|
-
const
|
|
1902
|
-
|
|
2313
|
+
const scriptInfo = deferScriptInfo[res.index][1];
|
|
2314
|
+
scriptInfo.code = scriptInfo.code || res.data;
|
|
1903
2315
|
}, (err) => {
|
|
1904
2316
|
initHook.errorCount = initHook.errorCount ? ++initHook.errorCount : 1;
|
|
1905
2317
|
logError(err, app.name);
|
|
1906
2318
|
}, () => {
|
|
1907
|
-
deferScriptInfo.forEach(([
|
|
1908
|
-
if (
|
|
1909
|
-
|
|
1910
|
-
|
|
2319
|
+
deferScriptInfo.forEach(([address, scriptInfo]) => {
|
|
2320
|
+
if (scriptInfo.code) {
|
|
2321
|
+
injectFiberTask(fiberScriptTasks, () => {
|
|
2322
|
+
runScript(address, app, scriptInfo, initHook);
|
|
2323
|
+
!isTypeModule(app, scriptInfo) && initHook(false);
|
|
2324
|
+
});
|
|
1911
2325
|
}
|
|
1912
2326
|
});
|
|
1913
|
-
|
|
1914
|
-
|
|
2327
|
+
/**
|
|
2328
|
+
* Fiber wraps js in requestIdleCallback and executes it in sequence
|
|
2329
|
+
* NOTE:
|
|
2330
|
+
* 1. In order to ensure the execution order, wait for all js loaded and then execute
|
|
2331
|
+
* 2. If js create a dynamic script, it may be errors in the execution order, because the subsequent js is wrapped in requestIdleCallback, even putting dynamic script in requestIdleCallback doesn't solve it
|
|
2332
|
+
*
|
|
2333
|
+
* BUG: NOTE.2 - execution order problem
|
|
2334
|
+
*/
|
|
2335
|
+
if (fiberScriptTasks) {
|
|
2336
|
+
fiberScriptTasks.push(() => Promise.resolve(initHook(isUndefined(initHook.moduleCount) ||
|
|
2337
|
+
initHook.errorCount === deferScriptPromise.length)));
|
|
2338
|
+
serialExecFiberTasks(fiberScriptTasks);
|
|
2339
|
+
}
|
|
2340
|
+
else {
|
|
2341
|
+
initHook(isUndefined(initHook.moduleCount) ||
|
|
2342
|
+
initHook.errorCount === deferScriptPromise.length);
|
|
2343
|
+
}
|
|
1915
2344
|
});
|
|
1916
2345
|
}
|
|
1917
2346
|
else {
|
|
1918
|
-
|
|
2347
|
+
if (fiberScriptTasks) {
|
|
2348
|
+
fiberScriptTasks.push(() => Promise.resolve(initHook(true)));
|
|
2349
|
+
serialExecFiberTasks(fiberScriptTasks);
|
|
2350
|
+
}
|
|
2351
|
+
else {
|
|
2352
|
+
initHook(true);
|
|
2353
|
+
}
|
|
1919
2354
|
}
|
|
1920
2355
|
}
|
|
1921
2356
|
/**
|
|
1922
2357
|
* run code
|
|
1923
|
-
* @param
|
|
2358
|
+
* @param address script address
|
|
1924
2359
|
* @param app app
|
|
1925
|
-
* @param
|
|
1926
|
-
* @param isDynamic dynamically created script
|
|
2360
|
+
* @param scriptInfo script info
|
|
1927
2361
|
* @param callback callback of module script
|
|
1928
2362
|
*/
|
|
1929
|
-
function runScript(
|
|
2363
|
+
function runScript(address, app, scriptInfo, callback, replaceElement) {
|
|
1930
2364
|
var _a;
|
|
1931
2365
|
try {
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
2366
|
+
actionsBeforeRunScript(app);
|
|
2367
|
+
const appSpaceData = scriptInfo.appSpace[app.name];
|
|
2368
|
+
const wrapInSandBox = isWrapInSandBox(app, scriptInfo);
|
|
2369
|
+
/**
|
|
2370
|
+
* NOTE:
|
|
2371
|
+
* 1. plugins and wrapCode will only be executed once
|
|
2372
|
+
* 2. if parsedCode not exist, parsedFunction is not exist
|
|
2373
|
+
* 3. if parsedCode exist, parsedFunction does not necessarily exist
|
|
2374
|
+
*/
|
|
2375
|
+
if (!appSpaceData.parsedCode || appSpaceData.wrapInSandBox !== wrapInSandBox) {
|
|
2376
|
+
appSpaceData.parsedCode = bindScope(address, app, scriptInfo.code, scriptInfo);
|
|
2377
|
+
appSpaceData.wrapInSandBox = wrapInSandBox;
|
|
2378
|
+
appSpaceData.parsedFunction = null;
|
|
2379
|
+
}
|
|
2380
|
+
if (isInlineMode(app, scriptInfo)) {
|
|
2381
|
+
const scriptElement = replaceElement || pureCreateElement('script');
|
|
2382
|
+
runCode2InlineScript(address, appSpaceData.parsedCode, isTypeModule(app, scriptInfo), scriptElement, appSpaceData.attrs, callback);
|
|
2383
|
+
if (!replaceElement) {
|
|
2384
|
+
// TEST IGNORE
|
|
2385
|
+
(_a = app.container) === null || _a === void 0 ? void 0 : _a.querySelector('micro-app-body').appendChild(scriptElement);
|
|
2386
|
+
}
|
|
1940
2387
|
}
|
|
1941
2388
|
else {
|
|
1942
|
-
|
|
1943
|
-
if (isDynamic)
|
|
1944
|
-
return document.createComment('dynamic script extract by micro-app');
|
|
2389
|
+
runParsedFunction(app, scriptInfo);
|
|
1945
2390
|
}
|
|
1946
2391
|
}
|
|
1947
2392
|
catch (e) {
|
|
1948
|
-
console.error(`[micro-app from runScript] app ${app.name}: `, e);
|
|
2393
|
+
console.error(`[micro-app from ${replaceElement ? 'runDynamicScript' : 'runScript'}] app ${app.name}: `, e, address);
|
|
1949
2394
|
}
|
|
1950
2395
|
}
|
|
1951
2396
|
/**
|
|
1952
2397
|
* Get dynamically created remote script
|
|
1953
|
-
* @param
|
|
1954
|
-
* @param
|
|
1955
|
-
* @param
|
|
2398
|
+
* @param address script address
|
|
2399
|
+
* @param app app instance
|
|
2400
|
+
* @param scriptInfo scriptInfo
|
|
1956
2401
|
* @param originScript origin script element
|
|
1957
2402
|
*/
|
|
1958
|
-
function runDynamicRemoteScript(
|
|
2403
|
+
function runDynamicRemoteScript(address, app, scriptInfo, originScript) {
|
|
2404
|
+
const replaceElement = isInlineMode(app, scriptInfo) ? pureCreateElement('script') : document.createComment('dynamic script extract by micro-app');
|
|
1959
2405
|
const dispatchScriptOnLoadEvent = () => dispatchOnLoadEvent(originScript);
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
if (globalScripts.has(url)) {
|
|
1974
|
-
const code = globalScripts.get(url);
|
|
1975
|
-
info.code = code;
|
|
1976
|
-
app.source.scripts.set(url, info);
|
|
1977
|
-
!info.module && defer(dispatchScriptOnLoadEvent);
|
|
1978
|
-
return runScript(url, app, info, true, dispatchScriptOnLoadEvent);
|
|
1979
|
-
}
|
|
1980
|
-
let replaceElement;
|
|
1981
|
-
if (app.inline || info.module) {
|
|
1982
|
-
replaceElement = pureCreateElement('script');
|
|
2406
|
+
const runDynamicScript = () => {
|
|
2407
|
+
const descriptor = Object.getOwnPropertyDescriptor(globalEnv.rawDocument, 'currentScript');
|
|
2408
|
+
if (!descriptor || descriptor.configurable) {
|
|
2409
|
+
Object.defineProperty(globalEnv.rawDocument, 'currentScript', {
|
|
2410
|
+
value: originScript,
|
|
2411
|
+
configurable: true,
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2414
|
+
runScript(address, app, scriptInfo, dispatchScriptOnLoadEvent, replaceElement);
|
|
2415
|
+
!isTypeModule(app, scriptInfo) && dispatchScriptOnLoadEvent();
|
|
2416
|
+
};
|
|
2417
|
+
if (scriptInfo.code) {
|
|
2418
|
+
defer(runDynamicScript);
|
|
1983
2419
|
}
|
|
1984
2420
|
else {
|
|
1985
|
-
|
|
2421
|
+
fetchSource(address, app.name).then((code) => {
|
|
2422
|
+
scriptInfo.code = code;
|
|
2423
|
+
runDynamicScript();
|
|
2424
|
+
}).catch((err) => {
|
|
2425
|
+
logError(err, app.name);
|
|
2426
|
+
dispatchOnErrorEvent(originScript);
|
|
2427
|
+
});
|
|
1986
2428
|
}
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
catch (e) {
|
|
2001
|
-
console.error(`[micro-app from runDynamicScript] app ${app.name}: `, e, url);
|
|
2002
|
-
}
|
|
2003
|
-
!info.module && dispatchScriptOnLoadEvent();
|
|
2004
|
-
}).catch((err) => {
|
|
2005
|
-
logError(err, app.name);
|
|
2006
|
-
dispatchOnErrorEvent(originScript);
|
|
2007
|
-
});
|
|
2429
|
+
return replaceElement;
|
|
2430
|
+
}
|
|
2431
|
+
/**
|
|
2432
|
+
* Get dynamically created inline script
|
|
2433
|
+
* @param address script address
|
|
2434
|
+
* @param app app instance
|
|
2435
|
+
* @param scriptInfo scriptInfo
|
|
2436
|
+
*/
|
|
2437
|
+
function runDynamicInlineScript(address, app, scriptInfo) {
|
|
2438
|
+
const replaceElement = isInlineMode(app, scriptInfo) ? pureCreateElement('script') : document.createComment('dynamic script extract by micro-app');
|
|
2439
|
+
runScript(address, app, scriptInfo, void 0, replaceElement);
|
|
2008
2440
|
return replaceElement;
|
|
2009
2441
|
}
|
|
2010
2442
|
/**
|
|
2011
2443
|
* common handle for inline script
|
|
2012
|
-
* @param
|
|
2444
|
+
* @param address script address
|
|
2013
2445
|
* @param code bound code
|
|
2014
2446
|
* @param module type='module' of script
|
|
2015
2447
|
* @param scriptElement target script element
|
|
2448
|
+
* @param attrs attributes of script element
|
|
2016
2449
|
* @param callback callback of module script
|
|
2017
2450
|
*/
|
|
2018
|
-
function runCode2InlineScript(
|
|
2451
|
+
function runCode2InlineScript(address, code, module, scriptElement, attrs, callback) {
|
|
2019
2452
|
if (module) {
|
|
2020
2453
|
// module script is async, transform it to a blob for subsequent operations
|
|
2021
|
-
|
|
2022
|
-
|
|
2454
|
+
if (isInlineScript(address)) {
|
|
2455
|
+
const blob = new Blob([code], { type: 'text/javascript' });
|
|
2456
|
+
scriptElement.src = URL.createObjectURL(blob);
|
|
2457
|
+
}
|
|
2458
|
+
else {
|
|
2459
|
+
scriptElement.src = address;
|
|
2460
|
+
}
|
|
2023
2461
|
scriptElement.setAttribute('type', 'module');
|
|
2024
2462
|
if (callback) {
|
|
2025
2463
|
callback.moduleCount && callback.moduleCount--;
|
|
@@ -2029,55 +2467,65 @@ function runCode2InlineScript(url, code, module, scriptElement, callback) {
|
|
|
2029
2467
|
else {
|
|
2030
2468
|
scriptElement.textContent = code;
|
|
2031
2469
|
}
|
|
2032
|
-
|
|
2033
|
-
scriptElement.setAttribute('data-origin-src', url);
|
|
2034
|
-
}
|
|
2470
|
+
setConvertScriptAttr(scriptElement, attrs);
|
|
2035
2471
|
}
|
|
2036
2472
|
// init & run code2Function
|
|
2037
|
-
function
|
|
2038
|
-
|
|
2039
|
-
|
|
2473
|
+
function runParsedFunction(app, scriptInfo) {
|
|
2474
|
+
const appSpaceData = scriptInfo.appSpace[app.name];
|
|
2475
|
+
if (!appSpaceData.parsedFunction) {
|
|
2476
|
+
appSpaceData.parsedFunction = getParsedFunction(app, scriptInfo, appSpaceData.parsedCode);
|
|
2040
2477
|
}
|
|
2041
|
-
|
|
2478
|
+
appSpaceData.parsedFunction.call(window);
|
|
2042
2479
|
}
|
|
2043
2480
|
/**
|
|
2044
2481
|
* bind js scope
|
|
2045
|
-
* @param url script address
|
|
2046
2482
|
* @param app app
|
|
2047
2483
|
* @param code code
|
|
2048
|
-
* @param
|
|
2484
|
+
* @param scriptInfo source script info
|
|
2049
2485
|
*/
|
|
2050
|
-
function bindScope(
|
|
2051
|
-
// TODO:
|
|
2052
|
-
if (isPlainObject(microApp.plugins)) {
|
|
2053
|
-
code = usePlugins(
|
|
2486
|
+
function bindScope(address, app, code, scriptInfo) {
|
|
2487
|
+
// TODO: cache
|
|
2488
|
+
if (isPlainObject(microApp.options.plugins)) {
|
|
2489
|
+
code = usePlugins(address, code, app.name, microApp.options.plugins);
|
|
2054
2490
|
}
|
|
2055
|
-
if (app
|
|
2056
|
-
|
|
2057
|
-
return `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`;
|
|
2491
|
+
if (isWrapInSandBox(app, scriptInfo)) {
|
|
2492
|
+
return `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n${isInlineScript(address) ? '' : `//# sourceURL=${address}\n`}}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`;
|
|
2058
2493
|
}
|
|
2059
2494
|
return code;
|
|
2060
2495
|
}
|
|
2496
|
+
/**
|
|
2497
|
+
* actions before run script
|
|
2498
|
+
*/
|
|
2499
|
+
function actionsBeforeRunScript(app) {
|
|
2500
|
+
setActiveProxyWindow(app);
|
|
2501
|
+
}
|
|
2502
|
+
/**
|
|
2503
|
+
* set active sandBox.proxyWindow to window.__MICRO_APP_PROXY_WINDOW__
|
|
2504
|
+
*/
|
|
2505
|
+
function setActiveProxyWindow(app) {
|
|
2506
|
+
if (app.sandBox) {
|
|
2507
|
+
globalEnv.rawWindow.__MICRO_APP_PROXY_WINDOW__ = app.sandBox.proxyWindow;
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2061
2510
|
/**
|
|
2062
2511
|
* Call the plugin to process the file
|
|
2063
|
-
* @param
|
|
2512
|
+
* @param address script address
|
|
2064
2513
|
* @param code code
|
|
2065
2514
|
* @param appName app name
|
|
2066
2515
|
* @param plugins plugin list
|
|
2067
|
-
* @param info source script info
|
|
2068
2516
|
*/
|
|
2069
|
-
function usePlugins(
|
|
2517
|
+
function usePlugins(address, code, appName, plugins) {
|
|
2070
2518
|
var _a;
|
|
2071
|
-
const newCode = processCode(plugins.global, code,
|
|
2072
|
-
return processCode((_a = plugins.modules) === null || _a === void 0 ? void 0 : _a[appName], newCode,
|
|
2519
|
+
const newCode = processCode(plugins.global, code, address);
|
|
2520
|
+
return processCode((_a = plugins.modules) === null || _a === void 0 ? void 0 : _a[appName], newCode, address);
|
|
2073
2521
|
}
|
|
2074
|
-
function processCode(configs, code,
|
|
2522
|
+
function processCode(configs, code, address) {
|
|
2075
2523
|
if (!isArray(configs)) {
|
|
2076
2524
|
return code;
|
|
2077
2525
|
}
|
|
2078
2526
|
return configs.reduce((preCode, config) => {
|
|
2079
2527
|
if (isPlainObject(config) && isFunction(config.loader)) {
|
|
2080
|
-
return config.loader(preCode,
|
|
2528
|
+
return config.loader(preCode, address);
|
|
2081
2529
|
}
|
|
2082
2530
|
return preCode;
|
|
2083
2531
|
}, code);
|
|
@@ -2098,10 +2546,10 @@ function getWrapElement(str) {
|
|
|
2098
2546
|
* @param app app
|
|
2099
2547
|
* @param microAppHead micro-app-head element
|
|
2100
2548
|
*/
|
|
2101
|
-
function flatChildren(parent, app, microAppHead) {
|
|
2549
|
+
function flatChildren(parent, app, microAppHead, fiberStyleTasks) {
|
|
2102
2550
|
const children = Array.from(parent.children);
|
|
2103
2551
|
children.length && children.forEach((child) => {
|
|
2104
|
-
flatChildren(child, app);
|
|
2552
|
+
flatChildren(child, app, microAppHead, fiberStyleTasks);
|
|
2105
2553
|
});
|
|
2106
2554
|
for (const dom of children) {
|
|
2107
2555
|
if (dom instanceof HTMLLinkElement) {
|
|
@@ -2120,7 +2568,7 @@ function flatChildren(parent, app, microAppHead) {
|
|
|
2120
2568
|
parent.replaceChild(document.createComment('style element with exclude attribute ignored by micro-app'), dom);
|
|
2121
2569
|
}
|
|
2122
2570
|
else if (app.scopecss && !dom.hasAttribute('ignore')) {
|
|
2123
|
-
scopedCSS(dom, app);
|
|
2571
|
+
injectFiberTask(fiberStyleTasks, () => scopedCSS(dom, app));
|
|
2124
2572
|
}
|
|
2125
2573
|
}
|
|
2126
2574
|
else if (dom instanceof HTMLScriptElement) {
|
|
@@ -2148,9 +2596,17 @@ function extractSourceDom(htmlStr, app) {
|
|
|
2148
2596
|
app.onerror(new Error(msg));
|
|
2149
2597
|
return logError(msg, app.name);
|
|
2150
2598
|
}
|
|
2151
|
-
|
|
2599
|
+
const fiberStyleTasks = app.isPrefetch || app.fiber ? [] : null;
|
|
2600
|
+
flatChildren(wrapElement, app, microAppHead, fiberStyleTasks);
|
|
2601
|
+
/**
|
|
2602
|
+
* Style and link are parallel, because it takes a lot of time for link to request resources. During this period, style processing can be performed to improve efficiency.
|
|
2603
|
+
*/
|
|
2604
|
+
const fiberStyleResult = serialExecFiberTasks(fiberStyleTasks);
|
|
2152
2605
|
if (app.source.links.size) {
|
|
2153
|
-
fetchLinksFromHtml(wrapElement, app, microAppHead);
|
|
2606
|
+
fetchLinksFromHtml(wrapElement, app, microAppHead, fiberStyleResult);
|
|
2607
|
+
}
|
|
2608
|
+
else if (fiberStyleResult) {
|
|
2609
|
+
fiberStyleResult.then(() => app.onLoad(wrapElement));
|
|
2154
2610
|
}
|
|
2155
2611
|
else {
|
|
2156
2612
|
app.onLoad(wrapElement);
|
|
@@ -2166,6 +2622,37 @@ function extractSourceDom(htmlStr, app) {
|
|
|
2166
2622
|
class EventCenter {
|
|
2167
2623
|
constructor() {
|
|
2168
2624
|
this.eventList = new Map();
|
|
2625
|
+
this.queue = [];
|
|
2626
|
+
this.recordStep = {};
|
|
2627
|
+
// run task
|
|
2628
|
+
this.process = () => {
|
|
2629
|
+
var _a, _b;
|
|
2630
|
+
let name;
|
|
2631
|
+
const temRecordStep = this.recordStep;
|
|
2632
|
+
const queue = this.queue;
|
|
2633
|
+
this.recordStep = {};
|
|
2634
|
+
this.queue = [];
|
|
2635
|
+
while (name = queue.shift()) {
|
|
2636
|
+
const eventInfo = this.eventList.get(name);
|
|
2637
|
+
// clear tempData, force before exec nextStep
|
|
2638
|
+
const tempData = eventInfo.tempData;
|
|
2639
|
+
const force = eventInfo.force;
|
|
2640
|
+
eventInfo.tempData = null;
|
|
2641
|
+
eventInfo.force = false;
|
|
2642
|
+
if (force || !this.isEqual(eventInfo.data, tempData)) {
|
|
2643
|
+
eventInfo.data = tempData || eventInfo.data;
|
|
2644
|
+
for (const f of eventInfo.callbacks) {
|
|
2645
|
+
f(eventInfo.data);
|
|
2646
|
+
}
|
|
2647
|
+
(_b = (_a = temRecordStep[name]).dispatchDataEvent) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
2648
|
+
/**
|
|
2649
|
+
* WARING:
|
|
2650
|
+
* If data of other app is sent in nextStep, it may cause confusion of tempData and force
|
|
2651
|
+
*/
|
|
2652
|
+
temRecordStep[name].nextStepList.forEach((nextStep) => nextStep());
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
};
|
|
2169
2656
|
}
|
|
2170
2657
|
// whether the name is legal
|
|
2171
2658
|
isLegalName(name) {
|
|
@@ -2175,6 +2662,39 @@ class EventCenter {
|
|
|
2175
2662
|
}
|
|
2176
2663
|
return true;
|
|
2177
2664
|
}
|
|
2665
|
+
// add appName to queue
|
|
2666
|
+
enqueue(name, nextStep, dispatchDataEvent) {
|
|
2667
|
+
// this.nextStepList.push(nextStep)
|
|
2668
|
+
if (this.recordStep[name]) {
|
|
2669
|
+
this.recordStep[name].nextStepList.push(nextStep);
|
|
2670
|
+
dispatchDataEvent && (this.recordStep[name].dispatchDataEvent = dispatchDataEvent);
|
|
2671
|
+
}
|
|
2672
|
+
else {
|
|
2673
|
+
this.recordStep[name] = {
|
|
2674
|
+
nextStepList: [nextStep],
|
|
2675
|
+
dispatchDataEvent,
|
|
2676
|
+
};
|
|
2677
|
+
}
|
|
2678
|
+
/**
|
|
2679
|
+
* The micro task is executed async when the second render of child.
|
|
2680
|
+
* We should ensure that the data changes are executed before binding the listening function
|
|
2681
|
+
*/
|
|
2682
|
+
(!this.queue.includes(name) && this.queue.push(name) === 1) && defer(this.process);
|
|
2683
|
+
}
|
|
2684
|
+
/**
|
|
2685
|
+
* In react, each setState will trigger setData, so we need a filter operation to avoid repeated trigger
|
|
2686
|
+
*/
|
|
2687
|
+
isEqual(oldData, newData) {
|
|
2688
|
+
if (!newData || Object.keys(oldData).length !== Object.keys(newData).length)
|
|
2689
|
+
return false;
|
|
2690
|
+
for (const key in oldData) {
|
|
2691
|
+
if (Object.prototype.hasOwnProperty.call(oldData, key)) {
|
|
2692
|
+
if (oldData[key] !== newData[key])
|
|
2693
|
+
return false;
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
return true;
|
|
2697
|
+
}
|
|
2178
2698
|
/**
|
|
2179
2699
|
* add listener
|
|
2180
2700
|
* @param name event name
|
|
@@ -2194,7 +2714,10 @@ class EventCenter {
|
|
|
2194
2714
|
};
|
|
2195
2715
|
this.eventList.set(name, eventInfo);
|
|
2196
2716
|
}
|
|
2197
|
-
else if (autoTrigger &&
|
|
2717
|
+
else if (autoTrigger &&
|
|
2718
|
+
Object.keys(eventInfo.data).length &&
|
|
2719
|
+
(!this.queue.includes(name) ||
|
|
2720
|
+
this.isEqual(eventInfo.data, eventInfo.tempData))) {
|
|
2198
2721
|
// auto trigger when data not null
|
|
2199
2722
|
f(eventInfo.data);
|
|
2200
2723
|
}
|
|
@@ -2215,21 +2738,27 @@ class EventCenter {
|
|
|
2215
2738
|
}
|
|
2216
2739
|
}
|
|
2217
2740
|
}
|
|
2741
|
+
/**
|
|
2742
|
+
* clearData
|
|
2743
|
+
*/
|
|
2744
|
+
clearData(name) {
|
|
2745
|
+
if (this.isLegalName(name)) {
|
|
2746
|
+
const eventInfo = this.eventList.get(name);
|
|
2747
|
+
if (eventInfo) {
|
|
2748
|
+
eventInfo.data = {};
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2218
2752
|
// dispatch data
|
|
2219
|
-
dispatch(name, data) {
|
|
2753
|
+
dispatch(name, data, nextStep, force, dispatchDataEvent) {
|
|
2220
2754
|
if (this.isLegalName(name)) {
|
|
2221
2755
|
if (!isPlainObject(data)) {
|
|
2222
2756
|
return logError('event-center: data must be object');
|
|
2223
2757
|
}
|
|
2224
2758
|
let eventInfo = this.eventList.get(name);
|
|
2225
2759
|
if (eventInfo) {
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
eventInfo.data = data;
|
|
2229
|
-
for (const f of eventInfo.callbacks) {
|
|
2230
|
-
f(data);
|
|
2231
|
-
}
|
|
2232
|
-
}
|
|
2760
|
+
eventInfo.tempData = assign({}, eventInfo.tempData || eventInfo.data, data);
|
|
2761
|
+
!eventInfo.force && (eventInfo.force = !!force);
|
|
2233
2762
|
}
|
|
2234
2763
|
else {
|
|
2235
2764
|
eventInfo = {
|
|
@@ -2237,7 +2766,13 @@ class EventCenter {
|
|
|
2237
2766
|
callbacks: new Set(),
|
|
2238
2767
|
};
|
|
2239
2768
|
this.eventList.set(name, eventInfo);
|
|
2769
|
+
/**
|
|
2770
|
+
* When sent data to parent, eventInfo probably does not exist, because parent may listen to datachange
|
|
2771
|
+
*/
|
|
2772
|
+
eventInfo.force = true;
|
|
2240
2773
|
}
|
|
2774
|
+
// add to queue, event eventInfo is null
|
|
2775
|
+
this.enqueue(name, nextStep, dispatchDataEvent);
|
|
2241
2776
|
}
|
|
2242
2777
|
}
|
|
2243
2778
|
// get data
|
|
@@ -2286,10 +2821,13 @@ class EventCenterForGlobal {
|
|
|
2286
2821
|
* dispatch global data
|
|
2287
2822
|
* @param data data
|
|
2288
2823
|
*/
|
|
2289
|
-
setGlobalData(data) {
|
|
2824
|
+
setGlobalData(data, nextStep, force) {
|
|
2290
2825
|
// clear dom scope before dispatch global data, apply to micro app
|
|
2291
2826
|
removeDomScope();
|
|
2292
|
-
eventCenter.dispatch('global', data);
|
|
2827
|
+
eventCenter.dispatch('global', data, () => isFunction(nextStep) && nextStep(), force);
|
|
2828
|
+
}
|
|
2829
|
+
forceSetGlobalData(data, nextStep) {
|
|
2830
|
+
this.setGlobalData(data, nextStep, true);
|
|
2293
2831
|
}
|
|
2294
2832
|
/**
|
|
2295
2833
|
* get global data
|
|
@@ -2297,6 +2835,12 @@ class EventCenterForGlobal {
|
|
|
2297
2835
|
getGlobalData() {
|
|
2298
2836
|
return eventCenter.getData('global');
|
|
2299
2837
|
}
|
|
2838
|
+
/**
|
|
2839
|
+
* clear global data
|
|
2840
|
+
*/
|
|
2841
|
+
clearGlobalData() {
|
|
2842
|
+
eventCenter.clearData('global');
|
|
2843
|
+
}
|
|
2300
2844
|
/**
|
|
2301
2845
|
* clear all listener of global data
|
|
2302
2846
|
* if appName exists, only the specified functions is cleared
|
|
@@ -2347,8 +2891,19 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
2347
2891
|
* @param appName app.name
|
|
2348
2892
|
* @param data data
|
|
2349
2893
|
*/
|
|
2350
|
-
setData(appName, data) {
|
|
2351
|
-
eventCenter.dispatch(formatEventName(formatAppName(appName), true), data);
|
|
2894
|
+
setData(appName, data, nextStep, force) {
|
|
2895
|
+
eventCenter.dispatch(formatEventName(formatAppName(appName), true), data, () => isFunction(nextStep) && nextStep(), force);
|
|
2896
|
+
}
|
|
2897
|
+
forceSetData(appName, data, nextStep) {
|
|
2898
|
+
this.setData(appName, data, nextStep, true);
|
|
2899
|
+
}
|
|
2900
|
+
/**
|
|
2901
|
+
* clear data from base app
|
|
2902
|
+
* @param appName app.name
|
|
2903
|
+
* @param fromBaseApp whether clear data from child app, default is true
|
|
2904
|
+
*/
|
|
2905
|
+
clearData(appName, fromBaseApp = true) {
|
|
2906
|
+
eventCenter.clearData(formatEventName(formatAppName(appName), fromBaseApp));
|
|
2352
2907
|
}
|
|
2353
2908
|
/**
|
|
2354
2909
|
* clear all listener for specified micro app
|
|
@@ -2384,25 +2939,36 @@ class EventCenterForMicroApp extends EventCenterForGlobal {
|
|
|
2384
2939
|
/**
|
|
2385
2940
|
* get data from base app
|
|
2386
2941
|
*/
|
|
2387
|
-
getData() {
|
|
2388
|
-
return eventCenter.getData(formatEventName(this.appName,
|
|
2942
|
+
getData(fromBaseApp = true) {
|
|
2943
|
+
return eventCenter.getData(formatEventName(this.appName, fromBaseApp));
|
|
2389
2944
|
}
|
|
2390
2945
|
/**
|
|
2391
2946
|
* dispatch data to base app
|
|
2392
2947
|
* @param data data
|
|
2393
2948
|
*/
|
|
2394
|
-
dispatch(data) {
|
|
2949
|
+
dispatch(data, nextStep, force) {
|
|
2395
2950
|
removeDomScope();
|
|
2396
|
-
eventCenter.dispatch(formatEventName(this.appName, false), data)
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2951
|
+
eventCenter.dispatch(formatEventName(this.appName, false), data, () => isFunction(nextStep) && nextStep(), force, () => {
|
|
2952
|
+
const app = appInstanceMap.get(this.appName);
|
|
2953
|
+
if ((app === null || app === void 0 ? void 0 : app.container) && isPlainObject(data)) {
|
|
2954
|
+
const event = new CustomEvent('datachange', {
|
|
2955
|
+
detail: {
|
|
2956
|
+
data: eventCenter.getData(formatEventName(this.appName, false))
|
|
2957
|
+
}
|
|
2958
|
+
});
|
|
2959
|
+
getRootContainer(app.container).dispatchEvent(event);
|
|
2960
|
+
}
|
|
2961
|
+
});
|
|
2962
|
+
}
|
|
2963
|
+
forceDispatch(data, nextStep) {
|
|
2964
|
+
this.dispatch(data, nextStep, true);
|
|
2965
|
+
}
|
|
2966
|
+
/**
|
|
2967
|
+
* clear data from child app
|
|
2968
|
+
* @param fromBaseApp whether clear data from base app, default is false
|
|
2969
|
+
*/
|
|
2970
|
+
clearData(fromBaseApp = false) {
|
|
2971
|
+
eventCenter.clearData(formatEventName(this.appName, fromBaseApp));
|
|
2406
2972
|
}
|
|
2407
2973
|
/**
|
|
2408
2974
|
* clear all listeners
|
|
@@ -2989,9 +3555,19 @@ function addHistoryListener(appName) {
|
|
|
2989
3555
|
function dispatchPopStateEventToMicroApp(appName, proxyWindow) {
|
|
2990
3556
|
// create PopStateEvent named popstate-appName with sub app state
|
|
2991
3557
|
const newPopStateEvent = new PopStateEvent(formatEventName$1('popstate', appName), { state: getMicroState(appName) });
|
|
3558
|
+
/**
|
|
3559
|
+
* angular14 takes e.type as type judgment
|
|
3560
|
+
* when e.type is popstate-appName popstate event will be invalid
|
|
3561
|
+
*/
|
|
3562
|
+
// Object.defineProperty(newPopStateEvent, 'type', {
|
|
3563
|
+
// value: 'popstate',
|
|
3564
|
+
// writable: true,
|
|
3565
|
+
// configurable: true,
|
|
3566
|
+
// enumerable: true,
|
|
3567
|
+
// })
|
|
2992
3568
|
globalEnv.rawWindow.dispatchEvent(newPopStateEvent);
|
|
2993
3569
|
// call function window.onpopstate if it exists
|
|
2994
|
-
|
|
3570
|
+
isFunction(proxyWindow.onpopstate) && proxyWindow.onpopstate(newPopStateEvent);
|
|
2995
3571
|
}
|
|
2996
3572
|
/**
|
|
2997
3573
|
* dispatch formatted hashchange event to microApp
|
|
@@ -3006,7 +3582,7 @@ function dispatchHashChangeEventToMicroApp(appName, proxyWindow, oldHref) {
|
|
|
3006
3582
|
});
|
|
3007
3583
|
globalEnv.rawWindow.dispatchEvent(newHashChangeEvent);
|
|
3008
3584
|
// call function window.onhashchange if it exists
|
|
3009
|
-
|
|
3585
|
+
isFunction(proxyWindow.onhashchange) && proxyWindow.onhashchange(newHashChangeEvent);
|
|
3010
3586
|
}
|
|
3011
3587
|
/**
|
|
3012
3588
|
* dispatch native PopStateEvent, simulate location behavior
|
|
@@ -3163,7 +3739,6 @@ function reWriteHistoryMethod(method) {
|
|
|
3163
3739
|
* 1. Exec after apply pushState/replaceState
|
|
3164
3740
|
* 2. Unable to catch when base app navigate with location
|
|
3165
3741
|
* 3. When in nest app, rawPushState/rawReplaceState has been modified by parent
|
|
3166
|
-
* 4.
|
|
3167
3742
|
*/
|
|
3168
3743
|
getActiveApps(true).forEach(appName => {
|
|
3169
3744
|
const app = appInstanceMap.get(appName);
|
|
@@ -3273,7 +3848,7 @@ function createRouterApi() {
|
|
|
3273
3848
|
removeDomScope();
|
|
3274
3849
|
for (const guard of guards) {
|
|
3275
3850
|
if (isFunction(guard)) {
|
|
3276
|
-
guard(
|
|
3851
|
+
guard(to, from, appName);
|
|
3277
3852
|
}
|
|
3278
3853
|
else if (isPlainObject(guard) && isFunction(guard[appName])) {
|
|
3279
3854
|
guard[appName](to, from);
|
|
@@ -3614,7 +4189,12 @@ function createMicroRouter(appName, url) {
|
|
|
3614
4189
|
microHistory: createMicroHistory(appName, microLocation),
|
|
3615
4190
|
};
|
|
3616
4191
|
}
|
|
3617
|
-
|
|
4192
|
+
/**
|
|
4193
|
+
* When the sandbox executes start, or the hidden keep-alive application is re-rendered, the location is updated according to the browser url or attach router info to browser url
|
|
4194
|
+
* @param appName app.name
|
|
4195
|
+
* @param microLocation MicroLocation for sandbox
|
|
4196
|
+
* @param defaultPage default page
|
|
4197
|
+
*/
|
|
3618
4198
|
function initRouteStateWithURL(appName, microLocation, defaultPage) {
|
|
3619
4199
|
const microPath = getMicroPathFromURL(appName);
|
|
3620
4200
|
if (microPath) {
|
|
@@ -3766,7 +4346,7 @@ function useMicroEventSource() {
|
|
|
3766
4346
|
const { createMicroEventSource, clearMicroEventSource } = useMicroEventSource();
|
|
3767
4347
|
const globalPropertyList = ['window', 'self', 'globalThis'];
|
|
3768
4348
|
class SandBox {
|
|
3769
|
-
constructor(appName, url
|
|
4349
|
+
constructor(appName, url) {
|
|
3770
4350
|
/**
|
|
3771
4351
|
* Scoped global Properties(Properties that can only get and set in microAppWindow, will not escape to rawWindow)
|
|
3772
4352
|
* Fix https://github.com/micro-zoe/micro-app/issues/234
|
|
@@ -3791,26 +4371,36 @@ class SandBox {
|
|
|
3791
4371
|
// Rewrite global event listener & timeout
|
|
3792
4372
|
assign(this, effect(appName, this.microAppWindow));
|
|
3793
4373
|
// inject global properties
|
|
3794
|
-
this.initStaticGlobalKeys(this.microAppWindow, appName, url
|
|
4374
|
+
this.initStaticGlobalKeys(this.microAppWindow, appName, url);
|
|
3795
4375
|
}
|
|
3796
|
-
|
|
3797
|
-
|
|
4376
|
+
/**
|
|
4377
|
+
* open sandbox and perform some initial actions
|
|
4378
|
+
* @param umdMode is umd mode
|
|
4379
|
+
* @param baseroute base route for child
|
|
4380
|
+
* @param useMemoryRouter use virtual router
|
|
4381
|
+
* @param defaultPage default page when mount child base on virtual router
|
|
4382
|
+
* @param disablePatchRequest prevent patchRequestApi
|
|
4383
|
+
*/
|
|
4384
|
+
start({ umdMode, baseroute, useMemoryRouter, defaultPage, disablePatchRequest, }) {
|
|
3798
4385
|
if (!this.active) {
|
|
3799
4386
|
this.active = true;
|
|
3800
4387
|
if (useMemoryRouter) {
|
|
4388
|
+
if (isUndefined(this.microAppWindow.location)) {
|
|
4389
|
+
this.setMicroAppRouter(this.microAppWindow, this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.__MICRO_APP_URL__);
|
|
4390
|
+
}
|
|
3801
4391
|
this.initRouteState(defaultPage);
|
|
3802
4392
|
// unique listener of popstate event for sub app
|
|
3803
|
-
this.removeHistoryListener = addHistoryListener(this.
|
|
4393
|
+
this.removeHistoryListener = addHistoryListener(this.microAppWindow.__MICRO_APP_NAME__);
|
|
3804
4394
|
}
|
|
3805
4395
|
else {
|
|
3806
|
-
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ =
|
|
4396
|
+
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
|
|
3807
4397
|
}
|
|
3808
4398
|
/**
|
|
3809
4399
|
* 1. prevent the key deleted during sandBox.stop after rewrite
|
|
3810
4400
|
* 2. umd mode will not delete any keys during sandBox.stop
|
|
3811
4401
|
*/
|
|
3812
4402
|
if (!umdMode) {
|
|
3813
|
-
this.initGlobalKeysWhenStart(this.microAppWindow, this.
|
|
4403
|
+
this.initGlobalKeysWhenStart(this.microAppWindow, this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.__MICRO_APP_URL__, disablePatchRequest);
|
|
3814
4404
|
}
|
|
3815
4405
|
if (++SandBox.activeCount === 1) {
|
|
3816
4406
|
effectDocumentEvent();
|
|
@@ -3821,18 +4411,26 @@ class SandBox {
|
|
|
3821
4411
|
fixBabelPolyfill6();
|
|
3822
4412
|
}
|
|
3823
4413
|
}
|
|
3824
|
-
|
|
4414
|
+
/**
|
|
4415
|
+
* close sandbox and perform some clean up actions
|
|
4416
|
+
* @param umdMode is umd mode
|
|
4417
|
+
* @param keepRouteState prevent reset route
|
|
4418
|
+
* @param clearEventSource clear MicroEventSource when destroy
|
|
4419
|
+
* @param clearData clear data from base app
|
|
4420
|
+
*/
|
|
4421
|
+
stop({ umdMode, keepRouteState, clearEventSource, clearData, }) {
|
|
3825
4422
|
if (this.active) {
|
|
3826
4423
|
this.releaseEffect();
|
|
3827
4424
|
this.microAppWindow.microApp.clearDataListener();
|
|
3828
4425
|
this.microAppWindow.microApp.clearGlobalDataListener();
|
|
4426
|
+
clearData && this.microAppWindow.microApp.clearData();
|
|
3829
4427
|
if (this.removeHistoryListener) {
|
|
3830
4428
|
this.clearRouteState(keepRouteState);
|
|
3831
4429
|
// release listener of popstate
|
|
3832
4430
|
this.removeHistoryListener();
|
|
3833
4431
|
}
|
|
3834
4432
|
if (clearEventSource) {
|
|
3835
|
-
clearMicroEventSource(this.
|
|
4433
|
+
clearMicroEventSource(this.microAppWindow.__MICRO_APP_NAME__);
|
|
3836
4434
|
}
|
|
3837
4435
|
/**
|
|
3838
4436
|
* NOTE:
|
|
@@ -3883,9 +4481,9 @@ class SandBox {
|
|
|
3883
4481
|
getSpecialProperties(appName) {
|
|
3884
4482
|
var _a;
|
|
3885
4483
|
this.scopeProperties = this.scopeProperties.concat(this.adapter.staticScopeProperties);
|
|
3886
|
-
if (isPlainObject(microApp.plugins)) {
|
|
3887
|
-
this.commonActionForSpecialProperties(microApp.plugins.global);
|
|
3888
|
-
this.commonActionForSpecialProperties((_a = microApp.plugins.modules) === null || _a === void 0 ? void 0 : _a[appName]);
|
|
4484
|
+
if (isPlainObject(microApp.options.plugins)) {
|
|
4485
|
+
this.commonActionForSpecialProperties(microApp.options.plugins.global);
|
|
4486
|
+
this.commonActionForSpecialProperties((_a = microApp.options.plugins.modules) === null || _a === void 0 ? void 0 : _a[appName]);
|
|
3889
4487
|
}
|
|
3890
4488
|
}
|
|
3891
4489
|
// common action for global plugins and module plugins
|
|
@@ -4003,7 +4601,7 @@ class SandBox {
|
|
|
4003
4601
|
* @param url app url
|
|
4004
4602
|
* @param useMemoryRouter whether use memory router
|
|
4005
4603
|
*/
|
|
4006
|
-
initStaticGlobalKeys(microAppWindow, appName, url
|
|
4604
|
+
initStaticGlobalKeys(microAppWindow, appName, url) {
|
|
4007
4605
|
microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
|
|
4008
4606
|
microAppWindow.__MICRO_APP_NAME__ = appName;
|
|
4009
4607
|
microAppWindow.__MICRO_APP_URL__ = url;
|
|
@@ -4018,8 +4616,6 @@ class SandBox {
|
|
|
4018
4616
|
});
|
|
4019
4617
|
this.setProxyDocument(microAppWindow, appName);
|
|
4020
4618
|
this.setMappingPropertiesWithRawDescriptor(microAppWindow);
|
|
4021
|
-
if (useMemoryRouter)
|
|
4022
|
-
this.setMicroAppRouter(microAppWindow, appName, url);
|
|
4023
4619
|
}
|
|
4024
4620
|
setProxyDocument(microAppWindow, appName) {
|
|
4025
4621
|
const { proxyDocument, MicroDocument } = this.createProxyDocument(appName);
|
|
@@ -4197,17 +4793,19 @@ class SandBox {
|
|
|
4197
4793
|
return element;
|
|
4198
4794
|
};
|
|
4199
4795
|
const proxyDocument = new Proxy(rawDocument, {
|
|
4200
|
-
get(target, key) {
|
|
4796
|
+
get: (target, key) => {
|
|
4201
4797
|
throttleDeferForSetAppName(appName);
|
|
4202
4798
|
throttleDeferForParentNode(proxyDocument);
|
|
4203
4799
|
if (key === 'createElement')
|
|
4204
4800
|
return createElement;
|
|
4205
4801
|
if (key === Symbol.toStringTag)
|
|
4206
4802
|
return 'ProxyDocument';
|
|
4803
|
+
if (key === 'defaultView')
|
|
4804
|
+
return this.proxyWindow;
|
|
4207
4805
|
const rawValue = Reflect.get(target, key);
|
|
4208
4806
|
return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
|
|
4209
4807
|
},
|
|
4210
|
-
set(target, key, value) {
|
|
4808
|
+
set: (target, key, value) => {
|
|
4211
4809
|
// Fix TypeError: Illegal invocation when set document.title
|
|
4212
4810
|
Reflect.set(target, key, value);
|
|
4213
4811
|
/**
|
|
@@ -4299,10 +4897,8 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
|
|
|
4299
4897
|
});
|
|
4300
4898
|
formatEventInfo(event, element);
|
|
4301
4899
|
// global hooks
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
// @ts-ignore
|
|
4305
|
-
microApp.lifeCycles[lifecycleName](event);
|
|
4900
|
+
if (isFunction((_a = microApp.options.lifeCycles) === null || _a === void 0 ? void 0 : _a[lifecycleName])) {
|
|
4901
|
+
microApp.options.lifeCycles[lifecycleName](event);
|
|
4306
4902
|
}
|
|
4307
4903
|
element.dispatchEvent(event);
|
|
4308
4904
|
}
|
|
@@ -4322,7 +4918,7 @@ function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
|
|
|
4322
4918
|
// micro app instances
|
|
4323
4919
|
const appInstanceMap = new Map();
|
|
4324
4920
|
class CreateApp {
|
|
4325
|
-
constructor({ name, url,
|
|
4921
|
+
constructor({ name, url, container, scopecss, useSandbox, inline, esmodule, ssrUrl, isPrefetch, }) {
|
|
4326
4922
|
this.state = appStates.CREATED;
|
|
4327
4923
|
this.keepAliveState = null;
|
|
4328
4924
|
this.keepAliveContainer = null;
|
|
@@ -4331,30 +4927,26 @@ class CreateApp {
|
|
|
4331
4927
|
this.umdHookUnmount = null;
|
|
4332
4928
|
this.libraryName = null;
|
|
4333
4929
|
this.umdMode = false;
|
|
4334
|
-
this.isPrefetch = false;
|
|
4335
|
-
this.prefetchResolve = null;
|
|
4336
|
-
this.container = null;
|
|
4337
4930
|
this.sandBox = null;
|
|
4931
|
+
this.keepRouteState = false;
|
|
4932
|
+
this.fiber = false;
|
|
4933
|
+
this.useMemoryRouter = true;
|
|
4338
4934
|
this.name = name;
|
|
4339
4935
|
this.url = url;
|
|
4340
4936
|
this.useSandbox = useSandbox;
|
|
4341
4937
|
this.scopecss = this.useSandbox && scopecss;
|
|
4342
|
-
this.
|
|
4343
|
-
|
|
4938
|
+
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
4939
|
+
this.esmodule = esmodule !== null && esmodule !== void 0 ? esmodule : false;
|
|
4940
|
+
// not exist when prefetch 👇
|
|
4344
4941
|
this.container = container !== null && container !== void 0 ? container : null;
|
|
4345
4942
|
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
4346
|
-
|
|
4347
|
-
this.
|
|
4348
|
-
|
|
4349
|
-
this.
|
|
4350
|
-
this.
|
|
4351
|
-
this.disablePatchRequest = disablePatchRequest !== null && disablePatchRequest !== void 0 ? disablePatchRequest : false;
|
|
4352
|
-
this.source = {
|
|
4353
|
-
links: new Map(),
|
|
4354
|
-
scripts: new Map(),
|
|
4355
|
-
};
|
|
4943
|
+
// not exist when normal 👇
|
|
4944
|
+
this.isPrefetch = isPrefetch !== null && isPrefetch !== void 0 ? isPrefetch : false;
|
|
4945
|
+
// init actions
|
|
4946
|
+
appInstanceMap.set(this.name, this);
|
|
4947
|
+
this.source = { html: null, links: new Set(), scripts: new Set() };
|
|
4356
4948
|
this.loadSourceCode();
|
|
4357
|
-
this.useSandbox && (this.sandBox = new SandBox(name, url
|
|
4949
|
+
this.useSandbox && (this.sandBox = new SandBox(name, url));
|
|
4358
4950
|
}
|
|
4359
4951
|
// Load resources
|
|
4360
4952
|
loadSourceCode() {
|
|
@@ -4365,16 +4957,12 @@ class CreateApp {
|
|
|
4365
4957
|
* When resource is loaded, mount app if it is not prefetch or unmount
|
|
4366
4958
|
*/
|
|
4367
4959
|
onLoad(html) {
|
|
4368
|
-
var _a;
|
|
4369
4960
|
if (++this.loadSourceLevel === 2) {
|
|
4370
4961
|
this.source.html = html;
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
else if (appStates.UNMOUNT !== this.state) {
|
|
4376
|
-
this.state = appStates.LOADED;
|
|
4377
|
-
this.mount();
|
|
4962
|
+
this.state = appStates.LOADED;
|
|
4963
|
+
if (!this.isPrefetch && appStates.UNMOUNT !== this.state) {
|
|
4964
|
+
// @ts-ignore
|
|
4965
|
+
getRootContainer(this.container).mount(this);
|
|
4378
4966
|
}
|
|
4379
4967
|
}
|
|
4380
4968
|
}
|
|
@@ -4384,10 +4972,6 @@ class CreateApp {
|
|
|
4384
4972
|
*/
|
|
4385
4973
|
onLoadError(e) {
|
|
4386
4974
|
this.loadSourceLevel = -1;
|
|
4387
|
-
if (this.prefetchResolve) {
|
|
4388
|
-
this.prefetchResolve();
|
|
4389
|
-
this.prefetchResolve = null;
|
|
4390
|
-
}
|
|
4391
4975
|
if (appStates.UNMOUNT !== this.state) {
|
|
4392
4976
|
this.onerror(e);
|
|
4393
4977
|
this.state = appStates.LOAD_FAILED;
|
|
@@ -4401,15 +4985,16 @@ class CreateApp {
|
|
|
4401
4985
|
* @param keepRouteState keep route state when unmount, default is false
|
|
4402
4986
|
* @param disablePatchRequest prevent rewrite request method of child app
|
|
4403
4987
|
*/
|
|
4404
|
-
mount(container, inline, baseroute, keepRouteState, defaultPage,
|
|
4405
|
-
var _a, _b
|
|
4406
|
-
this.
|
|
4407
|
-
this.
|
|
4408
|
-
this.
|
|
4409
|
-
this.
|
|
4410
|
-
this.
|
|
4411
|
-
|
|
4412
|
-
this.
|
|
4988
|
+
mount({ container, inline, esmodule, useMemoryRouter, baseroute, keepRouteState, defaultPage, disablePatchRequest, fiber, }) {
|
|
4989
|
+
var _a, _b;
|
|
4990
|
+
this.container = container;
|
|
4991
|
+
this.inline = inline;
|
|
4992
|
+
this.esmodule = esmodule;
|
|
4993
|
+
this.keepRouteState = keepRouteState;
|
|
4994
|
+
this.fiber = fiber;
|
|
4995
|
+
// use in sandbox/effect
|
|
4996
|
+
this.useMemoryRouter = useMemoryRouter;
|
|
4997
|
+
// this.hiddenRouter = hiddenRouter ?? this.hiddenRouter
|
|
4413
4998
|
if (this.loadSourceLevel !== 2) {
|
|
4414
4999
|
this.state = appStates.LOADING;
|
|
4415
5000
|
return;
|
|
@@ -4417,24 +5002,34 @@ class CreateApp {
|
|
|
4417
5002
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
|
|
4418
5003
|
this.state = appStates.MOUNTING;
|
|
4419
5004
|
cloneContainer(this.source.html, this.container, !this.umdMode);
|
|
4420
|
-
(
|
|
5005
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.start({
|
|
5006
|
+
umdMode: this.umdMode,
|
|
5007
|
+
baseroute,
|
|
5008
|
+
useMemoryRouter,
|
|
5009
|
+
defaultPage,
|
|
5010
|
+
disablePatchRequest,
|
|
5011
|
+
});
|
|
4421
5012
|
let umdHookMountResult; // result of mount function
|
|
4422
5013
|
if (!this.umdMode) {
|
|
4423
5014
|
let hasDispatchMountedEvent = false;
|
|
4424
5015
|
// if all js are executed, param isFinished will be true
|
|
4425
|
-
execScripts(this
|
|
5016
|
+
execScripts(this, (isFinished) => {
|
|
4426
5017
|
if (!this.umdMode) {
|
|
4427
5018
|
const { mount, unmount } = this.getUmdLibraryHooks();
|
|
5019
|
+
/**
|
|
5020
|
+
* umdHookUnmount can works in non UMD mode
|
|
5021
|
+
* register with window.unmount
|
|
5022
|
+
*/
|
|
5023
|
+
this.umdHookUnmount = unmount;
|
|
4428
5024
|
// if mount & unmount is function, the sub app is umd mode
|
|
4429
5025
|
if (isFunction(mount) && isFunction(unmount)) {
|
|
4430
5026
|
this.umdHookMount = mount;
|
|
4431
|
-
this.umdHookUnmount = unmount;
|
|
4432
5027
|
this.umdMode = true;
|
|
4433
5028
|
if (this.sandBox)
|
|
4434
5029
|
this.sandBox.proxyWindow.__MICRO_APP_UMD_MODE__ = true;
|
|
4435
5030
|
// this.sandBox?.recordUmdSnapshot()
|
|
4436
5031
|
try {
|
|
4437
|
-
umdHookMountResult = this.umdHookMount();
|
|
5032
|
+
umdHookMountResult = this.umdHookMount(microApp.getData(this.name, true));
|
|
4438
5033
|
}
|
|
4439
5034
|
catch (e) {
|
|
4440
5035
|
logError('an error occurred in the mount function \n', this.name, e);
|
|
@@ -4448,7 +5043,7 @@ class CreateApp {
|
|
|
4448
5043
|
});
|
|
4449
5044
|
}
|
|
4450
5045
|
else {
|
|
4451
|
-
(
|
|
5046
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.rebuildUmdSnapshot();
|
|
4452
5047
|
try {
|
|
4453
5048
|
umdHookMountResult = this.umdHookMount();
|
|
4454
5049
|
}
|
|
@@ -4478,6 +5073,9 @@ class CreateApp {
|
|
|
4478
5073
|
dispatchMountedEvent() {
|
|
4479
5074
|
if (appStates.UNMOUNT !== this.state) {
|
|
4480
5075
|
this.state = appStates.MOUNTED;
|
|
5076
|
+
// call window.onmount of child app
|
|
5077
|
+
callFnWithTryCatch(this.getGlobalEventListener(microGlobalEvent.ONMOUNT), this.name, `window.${microGlobalEvent.ONMOUNT}`, microApp.getData(this.name, true));
|
|
5078
|
+
// dispatch event mounted to parent
|
|
4481
5079
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.MOUNTED);
|
|
4482
5080
|
}
|
|
4483
5081
|
}
|
|
@@ -4487,7 +5085,7 @@ class CreateApp {
|
|
|
4487
5085
|
* @param destroy completely destroy, delete cache resources
|
|
4488
5086
|
* @param unmountcb callback of unmount
|
|
4489
5087
|
*/
|
|
4490
|
-
unmount(destroy, unmountcb) {
|
|
5088
|
+
unmount({ destroy, clearData, unmountcb, }) {
|
|
4491
5089
|
if (this.state === appStates.LOAD_FAILED) {
|
|
4492
5090
|
destroy = true;
|
|
4493
5091
|
}
|
|
@@ -4500,17 +5098,19 @@ class CreateApp {
|
|
|
4500
5098
|
* send an unmount event to the micro app or call umd unmount hook
|
|
4501
5099
|
* before the sandbox is cleared
|
|
4502
5100
|
*/
|
|
4503
|
-
if (this.umdHookUnmount) {
|
|
5101
|
+
if (isFunction(this.umdHookUnmount)) {
|
|
4504
5102
|
try {
|
|
4505
|
-
umdHookUnmountResult = this.umdHookUnmount();
|
|
5103
|
+
umdHookUnmountResult = this.umdHookUnmount(microApp.getData(this.name, true));
|
|
4506
5104
|
}
|
|
4507
5105
|
catch (e) {
|
|
4508
5106
|
logError('an error occurred in the unmount function \n', this.name, e);
|
|
4509
5107
|
}
|
|
4510
5108
|
}
|
|
5109
|
+
// call window.onunmount of child app
|
|
5110
|
+
callFnWithTryCatch(this.getGlobalEventListener(microGlobalEvent.ONUNMOUNT), this.name, `window.${microGlobalEvent.ONUNMOUNT}`);
|
|
4511
5111
|
// dispatch unmount event to micro app
|
|
4512
5112
|
dispatchCustomEventToMicroApp('unmount', this.name);
|
|
4513
|
-
this.handleUnmounted(destroy, umdHookUnmountResult, unmountcb);
|
|
5113
|
+
this.handleUnmounted(destroy, clearData, umdHookUnmountResult, unmountcb);
|
|
4514
5114
|
}
|
|
4515
5115
|
/**
|
|
4516
5116
|
* handle for promise umdHookUnmount
|
|
@@ -4518,14 +5118,14 @@ class CreateApp {
|
|
|
4518
5118
|
* @param umdHookUnmountResult result of umdHookUnmount
|
|
4519
5119
|
* @param unmountcb callback of unmount
|
|
4520
5120
|
*/
|
|
4521
|
-
handleUnmounted(destroy, umdHookUnmountResult, unmountcb) {
|
|
5121
|
+
handleUnmounted(destroy, clearData, umdHookUnmountResult, unmountcb) {
|
|
4522
5122
|
if (isPromise(umdHookUnmountResult)) {
|
|
4523
5123
|
umdHookUnmountResult
|
|
4524
|
-
.then(() => this.actionsForUnmount(destroy, unmountcb))
|
|
4525
|
-
.catch(() => this.actionsForUnmount(destroy, unmountcb));
|
|
5124
|
+
.then(() => this.actionsForUnmount(destroy, clearData, unmountcb))
|
|
5125
|
+
.catch(() => this.actionsForUnmount(destroy, clearData, unmountcb));
|
|
4526
5126
|
}
|
|
4527
5127
|
else {
|
|
4528
|
-
this.actionsForUnmount(destroy, unmountcb);
|
|
5128
|
+
this.actionsForUnmount(destroy, clearData, unmountcb);
|
|
4529
5129
|
}
|
|
4530
5130
|
}
|
|
4531
5131
|
/**
|
|
@@ -4533,7 +5133,7 @@ class CreateApp {
|
|
|
4533
5133
|
* @param destroy completely destroy, delete cache resources
|
|
4534
5134
|
* @param unmountcb callback of unmount
|
|
4535
5135
|
*/
|
|
4536
|
-
actionsForUnmount(destroy, unmountcb) {
|
|
5136
|
+
actionsForUnmount(destroy, clearData, unmountcb) {
|
|
4537
5137
|
var _a, _b;
|
|
4538
5138
|
if (destroy) {
|
|
4539
5139
|
this.actionsForCompletelyDestroy();
|
|
@@ -4544,13 +5144,21 @@ class CreateApp {
|
|
|
4544
5144
|
if (this.umdMode) {
|
|
4545
5145
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.recordUmdSnapshot();
|
|
4546
5146
|
}
|
|
5147
|
+
if (clearData || destroy) {
|
|
5148
|
+
microApp.clearData(this.name);
|
|
5149
|
+
}
|
|
4547
5150
|
/**
|
|
4548
5151
|
* this.container maybe contains micro-app element, stop sandbox should exec after cloneContainer
|
|
4549
5152
|
* NOTE:
|
|
4550
5153
|
* 1. if destroy is true, clear route state
|
|
4551
5154
|
* 2. umd mode and keep-alive will not clear EventSource
|
|
4552
5155
|
*/
|
|
4553
|
-
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.stop(
|
|
5156
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.stop({
|
|
5157
|
+
umdMode: this.umdMode,
|
|
5158
|
+
keepRouteState: this.keepRouteState && !destroy,
|
|
5159
|
+
clearEventSource: !this.umdMode || destroy,
|
|
5160
|
+
clearData: clearData || destroy,
|
|
5161
|
+
});
|
|
4554
5162
|
if (!getActiveApps().length) {
|
|
4555
5163
|
releasePatchSetAttribute();
|
|
4556
5164
|
}
|
|
@@ -4565,10 +5173,11 @@ class CreateApp {
|
|
|
4565
5173
|
if (!this.useSandbox && this.umdMode) {
|
|
4566
5174
|
delete window[this.libraryName];
|
|
4567
5175
|
}
|
|
5176
|
+
sourceCenter.script.deleteInlineInfo(this.source.scripts);
|
|
4568
5177
|
appInstanceMap.delete(this.name);
|
|
4569
5178
|
}
|
|
4570
5179
|
// hidden app when disconnectedCallback called with keep-alive
|
|
4571
|
-
hiddenKeepAliveApp() {
|
|
5180
|
+
hiddenKeepAliveApp(callback) {
|
|
4572
5181
|
var _a;
|
|
4573
5182
|
const oldContainer = this.container;
|
|
4574
5183
|
cloneContainer(this.container, this.keepAliveContainer ? this.keepAliveContainer : (this.keepAliveContainer = document.createElement('div')), false);
|
|
@@ -4583,6 +5192,7 @@ class CreateApp {
|
|
|
4583
5192
|
dispatchLifecyclesEvent(oldContainer, this.name, lifeCycles.AFTERHIDDEN);
|
|
4584
5193
|
// called after lifeCyclesEvent
|
|
4585
5194
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.removeRouteInfoForKeepAliveApp();
|
|
5195
|
+
callback && callback();
|
|
4586
5196
|
}
|
|
4587
5197
|
// show app when connectedCallback called with keep-alive
|
|
4588
5198
|
showKeepAliveApp(container) {
|
|
@@ -4622,16 +5232,27 @@ class CreateApp {
|
|
|
4622
5232
|
}
|
|
4623
5233
|
// get umd library, if it not exist, return empty object
|
|
4624
5234
|
getUmdLibraryHooks() {
|
|
4625
|
-
var _a, _b;
|
|
5235
|
+
var _a, _b, _c, _d;
|
|
4626
5236
|
// after execScripts, the app maybe unmounted
|
|
4627
5237
|
if (appStates.UNMOUNT !== this.state) {
|
|
4628
5238
|
const global = ((_b = (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow) !== null && _b !== void 0 ? _b : globalEnv.rawWindow);
|
|
4629
5239
|
this.libraryName = getRootContainer(this.container).getAttribute('library') || `micro-app-${this.name}`;
|
|
4630
|
-
|
|
4631
|
-
|
|
5240
|
+
if (isObject(global[this.libraryName])) {
|
|
5241
|
+
return global[this.libraryName];
|
|
5242
|
+
}
|
|
5243
|
+
return {
|
|
5244
|
+
mount: (_c = this.sandBox) === null || _c === void 0 ? void 0 : _c.proxyWindow.mount,
|
|
5245
|
+
unmount: (_d = this.sandBox) === null || _d === void 0 ? void 0 : _d.proxyWindow.unmount,
|
|
5246
|
+
};
|
|
4632
5247
|
}
|
|
4633
5248
|
return {};
|
|
4634
5249
|
}
|
|
5250
|
+
getGlobalEventListener(eventName) {
|
|
5251
|
+
var _a;
|
|
5252
|
+
// @ts-ignore
|
|
5253
|
+
const listener = (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow[eventName];
|
|
5254
|
+
return isFunction(listener) ? listener : null;
|
|
5255
|
+
}
|
|
4635
5256
|
}
|
|
4636
5257
|
|
|
4637
5258
|
/**
|
|
@@ -4644,7 +5265,8 @@ function defineElement(tagName) {
|
|
|
4644
5265
|
super();
|
|
4645
5266
|
this.isWaiting = false;
|
|
4646
5267
|
this.cacheData = null;
|
|
4647
|
-
this.
|
|
5268
|
+
this.connectedCount = 0;
|
|
5269
|
+
this.connectStateMap = new Map();
|
|
4648
5270
|
this.appName = ''; // app name
|
|
4649
5271
|
this.appUrl = ''; // app url
|
|
4650
5272
|
this.ssrUrl = ''; // html path in ssr mode
|
|
@@ -4654,6 +5276,8 @@ function defineElement(tagName) {
|
|
|
4654
5276
|
*/
|
|
4655
5277
|
this.handleAttributeUpdate = () => {
|
|
4656
5278
|
this.isWaiting = false;
|
|
5279
|
+
if (!this.connectStateMap.get(this.connectedCount))
|
|
5280
|
+
return;
|
|
4657
5281
|
const formatAttrName = formatAppName(this.getAttribute('name'));
|
|
4658
5282
|
const formatAttrUrl = formatAppURL(this.getAttribute('url'), this.appName);
|
|
4659
5283
|
if (this.legalAttribute('name', formatAttrName) && this.legalAttribute('url', formatAttrUrl)) {
|
|
@@ -4664,7 +5288,7 @@ function defineElement(tagName) {
|
|
|
4664
5288
|
keepAliveStates.KEEP_ALIVE_HIDDEN !== existApp.getKeepAliveState() &&
|
|
4665
5289
|
!existApp.isPrefetch) {
|
|
4666
5290
|
this.setAttribute('name', this.appName);
|
|
4667
|
-
return logError(`app name conflict, an app named ${formatAttrName} is running
|
|
5291
|
+
return logError(`app name conflict, an app named ${formatAttrName} is running`);
|
|
4668
5292
|
}
|
|
4669
5293
|
}
|
|
4670
5294
|
if (formatAttrName !== this.appName || formatAttrUrl !== this.appUrl) {
|
|
@@ -4705,22 +5329,56 @@ function defineElement(tagName) {
|
|
|
4705
5329
|
// baseRoute: route prefix, default is ''
|
|
4706
5330
|
// keep-alive: open keep-alive mode
|
|
4707
5331
|
connectedCallback() {
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
5332
|
+
const cacheCount = ++this.connectedCount;
|
|
5333
|
+
this.connectStateMap.set(cacheCount, true);
|
|
5334
|
+
/**
|
|
5335
|
+
* In some special scenes, such as vue's keep-alive, the micro-app will be inserted and deleted twice in an instant
|
|
5336
|
+
* So we execute the mount method async and record connectState to prevent repeated rendering
|
|
5337
|
+
*/
|
|
5338
|
+
defer(() => {
|
|
5339
|
+
if (this.connectStateMap.get(cacheCount)) {
|
|
5340
|
+
dispatchLifecyclesEvent(this, this.appName, lifeCycles.CREATED);
|
|
5341
|
+
this.handleConnected();
|
|
5342
|
+
}
|
|
5343
|
+
});
|
|
4711
5344
|
}
|
|
4712
5345
|
disconnectedCallback() {
|
|
4713
|
-
this.
|
|
5346
|
+
this.connectStateMap.set(this.connectedCount, false);
|
|
5347
|
+
this.handleDisconnected();
|
|
5348
|
+
}
|
|
5349
|
+
/**
|
|
5350
|
+
* Re render app from the command line
|
|
5351
|
+
* MicroAppElement.reload(destroy)
|
|
5352
|
+
*/
|
|
5353
|
+
reload(destroy) {
|
|
5354
|
+
return new Promise((resolve) => {
|
|
5355
|
+
const handleAfterReload = () => {
|
|
5356
|
+
this.removeEventListener(lifeCycles.MOUNTED, handleAfterReload);
|
|
5357
|
+
this.removeEventListener(lifeCycles.AFTERSHOW, handleAfterReload);
|
|
5358
|
+
resolve(true);
|
|
5359
|
+
};
|
|
5360
|
+
this.addEventListener(lifeCycles.MOUNTED, handleAfterReload);
|
|
5361
|
+
this.addEventListener(lifeCycles.AFTERSHOW, handleAfterReload);
|
|
5362
|
+
this.handleDisconnected(destroy, () => {
|
|
5363
|
+
this.handleConnected();
|
|
5364
|
+
});
|
|
5365
|
+
});
|
|
5366
|
+
}
|
|
5367
|
+
/**
|
|
5368
|
+
* common action for unmount
|
|
5369
|
+
* @param destroy reload param
|
|
5370
|
+
*/
|
|
5371
|
+
handleDisconnected(destroy = false, callback) {
|
|
4714
5372
|
const app = appInstanceMap.get(this.appName);
|
|
4715
5373
|
if (app &&
|
|
4716
5374
|
app.getAppState() !== appStates.UNMOUNT &&
|
|
4717
5375
|
app.getKeepAliveState() !== keepAliveStates.KEEP_ALIVE_HIDDEN) {
|
|
4718
5376
|
// keep-alive
|
|
4719
|
-
if (this.getKeepAliveModeResult()) {
|
|
4720
|
-
this.handleHiddenKeepAliveApp();
|
|
5377
|
+
if (this.getKeepAliveModeResult() && !destroy) {
|
|
5378
|
+
this.handleHiddenKeepAliveApp(callback);
|
|
4721
5379
|
}
|
|
4722
5380
|
else {
|
|
4723
|
-
this.handleUnmount(this.getDestroyCompatibleResult());
|
|
5381
|
+
this.handleUnmount(destroy || this.getDestroyCompatibleResult(), callback);
|
|
4724
5382
|
}
|
|
4725
5383
|
}
|
|
4726
5384
|
}
|
|
@@ -4758,12 +5416,12 @@ function defineElement(tagName) {
|
|
|
4758
5416
|
}
|
|
4759
5417
|
// handle for connectedCallback run before attributeChangedCallback
|
|
4760
5418
|
handleInitialNameAndUrl() {
|
|
4761
|
-
this.
|
|
5419
|
+
this.connectStateMap.get(this.connectedCount) && this.handleConnected();
|
|
4762
5420
|
}
|
|
4763
5421
|
/**
|
|
4764
5422
|
* first mount of this app
|
|
4765
5423
|
*/
|
|
4766
|
-
|
|
5424
|
+
handleConnected() {
|
|
4767
5425
|
if (!this.appName || !this.appUrl)
|
|
4768
5426
|
return;
|
|
4769
5427
|
if (this.getDisposeResult('shadowDOM') && !this.shadowRoot && isFunction(this.attachShadow)) {
|
|
@@ -4773,26 +5431,35 @@ function defineElement(tagName) {
|
|
|
4773
5431
|
if (appInstanceMap.has(this.appName)) {
|
|
4774
5432
|
const app = appInstanceMap.get(this.appName);
|
|
4775
5433
|
const existAppUrl = app.ssrUrl || app.url;
|
|
4776
|
-
const
|
|
4777
|
-
|
|
4778
|
-
|
|
5434
|
+
const targetAppUrl = this.ssrUrl || this.appUrl;
|
|
5435
|
+
/**
|
|
5436
|
+
* NOTE:
|
|
5437
|
+
* 1. keep-alive don't care about ssrUrl
|
|
5438
|
+
* 2. Even if the keep-alive app is pushed into the background, it is still active and cannot be replaced. Otherwise, it is difficult for developers to troubleshoot in case of conflict and will leave developers at a loss
|
|
5439
|
+
* 3. When scopecss, useSandbox of prefetch app different from target app, delete prefetch app and create new one
|
|
5440
|
+
*/
|
|
4779
5441
|
if (app.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN &&
|
|
4780
5442
|
app.url === this.appUrl) {
|
|
4781
5443
|
this.handleShowKeepAliveApp(app);
|
|
4782
5444
|
}
|
|
4783
|
-
else if (existAppUrl ===
|
|
4784
|
-
app.
|
|
5445
|
+
else if (existAppUrl === targetAppUrl && (app.getAppState() === appStates.UNMOUNT ||
|
|
5446
|
+
(app.isPrefetch && (app.scopecss === this.isScopecss() &&
|
|
5447
|
+
app.useSandbox === this.isSandbox())))) {
|
|
4785
5448
|
this.handleAppMount(app);
|
|
4786
5449
|
}
|
|
4787
5450
|
else if (app.isPrefetch || app.getAppState() === appStates.UNMOUNT) {
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
5451
|
+
if (process.env.NODE_ENV !== 'production' &&
|
|
5452
|
+
app.scopecss === this.isScopecss() &&
|
|
5453
|
+
app.useSandbox === this.isSandbox()) {
|
|
5454
|
+
/**
|
|
5455
|
+
* url is different & old app is unmounted or prefetch, create new app to replace old one
|
|
5456
|
+
*/
|
|
5457
|
+
logWarn(`the ${app.isPrefetch ? 'prefetch' : 'unmounted'} app with url: ${existAppUrl} replaced by a new app with url: ${targetAppUrl}`, this.appName);
|
|
5458
|
+
}
|
|
4792
5459
|
this.handleCreateApp();
|
|
4793
5460
|
}
|
|
4794
5461
|
else {
|
|
4795
|
-
logError(`app name conflict, an app named ${this.appName} is running
|
|
5462
|
+
logError(`app name conflict, an app named: ${this.appName} with url: ${existAppUrl} is running`);
|
|
4796
5463
|
}
|
|
4797
5464
|
}
|
|
4798
5465
|
else {
|
|
@@ -4827,7 +5494,7 @@ function defineElement(tagName) {
|
|
|
4827
5494
|
}
|
|
4828
5495
|
else {
|
|
4829
5496
|
// the hidden keep-alive app is still active
|
|
4830
|
-
logError(`app name conflict, an app named ${this.appName} is running
|
|
5497
|
+
logError(`app name conflict, an app named ${this.appName} is running`);
|
|
4831
5498
|
}
|
|
4832
5499
|
}
|
|
4833
5500
|
else if (existApp.url === this.appUrl && existApp.ssrUrl === this.ssrUrl) {
|
|
@@ -4854,20 +5521,6 @@ function defineElement(tagName) {
|
|
|
4854
5521
|
}
|
|
4855
5522
|
return true;
|
|
4856
5523
|
}
|
|
4857
|
-
/**
|
|
4858
|
-
* mount app
|
|
4859
|
-
* some serious note before mount:
|
|
4860
|
-
* 1. is prefetch ?
|
|
4861
|
-
* 2. is remount in another container ?
|
|
4862
|
-
* 3. is remount with change properties of the container ?
|
|
4863
|
-
*/
|
|
4864
|
-
handleAppMount(app) {
|
|
4865
|
-
app.isPrefetch = false;
|
|
4866
|
-
defer(() => {
|
|
4867
|
-
var _a;
|
|
4868
|
-
return app.mount((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this, this.getDisposeResult('inline'), this.getBaseRouteCompatible(), this.getDisposeResult('keep-router-state'), this.getDefaultPageValue(), this.getDisposeResult('hidden-router'), this.getDisposeResult('disable-patch-request'));
|
|
4869
|
-
});
|
|
4870
|
-
}
|
|
4871
5524
|
// create app instance
|
|
4872
5525
|
handleCreateApp() {
|
|
4873
5526
|
var _a;
|
|
@@ -4878,41 +5531,69 @@ function defineElement(tagName) {
|
|
|
4878
5531
|
if (appInstanceMap.has(this.appName)) {
|
|
4879
5532
|
appInstanceMap.get(this.appName).actionsForCompletelyDestroy();
|
|
4880
5533
|
}
|
|
4881
|
-
|
|
5534
|
+
new CreateApp({
|
|
4882
5535
|
name: this.appName,
|
|
4883
5536
|
url: this.appUrl,
|
|
5537
|
+
scopecss: this.isScopecss(),
|
|
5538
|
+
useSandbox: this.isSandbox(),
|
|
5539
|
+
inline: this.getDisposeResult('inline'),
|
|
5540
|
+
esmodule: this.getDisposeResult('esmodule'),
|
|
5541
|
+
container: (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this,
|
|
4884
5542
|
ssrUrl: this.ssrUrl,
|
|
5543
|
+
});
|
|
5544
|
+
}
|
|
5545
|
+
/**
|
|
5546
|
+
* mount app
|
|
5547
|
+
* some serious note before mount:
|
|
5548
|
+
* 1. is prefetch ?
|
|
5549
|
+
* 2. is remount in another container ?
|
|
5550
|
+
* 3. is remount with change properties of the container ?
|
|
5551
|
+
*/
|
|
5552
|
+
handleAppMount(app) {
|
|
5553
|
+
app.isPrefetch = false;
|
|
5554
|
+
defer(() => this.mount(app));
|
|
5555
|
+
}
|
|
5556
|
+
/**
|
|
5557
|
+
* public mount action for micro_app_element & create_app
|
|
5558
|
+
*/
|
|
5559
|
+
mount(app) {
|
|
5560
|
+
var _a;
|
|
5561
|
+
app.mount({
|
|
4885
5562
|
container: (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this,
|
|
4886
5563
|
inline: this.getDisposeResult('inline'),
|
|
4887
|
-
|
|
4888
|
-
useSandbox: !this.getDisposeResult('disable-sandbox'),
|
|
5564
|
+
esmodule: this.getDisposeResult('esmodule'),
|
|
4889
5565
|
useMemoryRouter: !this.getDisposeResult('disable-memory-router'),
|
|
4890
5566
|
baseroute: this.getBaseRouteCompatible(),
|
|
4891
5567
|
keepRouteState: this.getDisposeResult('keep-router-state'),
|
|
4892
5568
|
defaultPage: this.getDefaultPageValue(),
|
|
4893
5569
|
hiddenRouter: this.getDisposeResult('hidden-router'),
|
|
4894
5570
|
disablePatchRequest: this.getDisposeResult('disable-patch-request'),
|
|
5571
|
+
fiber: this.getDisposeResult('fiber'),
|
|
4895
5572
|
});
|
|
4896
|
-
appInstanceMap.set(this.appName, instance);
|
|
4897
5573
|
}
|
|
4898
5574
|
/**
|
|
4899
5575
|
* unmount app
|
|
4900
5576
|
* @param destroy delete cache resources when unmount
|
|
4901
5577
|
*/
|
|
4902
|
-
handleUnmount(destroy,
|
|
5578
|
+
handleUnmount(destroy, unmountcb) {
|
|
4903
5579
|
const app = appInstanceMap.get(this.appName);
|
|
4904
5580
|
if (app &&
|
|
4905
5581
|
app.getAppState() !== appStates.UNMOUNT) {
|
|
4906
|
-
app.unmount(
|
|
5582
|
+
app.unmount({
|
|
5583
|
+
destroy,
|
|
5584
|
+
clearData: this.getDisposeResult('clear-data'),
|
|
5585
|
+
unmountcb,
|
|
5586
|
+
});
|
|
4907
5587
|
}
|
|
4908
5588
|
}
|
|
4909
5589
|
// hidden app when disconnectedCallback called with keep-alive
|
|
4910
|
-
handleHiddenKeepAliveApp() {
|
|
5590
|
+
handleHiddenKeepAliveApp(callback) {
|
|
4911
5591
|
const app = appInstanceMap.get(this.appName);
|
|
4912
5592
|
if (app &&
|
|
4913
5593
|
app.getAppState() !== appStates.UNMOUNT &&
|
|
4914
|
-
app.getKeepAliveState() !== keepAliveStates.KEEP_ALIVE_HIDDEN)
|
|
4915
|
-
app.hiddenKeepAliveApp();
|
|
5594
|
+
app.getKeepAliveState() !== keepAliveStates.KEEP_ALIVE_HIDDEN) {
|
|
5595
|
+
app.hiddenKeepAliveApp(callback);
|
|
5596
|
+
}
|
|
4916
5597
|
}
|
|
4917
5598
|
// show app when connectedCallback called with keep-alive
|
|
4918
5599
|
handleShowKeepAliveApp(app) {
|
|
@@ -4925,8 +5606,7 @@ function defineElement(tagName) {
|
|
|
4925
5606
|
* @param name Configuration item name
|
|
4926
5607
|
*/
|
|
4927
5608
|
getDisposeResult(name) {
|
|
4928
|
-
|
|
4929
|
-
return (this.compatibleSpecialProperties(name) || !!microApp[name]) && this.compatibleDisableSpecialProperties(name);
|
|
5609
|
+
return (this.compatibleSpecialProperties(name) || !!microApp.options[name]) && this.compatibleDisableSpecialProperties(name);
|
|
4930
5610
|
}
|
|
4931
5611
|
// compatible of disableScopecss & disableSandbox
|
|
4932
5612
|
compatibleSpecialProperties(name) {
|
|
@@ -4948,6 +5628,12 @@ function defineElement(tagName) {
|
|
|
4948
5628
|
}
|
|
4949
5629
|
return this.getAttribute(name) !== 'false';
|
|
4950
5630
|
}
|
|
5631
|
+
isScopecss() {
|
|
5632
|
+
return !(this.getDisposeResult('disable-scopecss') || this.getDisposeResult('shadowDOM'));
|
|
5633
|
+
}
|
|
5634
|
+
isSandbox() {
|
|
5635
|
+
return !this.getDisposeResult('disable-sandbox');
|
|
5636
|
+
}
|
|
4951
5637
|
/**
|
|
4952
5638
|
* 2021-09-08
|
|
4953
5639
|
* get baseRoute
|
|
@@ -4995,8 +5681,10 @@ function defineElement(tagName) {
|
|
|
4995
5681
|
* get config of default page
|
|
4996
5682
|
*/
|
|
4997
5683
|
getDefaultPageValue() {
|
|
4998
|
-
|
|
4999
|
-
|
|
5684
|
+
return (router.getDefaultPage(this.appName) ||
|
|
5685
|
+
this.getAttribute('default-page') ||
|
|
5686
|
+
this.getAttribute('defaultPage') ||
|
|
5687
|
+
'');
|
|
5000
5688
|
}
|
|
5001
5689
|
/**
|
|
5002
5690
|
* Data from the base application
|
|
@@ -5022,7 +5710,7 @@ function defineElement(tagName) {
|
|
|
5022
5710
|
return null;
|
|
5023
5711
|
}
|
|
5024
5712
|
}
|
|
5025
|
-
|
|
5713
|
+
globalEnv.rawWindow.customElements.define(tagName, MicroAppElement);
|
|
5026
5714
|
}
|
|
5027
5715
|
|
|
5028
5716
|
/**
|
|
@@ -5053,33 +5741,40 @@ function preFetch(apps) {
|
|
|
5053
5741
|
});
|
|
5054
5742
|
}
|
|
5055
5743
|
// sequential preload app
|
|
5056
|
-
function preFetchInSerial(
|
|
5057
|
-
return
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
else {
|
|
5744
|
+
function preFetchInSerial(options) {
|
|
5745
|
+
return promiseRequestIdle((resolve) => {
|
|
5746
|
+
var _a, _b, _c, _d, _e, _f;
|
|
5747
|
+
if (isPlainObject(options) && navigator.onLine) {
|
|
5748
|
+
options.name = formatAppName(options.name);
|
|
5749
|
+
options.url = formatAppURL(options.url, options.name);
|
|
5750
|
+
if (options.name && options.url && !appInstanceMap.has(options.name)) {
|
|
5751
|
+
const app = new CreateApp({
|
|
5752
|
+
name: options.name,
|
|
5753
|
+
url: options.url,
|
|
5754
|
+
scopecss: !((_b = (_a = options['disable-scopecss']) !== null && _a !== void 0 ? _a : options.disableScopecss) !== null && _b !== void 0 ? _b : microApp.options['disable-scopecss']),
|
|
5755
|
+
useSandbox: !((_d = (_c = options['disable-sandbox']) !== null && _c !== void 0 ? _c : options.disableSandbox) !== null && _d !== void 0 ? _d : microApp.options['disable-sandbox']),
|
|
5756
|
+
inline: (_e = options.inline) !== null && _e !== void 0 ? _e : microApp.options.inline,
|
|
5757
|
+
esmodule: (_f = options.esmodule) !== null && _f !== void 0 ? _f : microApp.options.esmodule,
|
|
5758
|
+
isPrefetch: true,
|
|
5759
|
+
});
|
|
5760
|
+
const oldOnload = app.onLoad;
|
|
5761
|
+
const oldOnLoadError = app.onLoadError;
|
|
5762
|
+
app.onLoad = (html) => {
|
|
5076
5763
|
resolve();
|
|
5077
|
-
|
|
5764
|
+
oldOnload.call(app, html);
|
|
5765
|
+
};
|
|
5766
|
+
app.onLoadError = (e) => {
|
|
5767
|
+
resolve();
|
|
5768
|
+
oldOnLoadError.call(app, e);
|
|
5769
|
+
};
|
|
5078
5770
|
}
|
|
5079
5771
|
else {
|
|
5080
5772
|
resolve();
|
|
5081
5773
|
}
|
|
5082
|
-
}
|
|
5774
|
+
}
|
|
5775
|
+
else {
|
|
5776
|
+
resolve();
|
|
5777
|
+
}
|
|
5083
5778
|
});
|
|
5084
5779
|
}
|
|
5085
5780
|
/**
|
|
@@ -5089,21 +5784,35 @@ function preFetchInSerial(prefetchApp) {
|
|
|
5089
5784
|
function getGlobalAssets(assets) {
|
|
5090
5785
|
if (isPlainObject(assets)) {
|
|
5091
5786
|
requestIdleCallback(() => {
|
|
5092
|
-
fetchGlobalResources(assets.js, 'js',
|
|
5093
|
-
fetchGlobalResources(assets.css, 'css',
|
|
5787
|
+
fetchGlobalResources(assets.js, 'js', sourceCenter.script);
|
|
5788
|
+
fetchGlobalResources(assets.css, 'css', sourceCenter.link);
|
|
5094
5789
|
});
|
|
5095
5790
|
}
|
|
5096
5791
|
}
|
|
5097
5792
|
// TODO: requestIdleCallback for every file
|
|
5098
|
-
function fetchGlobalResources(resources, suffix,
|
|
5793
|
+
function fetchGlobalResources(resources, suffix, sourceHandler) {
|
|
5099
5794
|
if (isArray(resources)) {
|
|
5100
|
-
const effectiveResource = resources.filter((path) => isString(path) && path.includes(`.${suffix}`) && !
|
|
5795
|
+
const effectiveResource = resources.filter((path) => isString(path) && path.includes(`.${suffix}`) && !sourceHandler.hasInfo(path));
|
|
5101
5796
|
const fetchResourcePromise = effectiveResource.map((path) => fetchSource(path));
|
|
5102
5797
|
// fetch resource with stream
|
|
5103
5798
|
promiseStream(fetchResourcePromise, (res) => {
|
|
5104
5799
|
const path = effectiveResource[res.index];
|
|
5105
|
-
if (
|
|
5106
|
-
|
|
5800
|
+
if (suffix === 'js') {
|
|
5801
|
+
if (!sourceHandler.hasInfo(path)) {
|
|
5802
|
+
sourceHandler.setInfo(path, {
|
|
5803
|
+
code: res.data,
|
|
5804
|
+
isExternal: false,
|
|
5805
|
+
appSpace: {},
|
|
5806
|
+
});
|
|
5807
|
+
}
|
|
5808
|
+
}
|
|
5809
|
+
else {
|
|
5810
|
+
if (!sourceHandler.hasInfo(path)) {
|
|
5811
|
+
sourceHandler.setInfo(path, {
|
|
5812
|
+
code: res.data,
|
|
5813
|
+
appSpace: {}
|
|
5814
|
+
});
|
|
5815
|
+
}
|
|
5107
5816
|
}
|
|
5108
5817
|
}, (err) => {
|
|
5109
5818
|
logError(err);
|
|
@@ -5146,33 +5855,41 @@ function unmountApp(appName, options) {
|
|
|
5146
5855
|
if (options === null || options === void 0 ? void 0 : options.destroy) {
|
|
5147
5856
|
app.actionsForCompletelyDestroy();
|
|
5148
5857
|
}
|
|
5149
|
-
resolve();
|
|
5858
|
+
resolve(true);
|
|
5150
5859
|
}
|
|
5151
5860
|
else if (app.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN) {
|
|
5152
5861
|
if (options === null || options === void 0 ? void 0 : options.destroy) {
|
|
5153
|
-
app.unmount(
|
|
5862
|
+
app.unmount({
|
|
5863
|
+
destroy: true,
|
|
5864
|
+
clearData: true,
|
|
5865
|
+
unmountcb: resolve.bind(null, true)
|
|
5866
|
+
});
|
|
5154
5867
|
}
|
|
5155
5868
|
else if (options === null || options === void 0 ? void 0 : options.clearAliveState) {
|
|
5156
|
-
app.unmount(
|
|
5869
|
+
app.unmount({
|
|
5870
|
+
destroy: false,
|
|
5871
|
+
clearData: !!options.clearData,
|
|
5872
|
+
unmountcb: resolve.bind(null, true)
|
|
5873
|
+
});
|
|
5157
5874
|
}
|
|
5158
5875
|
else {
|
|
5159
|
-
resolve();
|
|
5876
|
+
resolve(true);
|
|
5160
5877
|
}
|
|
5161
5878
|
}
|
|
5162
5879
|
else {
|
|
5163
5880
|
const container = getRootContainer(app.container);
|
|
5164
5881
|
const unmountHandler = () => {
|
|
5165
|
-
container.removeEventListener(
|
|
5166
|
-
container.removeEventListener(
|
|
5167
|
-
resolve();
|
|
5882
|
+
container.removeEventListener(lifeCycles.UNMOUNT, unmountHandler);
|
|
5883
|
+
container.removeEventListener(lifeCycles.AFTERHIDDEN, afterhiddenHandler);
|
|
5884
|
+
resolve(true);
|
|
5168
5885
|
};
|
|
5169
5886
|
const afterhiddenHandler = () => {
|
|
5170
|
-
container.removeEventListener(
|
|
5171
|
-
container.removeEventListener(
|
|
5172
|
-
resolve();
|
|
5887
|
+
container.removeEventListener(lifeCycles.UNMOUNT, unmountHandler);
|
|
5888
|
+
container.removeEventListener(lifeCycles.AFTERHIDDEN, afterhiddenHandler);
|
|
5889
|
+
resolve(true);
|
|
5173
5890
|
};
|
|
5174
|
-
container.addEventListener(
|
|
5175
|
-
container.addEventListener(
|
|
5891
|
+
container.addEventListener(lifeCycles.UNMOUNT, unmountHandler);
|
|
5892
|
+
container.addEventListener(lifeCycles.AFTERHIDDEN, afterhiddenHandler);
|
|
5176
5893
|
if (options === null || options === void 0 ? void 0 : options.destroy) {
|
|
5177
5894
|
let destroyAttrValue, destoryAttrValue;
|
|
5178
5895
|
container.hasAttribute('destroy') && (destroyAttrValue = container.getAttribute('destroy'));
|
|
@@ -5180,36 +5897,131 @@ function unmountApp(appName, options) {
|
|
|
5180
5897
|
container.setAttribute('destroy', 'true');
|
|
5181
5898
|
container.parentNode.removeChild(container);
|
|
5182
5899
|
container.removeAttribute('destroy');
|
|
5183
|
-
|
|
5184
|
-
|
|
5900
|
+
isString(destroyAttrValue) && container.setAttribute('destroy', destroyAttrValue);
|
|
5901
|
+
isString(destoryAttrValue) && container.setAttribute('destory', destoryAttrValue);
|
|
5185
5902
|
}
|
|
5186
5903
|
else if ((options === null || options === void 0 ? void 0 : options.clearAliveState) && container.hasAttribute('keep-alive')) {
|
|
5187
5904
|
const keepAliveAttrValue = container.getAttribute('keep-alive');
|
|
5188
5905
|
container.removeAttribute('keep-alive');
|
|
5906
|
+
let clearDataAttrValue;
|
|
5907
|
+
if (options.clearData) {
|
|
5908
|
+
clearDataAttrValue = container.getAttribute('clear-data');
|
|
5909
|
+
container.setAttribute('clear-data', 'true');
|
|
5910
|
+
}
|
|
5189
5911
|
container.parentNode.removeChild(container);
|
|
5190
5912
|
container.setAttribute('keep-alive', keepAliveAttrValue);
|
|
5913
|
+
isString(clearDataAttrValue) && container.setAttribute('clear-data', clearDataAttrValue);
|
|
5191
5914
|
}
|
|
5192
5915
|
else {
|
|
5916
|
+
let clearDataAttrValue;
|
|
5917
|
+
if (options === null || options === void 0 ? void 0 : options.clearData) {
|
|
5918
|
+
clearDataAttrValue = container.getAttribute('clear-data');
|
|
5919
|
+
container.setAttribute('clear-data', 'true');
|
|
5920
|
+
}
|
|
5193
5921
|
container.parentNode.removeChild(container);
|
|
5922
|
+
isString(clearDataAttrValue) && container.setAttribute('clear-data', clearDataAttrValue);
|
|
5194
5923
|
}
|
|
5195
5924
|
}
|
|
5196
5925
|
}
|
|
5197
5926
|
else {
|
|
5198
5927
|
logWarn(`app ${appName} does not exist`);
|
|
5199
|
-
resolve();
|
|
5928
|
+
resolve(false);
|
|
5200
5929
|
}
|
|
5201
5930
|
});
|
|
5202
5931
|
}
|
|
5203
5932
|
// unmount all apps in turn
|
|
5204
5933
|
function unmountAllApps(options) {
|
|
5205
|
-
return Array.from(appInstanceMap.keys()).reduce((pre, next) => pre.then(() => unmountApp(next, options)), Promise.resolve());
|
|
5934
|
+
return Array.from(appInstanceMap.keys()).reduce((pre, next) => pre.then(() => unmountApp(next, options)), Promise.resolve(true));
|
|
5935
|
+
}
|
|
5936
|
+
/**
|
|
5937
|
+
* Re render app from the command line
|
|
5938
|
+
* microApp.reload(destroy)
|
|
5939
|
+
* @param appName app.name
|
|
5940
|
+
* @param destroy unmount app with destroy mode
|
|
5941
|
+
* @returns Promise<boolean>
|
|
5942
|
+
*/
|
|
5943
|
+
function reload(appName, destroy) {
|
|
5944
|
+
return new Promise((resolve) => {
|
|
5945
|
+
const app = appInstanceMap.get(formatAppName(appName));
|
|
5946
|
+
if (app) {
|
|
5947
|
+
const rootContainer = app.container && getRootContainer(app.container);
|
|
5948
|
+
if (rootContainer) {
|
|
5949
|
+
resolve(rootContainer.reload(destroy));
|
|
5950
|
+
}
|
|
5951
|
+
else {
|
|
5952
|
+
logWarn(`app ${appName} is not rendered, cannot use reload`);
|
|
5953
|
+
resolve(false);
|
|
5954
|
+
}
|
|
5955
|
+
}
|
|
5956
|
+
else {
|
|
5957
|
+
logWarn(`app ${appName} does not exist`);
|
|
5958
|
+
resolve(false);
|
|
5959
|
+
}
|
|
5960
|
+
});
|
|
5961
|
+
}
|
|
5962
|
+
/**
|
|
5963
|
+
* Manually render app
|
|
5964
|
+
* @param options RenderAppOptions
|
|
5965
|
+
* @returns Promise<boolean>
|
|
5966
|
+
*/
|
|
5967
|
+
function renderApp(options) {
|
|
5968
|
+
return new Promise((resolve) => {
|
|
5969
|
+
if (!isPlainObject(options))
|
|
5970
|
+
return logError('renderApp options must be an object');
|
|
5971
|
+
const container = isElement(options.container) ? options.container : isString(options.container) ? document.querySelector(options.container) : null;
|
|
5972
|
+
if (!isElement(container))
|
|
5973
|
+
return logError('Target container is not a DOM element.');
|
|
5974
|
+
const microAppElement = pureCreateElement(microApp.tagName);
|
|
5975
|
+
for (const attr in options) {
|
|
5976
|
+
if (attr === 'onDataChange') {
|
|
5977
|
+
if (isFunction(options[attr])) {
|
|
5978
|
+
microAppElement.addEventListener('datachange', options[attr]);
|
|
5979
|
+
}
|
|
5980
|
+
}
|
|
5981
|
+
else if (attr === 'lifeCycles') {
|
|
5982
|
+
const lifeCycleConfig = options[attr];
|
|
5983
|
+
if (isPlainObject(lifeCycleConfig)) {
|
|
5984
|
+
for (const lifeName in lifeCycleConfig) {
|
|
5985
|
+
if (lifeName.toUpperCase() in lifeCycles && isFunction(lifeCycleConfig[lifeName])) {
|
|
5986
|
+
microAppElement.addEventListener(lifeName.toLowerCase(), lifeCycleConfig[lifeName]);
|
|
5987
|
+
}
|
|
5988
|
+
}
|
|
5989
|
+
}
|
|
5990
|
+
}
|
|
5991
|
+
else if (attr !== 'container') {
|
|
5992
|
+
microAppElement.setAttribute(attr, options[attr]);
|
|
5993
|
+
}
|
|
5994
|
+
}
|
|
5995
|
+
const handleMount = () => {
|
|
5996
|
+
releaseListener();
|
|
5997
|
+
resolve(true);
|
|
5998
|
+
};
|
|
5999
|
+
const handleError = () => {
|
|
6000
|
+
releaseListener();
|
|
6001
|
+
resolve(false);
|
|
6002
|
+
};
|
|
6003
|
+
const releaseListener = () => {
|
|
6004
|
+
microAppElement.removeEventListener(lifeCycles.MOUNTED, handleMount);
|
|
6005
|
+
microAppElement.removeEventListener(lifeCycles.ERROR, handleError);
|
|
6006
|
+
};
|
|
6007
|
+
microAppElement.addEventListener(lifeCycles.MOUNTED, handleMount);
|
|
6008
|
+
microAppElement.addEventListener(lifeCycles.ERROR, handleError);
|
|
6009
|
+
container.appendChild(microAppElement);
|
|
6010
|
+
});
|
|
5206
6011
|
}
|
|
5207
6012
|
class MicroApp extends EventCenterForBaseApp {
|
|
5208
6013
|
constructor() {
|
|
5209
6014
|
super(...arguments);
|
|
5210
6015
|
this.tagName = 'micro-app';
|
|
5211
|
-
this.
|
|
6016
|
+
this.options = {};
|
|
5212
6017
|
this.router = router;
|
|
6018
|
+
this.preFetch = preFetch;
|
|
6019
|
+
this.unmountApp = unmountApp;
|
|
6020
|
+
this.unmountAllApps = unmountAllApps;
|
|
6021
|
+
this.getActiveApps = getActiveApps;
|
|
6022
|
+
this.getAllApps = getAllApps;
|
|
6023
|
+
this.reload = reload;
|
|
6024
|
+
this.renderApp = renderApp;
|
|
5213
6025
|
}
|
|
5214
6026
|
start(options) {
|
|
5215
6027
|
var _a, _b;
|
|
@@ -5228,26 +6040,10 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
5228
6040
|
return logWarn(`element ${this.tagName} is already defined`);
|
|
5229
6041
|
}
|
|
5230
6042
|
initGlobalEnv();
|
|
5231
|
-
if (
|
|
5232
|
-
this.
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
* compatible with versions below 0.4.2 of destroy
|
|
5236
|
-
* do not merge with the previous line
|
|
5237
|
-
*/
|
|
5238
|
-
// @ts-ignore
|
|
5239
|
-
this.destory = options.destory;
|
|
5240
|
-
this.inline = options.inline;
|
|
5241
|
-
this['disable-scopecss'] = (_a = options['disable-scopecss']) !== null && _a !== void 0 ? _a : options.disableScopecss;
|
|
5242
|
-
this['disable-sandbox'] = (_b = options['disable-sandbox']) !== null && _b !== void 0 ? _b : options.disableSandbox;
|
|
5243
|
-
this['disable-memory-router'] = options['disable-memory-router'];
|
|
5244
|
-
this['disable-patch-request'] = options['disable-patch-request'];
|
|
5245
|
-
this['keep-router-state'] = options['keep-router-state'];
|
|
5246
|
-
this['hidden-router'] = options['hidden-router'];
|
|
5247
|
-
this.esmodule = options.esmodule;
|
|
5248
|
-
this.ssr = options.ssr;
|
|
5249
|
-
isFunction(options.fetch) && (this.fetch = options.fetch);
|
|
5250
|
-
isPlainObject(options.lifeCycles) && (this.lifeCycles = options.lifeCycles);
|
|
6043
|
+
if (isPlainObject(options)) {
|
|
6044
|
+
this.options = options;
|
|
6045
|
+
options['disable-scopecss'] = (_a = options['disable-scopecss']) !== null && _a !== void 0 ? _a : options.disableScopecss;
|
|
6046
|
+
options['disable-sandbox'] = (_b = options['disable-sandbox']) !== null && _b !== void 0 ? _b : options.disableSandbox;
|
|
5251
6047
|
// load app assets when browser is idle
|
|
5252
6048
|
options.preFetchApps && preFetch(options.preFetchApps);
|
|
5253
6049
|
// load global assets when browser is idle
|
|
@@ -5263,15 +6059,14 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
5263
6059
|
}
|
|
5264
6060
|
}
|
|
5265
6061
|
}
|
|
5266
|
-
this.plugins = options.plugins;
|
|
5267
6062
|
}
|
|
5268
6063
|
}
|
|
5269
6064
|
// define customElement after init
|
|
5270
6065
|
defineElement(this.tagName);
|
|
5271
6066
|
}
|
|
5272
6067
|
}
|
|
5273
|
-
|
|
6068
|
+
const microApp = new MicroApp();
|
|
5274
6069
|
|
|
5275
6070
|
export default microApp;
|
|
5276
|
-
export { EventCenterForMicroApp, MicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, removeDomScope, unmountAllApps, unmountApp, version };
|
|
6071
|
+
export { EventCenterForMicroApp, MicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, reload, removeDomScope, renderApp, unmountAllApps, unmountApp, version };
|
|
5277
6072
|
//# sourceMappingURL=index.esm.js.map
|