@micro-zoe/micro-app 0.4.3 → 0.5.3
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 +19 -61
- package/README.zh-cn.md +19 -59
- package/lib/index.d.ts +89 -7
- package/lib/index.esm.js +261 -207
- 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 +19 -19
- package/polyfill/jsx-custom-event.js +3 -5
- package/polyfill/jsx-custom-event.js.map +1 -1
- package/typings/global.d.ts +7 -0
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '0.
|
|
1
|
+
const version = '0.5.3';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -85,10 +85,12 @@ function addProtocol(url) {
|
|
|
85
85
|
return url.startsWith('//') ? `${location.protocol}${url}` : url;
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
88
|
+
* format URL address
|
|
89
|
+
* note the scenes:
|
|
90
|
+
* 1. micro-app -> attributeChangedCallback
|
|
91
|
+
* 2. preFetch
|
|
90
92
|
*/
|
|
91
|
-
function
|
|
93
|
+
function formatAppURL(url, appName = null) {
|
|
92
94
|
if (!isString(url) || !url)
|
|
93
95
|
return '';
|
|
94
96
|
try {
|
|
@@ -105,10 +107,20 @@ function formatURL(url, appName = null) {
|
|
|
105
107
|
return '';
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
/**
|
|
111
|
+
* format name
|
|
112
|
+
* note the scenes:
|
|
113
|
+
* 1. micro-app -> attributeChangedCallback
|
|
114
|
+
* 2. event_center -> EventCenterForMicroApp -> constructor
|
|
115
|
+
* 3. event_center -> EventCenterForBaseApp -> all methods
|
|
116
|
+
* 4. preFetch
|
|
117
|
+
* 5. plugins
|
|
118
|
+
*/
|
|
119
|
+
function formatAppName(name) {
|
|
120
|
+
if (!isString(name) || !name)
|
|
121
|
+
return '';
|
|
122
|
+
return name.replace(/(^\d+)|([^\w\d-_])/gi, '');
|
|
123
|
+
}
|
|
112
124
|
/**
|
|
113
125
|
* Get valid address, such as https://xxx/xx/xx.html to https://xxx/xx/
|
|
114
126
|
* @param url app.url
|
|
@@ -245,7 +257,7 @@ function pureCreateElement(tagName, options) {
|
|
|
245
257
|
* @param target Accept cloned elements
|
|
246
258
|
* @param deep deep clone or transfer dom
|
|
247
259
|
*/
|
|
248
|
-
function
|
|
260
|
+
function cloneContainer(origin, target, deep) {
|
|
249
261
|
target.innerHTML = '';
|
|
250
262
|
if (deep) {
|
|
251
263
|
const clonedNode = origin.cloneNode(true);
|
|
@@ -271,6 +283,13 @@ function isUniqueElement(key) {
|
|
|
271
283
|
/^head$/i.test(key) ||
|
|
272
284
|
/^html$/i.test(key));
|
|
273
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* get micro-app element
|
|
288
|
+
* @param target app container
|
|
289
|
+
*/
|
|
290
|
+
function getRootContainer(target) {
|
|
291
|
+
return (isShadowRoot(target) ? target.host : target);
|
|
292
|
+
}
|
|
274
293
|
|
|
275
294
|
var ObservedAttrName;
|
|
276
295
|
(function (ObservedAttrName) {
|
|
@@ -499,33 +518,35 @@ function scopedRule(rules, prefix) {
|
|
|
499
518
|
*/
|
|
500
519
|
function commonAction(templateStyle, styleElement, originContent, prefix, baseURI, linkpath) {
|
|
501
520
|
var _a, _b;
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
521
|
+
if (!styleElement.__MICRO_APP_HAS_SCOPED__) {
|
|
522
|
+
const rules = Array.from((_b = (_a = templateStyle.sheet) === null || _a === void 0 ? void 0 : _a.cssRules) !== null && _b !== void 0 ? _b : []);
|
|
523
|
+
let result = scopedHost(scopedRule(rules, prefix), baseURI, originContent, linkpath);
|
|
524
|
+
/**
|
|
525
|
+
* Solve the problem of missing content quotes in some Safari browsers
|
|
526
|
+
* docs: https://developer.mozilla.org/zh-CN/docs/Web/CSS/content
|
|
527
|
+
* If there are still problems, it is recommended to use the attr()
|
|
528
|
+
*/
|
|
529
|
+
if (isSafari()) {
|
|
530
|
+
result = result.replace(/([;{]\s*content:\s*)([^\s"][^";}]*)/gm, (all, $1, $2) => {
|
|
531
|
+
if ($2 === 'none' ||
|
|
532
|
+
/^(url\()|(counter\()|(attr\()|(open-quote)|(close-quote)/.test($2)) {
|
|
533
|
+
return all;
|
|
534
|
+
}
|
|
535
|
+
return `${$1}"${$2}"`;
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
styleElement.textContent = result;
|
|
539
|
+
styleElement.__MICRO_APP_HAS_SCOPED__ = true;
|
|
517
540
|
}
|
|
518
|
-
styleElement.textContent = result;
|
|
519
541
|
}
|
|
520
542
|
/**
|
|
521
543
|
* scopedCSS
|
|
522
544
|
* @param styleElement target style element
|
|
523
545
|
* @param appName app name
|
|
524
546
|
*/
|
|
525
|
-
function scopedCSS(styleElement,
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const prefix = `${microApp.tagName}[name=${appName}]`;
|
|
547
|
+
function scopedCSS(styleElement, app) {
|
|
548
|
+
if (app.scopecss) {
|
|
549
|
+
const prefix = `${microApp.tagName}[name=${app.name}]`;
|
|
529
550
|
let templateStyle = globalEnv.templateStyle;
|
|
530
551
|
if (!templateStyle) {
|
|
531
552
|
globalEnv.templateStyle = templateStyle = pureCreateElement('style');
|
|
@@ -535,7 +556,7 @@ function scopedCSS(styleElement, appName) {
|
|
|
535
556
|
}
|
|
536
557
|
if (styleElement.textContent) {
|
|
537
558
|
templateStyle.textContent = styleElement.textContent;
|
|
538
|
-
commonAction(templateStyle, styleElement, styleElement.textContent, prefix, app.url, styleElement.
|
|
559
|
+
commonAction(templateStyle, styleElement, styleElement.textContent, prefix, app.url, styleElement.__MICRO_APP_LINK_PATH__);
|
|
539
560
|
templateStyle.textContent = '';
|
|
540
561
|
}
|
|
541
562
|
else {
|
|
@@ -546,7 +567,7 @@ function scopedCSS(styleElement, appName) {
|
|
|
546
567
|
if ((!styleElement.textContent && ((_b = (_a = styleElement.sheet) === null || _a === void 0 ? void 0 : _a.cssRules) === null || _b === void 0 ? void 0 : _b.length)) ||
|
|
547
568
|
styleElement.hasAttribute('data-styled'))
|
|
548
569
|
return;
|
|
549
|
-
commonAction(styleElement, styleElement, styleElement.textContent, prefix, app.url, styleElement.
|
|
570
|
+
commonAction(styleElement, styleElement, styleElement.textContent, prefix, app.url, styleElement.__MICRO_APP_LINK_PATH__);
|
|
550
571
|
});
|
|
551
572
|
observer.observe(styleElement, { childList: true });
|
|
552
573
|
}
|
|
@@ -604,7 +625,7 @@ const globalLinks = new Map();
|
|
|
604
625
|
* @param microAppHead micro-app-head element
|
|
605
626
|
* @param isDynamic dynamic insert
|
|
606
627
|
*/
|
|
607
|
-
function extractLinkFromHtml(link, parent, app,
|
|
628
|
+
function extractLinkFromHtml(link, parent, app, isDynamic = false) {
|
|
608
629
|
const rel = link.getAttribute('rel');
|
|
609
630
|
let href = link.getAttribute('href');
|
|
610
631
|
let replaceComment = null;
|
|
@@ -612,12 +633,9 @@ function extractLinkFromHtml(link, parent, app, microAppHead, isDynamic = false)
|
|
|
612
633
|
href = CompletionPath(href, app.url);
|
|
613
634
|
if (!isDynamic) {
|
|
614
635
|
replaceComment = document.createComment(`link element with href=${href} move to micro-app-head as style element`);
|
|
615
|
-
const placeholderComment = document.createComment(`placeholder for link with href=${href}`);
|
|
616
|
-
// all style elements insert into microAppHead
|
|
617
|
-
microAppHead.appendChild(placeholderComment);
|
|
618
636
|
app.source.links.set(href, {
|
|
619
637
|
code: '',
|
|
620
|
-
placeholder:
|
|
638
|
+
placeholder: replaceComment,
|
|
621
639
|
isGlobal: link.hasAttribute('global'),
|
|
622
640
|
});
|
|
623
641
|
}
|
|
@@ -632,7 +650,7 @@ function extractLinkFromHtml(link, parent, app, microAppHead, isDynamic = false)
|
|
|
632
650
|
}
|
|
633
651
|
}
|
|
634
652
|
else if (rel && ['prefetch', 'preload', 'prerender', 'icon', 'apple-touch-icon'].includes(rel)) {
|
|
635
|
-
// preload prefetch
|
|
653
|
+
// preload prefetch icon ....
|
|
636
654
|
if (isDynamic) {
|
|
637
655
|
replaceComment = document.createComment(`link element with rel=${rel}${href ? ' & href=' + href : ''} removed by micro-app`);
|
|
638
656
|
}
|
|
@@ -686,8 +704,9 @@ function fetchLinkSuccess(url, info, data, microAppHead, app) {
|
|
|
686
704
|
}
|
|
687
705
|
const styleLink = pureCreateElement('style');
|
|
688
706
|
styleLink.textContent = data;
|
|
689
|
-
styleLink.
|
|
690
|
-
|
|
707
|
+
styleLink.__MICRO_APP_LINK_PATH__ = url;
|
|
708
|
+
styleLink.setAttribute('data-origin-href', url);
|
|
709
|
+
microAppHead.replaceChild(scopedCSS(styleLink, app), info.placeholder);
|
|
691
710
|
info.placeholder = null;
|
|
692
711
|
info.code = data;
|
|
693
712
|
}
|
|
@@ -702,7 +721,7 @@ function fetchLinkSuccess(url, info, data, microAppHead, app) {
|
|
|
702
721
|
function foramtDynamicLink(url, info, app, originLink, replaceStyle) {
|
|
703
722
|
if (app.source.links.has(url)) {
|
|
704
723
|
replaceStyle.textContent = app.source.links.get(url).code;
|
|
705
|
-
scopedCSS(replaceStyle, app
|
|
724
|
+
scopedCSS(replaceStyle, app);
|
|
706
725
|
defer(() => dispatchOnLoadEvent(originLink));
|
|
707
726
|
return;
|
|
708
727
|
}
|
|
@@ -711,17 +730,16 @@ function foramtDynamicLink(url, info, app, originLink, replaceStyle) {
|
|
|
711
730
|
info.code = code;
|
|
712
731
|
app.source.links.set(url, info);
|
|
713
732
|
replaceStyle.textContent = code;
|
|
714
|
-
scopedCSS(replaceStyle, app
|
|
733
|
+
scopedCSS(replaceStyle, app);
|
|
715
734
|
defer(() => dispatchOnLoadEvent(originLink));
|
|
716
735
|
return;
|
|
717
736
|
}
|
|
718
737
|
fetchSource(url, app.name).then((data) => {
|
|
719
738
|
info.code = data;
|
|
720
739
|
app.source.links.set(url, info);
|
|
721
|
-
|
|
722
|
-
globalLinks.set(url, data);
|
|
740
|
+
info.isGlobal && globalLinks.set(url, data);
|
|
723
741
|
replaceStyle.textContent = data;
|
|
724
|
-
scopedCSS(replaceStyle, app
|
|
742
|
+
scopedCSS(replaceStyle, app);
|
|
725
743
|
dispatchOnLoadEvent(originLink);
|
|
726
744
|
}).catch((err) => {
|
|
727
745
|
logError(err, app.name);
|
|
@@ -861,6 +879,7 @@ function execScripts(scriptList, app, initedHook) {
|
|
|
861
879
|
const deferScriptInfo = [];
|
|
862
880
|
for (const [url, info] of scriptListEntries) {
|
|
863
881
|
if (!info.isDynamic) {
|
|
882
|
+
// Notice the second render
|
|
864
883
|
if (info.defer || info.async) {
|
|
865
884
|
if (info.isExternal && !info.code) {
|
|
866
885
|
deferScriptPromise.push(fetchSource(url, app.name));
|
|
@@ -869,11 +888,10 @@ function execScripts(scriptList, app, initedHook) {
|
|
|
869
888
|
deferScriptPromise.push(info.code);
|
|
870
889
|
}
|
|
871
890
|
deferScriptInfo.push([url, info]);
|
|
872
|
-
|
|
873
|
-
initedHook.moduleCount = initedHook.moduleCount ? ++initedHook.moduleCount : 1;
|
|
891
|
+
info.module && (initedHook.moduleCount = initedHook.moduleCount ? ++initedHook.moduleCount : 1);
|
|
874
892
|
}
|
|
875
893
|
else {
|
|
876
|
-
runScript(url,
|
|
894
|
+
runScript(url, app, info, false);
|
|
877
895
|
initedHook(false);
|
|
878
896
|
}
|
|
879
897
|
}
|
|
@@ -882,9 +900,9 @@ function execScripts(scriptList, app, initedHook) {
|
|
|
882
900
|
Promise.all(deferScriptPromise).then((res) => {
|
|
883
901
|
res.forEach((code, index) => {
|
|
884
902
|
const [url, info] = deferScriptInfo[index];
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
903
|
+
info.code = info.code || code;
|
|
904
|
+
runScript(url, app, info, false, initedHook);
|
|
905
|
+
!info.module && initedHook(false);
|
|
888
906
|
});
|
|
889
907
|
initedHook(isUndefined(initedHook.moduleCount));
|
|
890
908
|
}).catch((err) => {
|
|
@@ -899,26 +917,25 @@ function execScripts(scriptList, app, initedHook) {
|
|
|
899
917
|
/**
|
|
900
918
|
* run code
|
|
901
919
|
* @param url script address
|
|
902
|
-
* @param code js code
|
|
903
920
|
* @param app app
|
|
904
|
-
* @param
|
|
921
|
+
* @param info script info
|
|
905
922
|
* @param isDynamic dynamically created script
|
|
906
923
|
* @param callback callback of module script
|
|
907
924
|
*/
|
|
908
|
-
function runScript(url,
|
|
925
|
+
function runScript(url, app, info, isDynamic, callback) {
|
|
909
926
|
var _a;
|
|
910
927
|
try {
|
|
911
|
-
code = bindScope(url,
|
|
912
|
-
if (app.inline || module) {
|
|
928
|
+
const code = bindScope(url, app, info.code, info.module);
|
|
929
|
+
if (app.inline || info.module) {
|
|
913
930
|
const scriptElement = pureCreateElement('script');
|
|
914
|
-
|
|
931
|
+
runCode2InlineScript(url, code, info.module, scriptElement, callback);
|
|
915
932
|
if (isDynamic)
|
|
916
933
|
return scriptElement;
|
|
917
934
|
// TEST IGNORE
|
|
918
935
|
(_a = app.container) === null || _a === void 0 ? void 0 : _a.querySelector('micro-app-body').appendChild(scriptElement);
|
|
919
936
|
}
|
|
920
937
|
else {
|
|
921
|
-
|
|
938
|
+
runCode2Function(code, info);
|
|
922
939
|
if (isDynamic)
|
|
923
940
|
return document.createComment('dynamic script extract by micro-app');
|
|
924
941
|
}
|
|
@@ -936,19 +953,18 @@ function runScript(url, code, app, module, isDynamic, callback) {
|
|
|
936
953
|
*/
|
|
937
954
|
function runDynamicRemoteScript(url, info, app, originScript) {
|
|
938
955
|
const dispatchScriptOnLoadEvent = () => dispatchOnLoadEvent(originScript);
|
|
956
|
+
// url is unique
|
|
939
957
|
if (app.source.scripts.has(url)) {
|
|
940
958
|
const existInfo = app.source.scripts.get(url);
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
return runScript(url, existInfo.code, app, info.module, true, dispatchScriptOnLoadEvent);
|
|
959
|
+
!existInfo.module && defer(dispatchScriptOnLoadEvent);
|
|
960
|
+
return runScript(url, app, existInfo, true, dispatchScriptOnLoadEvent);
|
|
944
961
|
}
|
|
945
962
|
if (globalScripts.has(url)) {
|
|
946
963
|
const code = globalScripts.get(url);
|
|
947
964
|
info.code = code;
|
|
948
965
|
app.source.scripts.set(url, info);
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
return runScript(url, code, app, info.module, true, dispatchScriptOnLoadEvent);
|
|
966
|
+
!info.module && defer(dispatchScriptOnLoadEvent);
|
|
967
|
+
return runScript(url, app, info, true, dispatchScriptOnLoadEvent);
|
|
952
968
|
}
|
|
953
969
|
let replaceElement;
|
|
954
970
|
if (app.inline || info.module) {
|
|
@@ -960,22 +976,20 @@ function runDynamicRemoteScript(url, info, app, originScript) {
|
|
|
960
976
|
fetchSource(url, app.name).then((code) => {
|
|
961
977
|
info.code = code;
|
|
962
978
|
app.source.scripts.set(url, info);
|
|
963
|
-
|
|
964
|
-
globalScripts.set(url, code);
|
|
979
|
+
info.isGlobal && globalScripts.set(url, code);
|
|
965
980
|
try {
|
|
966
|
-
code = bindScope(url,
|
|
981
|
+
code = bindScope(url, app, code, info.module);
|
|
967
982
|
if (app.inline || info.module) {
|
|
968
|
-
|
|
983
|
+
runCode2InlineScript(url, code, info.module, replaceElement, dispatchScriptOnLoadEvent);
|
|
969
984
|
}
|
|
970
985
|
else {
|
|
971
|
-
|
|
986
|
+
runCode2Function(code, info);
|
|
972
987
|
}
|
|
973
988
|
}
|
|
974
989
|
catch (e) {
|
|
975
990
|
console.error(`[micro-app from runDynamicScript] app ${app.name}: `, e, url);
|
|
976
991
|
}
|
|
977
|
-
|
|
978
|
-
dispatchOnLoadEvent(originScript);
|
|
992
|
+
!info.module && dispatchOnLoadEvent(originScript);
|
|
979
993
|
}).catch((err) => {
|
|
980
994
|
logError(err, app.name);
|
|
981
995
|
dispatchOnErrorEvent(originScript);
|
|
@@ -985,20 +999,17 @@ function runDynamicRemoteScript(url, info, app, originScript) {
|
|
|
985
999
|
/**
|
|
986
1000
|
* common handle for inline script
|
|
987
1001
|
* @param url script address
|
|
988
|
-
* @param code
|
|
1002
|
+
* @param code bound code
|
|
989
1003
|
* @param module type='module' of script
|
|
990
1004
|
* @param scriptElement target script element
|
|
991
1005
|
* @param callback callback of module script
|
|
992
1006
|
*/
|
|
993
|
-
function
|
|
1007
|
+
function runCode2InlineScript(url, code, module, scriptElement, callback) {
|
|
994
1008
|
if (module) {
|
|
995
1009
|
// module script is async, transform it to a blob for subsequent operations
|
|
996
1010
|
const blob = new Blob([code], { type: 'text/javascript' });
|
|
997
1011
|
scriptElement.src = URL.createObjectURL(blob);
|
|
998
1012
|
scriptElement.setAttribute('type', 'module');
|
|
999
|
-
if (!url.startsWith('inline-')) {
|
|
1000
|
-
scriptElement.setAttribute('originSrc', url);
|
|
1001
|
-
}
|
|
1002
1013
|
if (callback) {
|
|
1003
1014
|
callback.moduleCount && callback.moduleCount--;
|
|
1004
1015
|
scriptElement.onload = callback.bind(scriptElement, callback.moduleCount === 0);
|
|
@@ -1007,15 +1018,25 @@ function setInlinScriptContent(url, code, module, scriptElement, callback) {
|
|
|
1007
1018
|
else {
|
|
1008
1019
|
scriptElement.textContent = code;
|
|
1009
1020
|
}
|
|
1021
|
+
if (!url.startsWith('inline-')) {
|
|
1022
|
+
scriptElement.setAttribute('data-origin-src', url);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
// init & run code2Function
|
|
1026
|
+
function runCode2Function(code, info) {
|
|
1027
|
+
if (!info.code2Function) {
|
|
1028
|
+
info.code2Function = new Function(code);
|
|
1029
|
+
}
|
|
1030
|
+
info.code2Function.call(window);
|
|
1010
1031
|
}
|
|
1011
1032
|
/**
|
|
1012
1033
|
* bind js scope
|
|
1013
1034
|
* @param url script address
|
|
1014
|
-
* @param code code
|
|
1015
1035
|
* @param app app
|
|
1036
|
+
* @param code code
|
|
1016
1037
|
* @param module type='module' of script
|
|
1017
1038
|
*/
|
|
1018
|
-
function bindScope(url,
|
|
1039
|
+
function bindScope(url, app, code, module) {
|
|
1019
1040
|
if (isPlainObject(microApp.plugins)) {
|
|
1020
1041
|
code = usePlugins(url, code, app.name, microApp.plugins);
|
|
1021
1042
|
}
|
|
@@ -1069,15 +1090,15 @@ function getWrapElement(str) {
|
|
|
1069
1090
|
function flatChildren(parent, app, microAppHead) {
|
|
1070
1091
|
const children = Array.from(parent.children);
|
|
1071
1092
|
children.length && children.forEach((child) => {
|
|
1072
|
-
flatChildren(child, app
|
|
1093
|
+
flatChildren(child, app);
|
|
1073
1094
|
});
|
|
1074
1095
|
for (const dom of children) {
|
|
1075
1096
|
if (dom instanceof HTMLLinkElement) {
|
|
1076
1097
|
if (dom.hasAttribute('exclude')) {
|
|
1077
1098
|
parent.replaceChild(document.createComment('link element with exclude attribute ignored by micro-app'), dom);
|
|
1078
1099
|
}
|
|
1079
|
-
else if (
|
|
1080
|
-
extractLinkFromHtml(dom, parent, app
|
|
1100
|
+
else if (!dom.hasAttribute('ignore')) {
|
|
1101
|
+
extractLinkFromHtml(dom, parent, app);
|
|
1081
1102
|
}
|
|
1082
1103
|
else if (dom.hasAttribute('href')) {
|
|
1083
1104
|
dom.setAttribute('href', CompletionPath(dom.getAttribute('href'), app.url));
|
|
@@ -1088,7 +1109,7 @@ function flatChildren(parent, app, microAppHead) {
|
|
|
1088
1109
|
parent.replaceChild(document.createComment('style element with exclude attribute ignored by micro-app'), dom);
|
|
1089
1110
|
}
|
|
1090
1111
|
else if (app.scopecss && !dom.hasAttribute('ignore')) {
|
|
1091
|
-
|
|
1112
|
+
scopedCSS(dom, app);
|
|
1092
1113
|
}
|
|
1093
1114
|
}
|
|
1094
1115
|
else if (dom instanceof HTMLScriptElement) {
|
|
@@ -1116,7 +1137,7 @@ function extractSourceDom(htmlStr, app) {
|
|
|
1116
1137
|
app.onerror(new Error(msg));
|
|
1117
1138
|
return logError(msg, app.name);
|
|
1118
1139
|
}
|
|
1119
|
-
flatChildren(wrapElement, app
|
|
1140
|
+
flatChildren(wrapElement, app);
|
|
1120
1141
|
if (app.source.links.size) {
|
|
1121
1142
|
fetchLinksFromHtml(wrapElement, app, microAppHead);
|
|
1122
1143
|
}
|
|
@@ -1135,7 +1156,7 @@ function extractSourceDom(htmlStr, app) {
|
|
|
1135
1156
|
* @param app app
|
|
1136
1157
|
*/
|
|
1137
1158
|
function extractHtml(app) {
|
|
1138
|
-
fetchSource(app.url, app.name, { cache: 'no-cache' }).then((htmlStr) => {
|
|
1159
|
+
fetchSource(app.ssrUrl || app.url, app.name, { cache: 'no-cache' }).then((htmlStr) => {
|
|
1139
1160
|
if (!htmlStr) {
|
|
1140
1161
|
const msg = 'html is empty, please check in detail';
|
|
1141
1162
|
app.onerror(new Error(msg));
|
|
@@ -1243,9 +1264,7 @@ function overwriteDocumentOnClick() {
|
|
|
1243
1264
|
}
|
|
1244
1265
|
}
|
|
1245
1266
|
});
|
|
1246
|
-
|
|
1247
|
-
document.onclick = rawOnClick;
|
|
1248
|
-
}
|
|
1267
|
+
rawOnClick && (document.onclick = rawOnClick);
|
|
1249
1268
|
}
|
|
1250
1269
|
/**
|
|
1251
1270
|
* The document event is globally, we need to clear these event bindings when micro application unmounted
|
|
@@ -1253,9 +1272,7 @@ function overwriteDocumentOnClick() {
|
|
|
1253
1272
|
const documentEventListenerMap = new Map();
|
|
1254
1273
|
function effectDocumentEvent() {
|
|
1255
1274
|
const { rawDocument, rawDocumentAddEventListener, rawDocumentRemoveEventListener, } = globalEnv;
|
|
1256
|
-
|
|
1257
|
-
overwriteDocumentOnClick();
|
|
1258
|
-
}
|
|
1275
|
+
!hasRewriteDocumentOnClick && overwriteDocumentOnClick();
|
|
1259
1276
|
document.addEventListener = function (type, listener, options) {
|
|
1260
1277
|
var _a;
|
|
1261
1278
|
const appName = getCurrentAppName();
|
|
@@ -1281,8 +1298,9 @@ function effectDocumentEvent() {
|
|
|
1281
1298
|
rawDocumentAddEventListener.call(rawDocument, type, listener, options);
|
|
1282
1299
|
};
|
|
1283
1300
|
document.removeEventListener = function (type, listener, options) {
|
|
1301
|
+
var _a;
|
|
1284
1302
|
const appName = getCurrentAppName();
|
|
1285
|
-
if (appName) {
|
|
1303
|
+
if (appName && !(((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.umdMode) && isBoundFunction(listener))) {
|
|
1286
1304
|
const appListenersMap = documentEventListenerMap.get(appName);
|
|
1287
1305
|
if (appListenersMap) {
|
|
1288
1306
|
const appListenerList = appListenersMap.get(type);
|
|
@@ -1578,9 +1596,7 @@ class EventCenterForGlobal {
|
|
|
1578
1596
|
* @param cb listener
|
|
1579
1597
|
*/
|
|
1580
1598
|
removeGlobalDataListener(cb) {
|
|
1581
|
-
|
|
1582
|
-
eventCenter.off('global', cb);
|
|
1583
|
-
}
|
|
1599
|
+
isFunction(cb) && eventCenter.off('global', cb);
|
|
1584
1600
|
}
|
|
1585
1601
|
/**
|
|
1586
1602
|
* dispatch global data
|
|
@@ -1624,7 +1640,7 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
1624
1640
|
* @param autoTrigger If there is cached data when first bind listener, whether it needs to trigger, default is false
|
|
1625
1641
|
*/
|
|
1626
1642
|
addDataListener(appName, cb, autoTrigger) {
|
|
1627
|
-
eventCenter.on(formatEventName(appName, false), cb, autoTrigger);
|
|
1643
|
+
eventCenter.on(formatEventName(formatAppName(appName), false), cb, autoTrigger);
|
|
1628
1644
|
}
|
|
1629
1645
|
/**
|
|
1630
1646
|
* remove listener
|
|
@@ -1632,9 +1648,7 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
1632
1648
|
* @param cb listener
|
|
1633
1649
|
*/
|
|
1634
1650
|
removeDataListener(appName, cb) {
|
|
1635
|
-
|
|
1636
|
-
eventCenter.off(formatEventName(appName, false), cb);
|
|
1637
|
-
}
|
|
1651
|
+
isFunction(cb) && eventCenter.off(formatEventName(formatAppName(appName), false), cb);
|
|
1638
1652
|
}
|
|
1639
1653
|
/**
|
|
1640
1654
|
* get data from micro app or base app
|
|
@@ -1642,7 +1656,7 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
1642
1656
|
* @param fromBaseApp whether get data from base app, default is false
|
|
1643
1657
|
*/
|
|
1644
1658
|
getData(appName, fromBaseApp = false) {
|
|
1645
|
-
return eventCenter.getData(formatEventName(appName, fromBaseApp));
|
|
1659
|
+
return eventCenter.getData(formatEventName(formatAppName(appName), fromBaseApp));
|
|
1646
1660
|
}
|
|
1647
1661
|
/**
|
|
1648
1662
|
* Dispatch data to the specified micro app
|
|
@@ -1650,21 +1664,22 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
1650
1664
|
* @param data data
|
|
1651
1665
|
*/
|
|
1652
1666
|
setData(appName, data) {
|
|
1653
|
-
eventCenter.dispatch(formatEventName(appName, true), data);
|
|
1667
|
+
eventCenter.dispatch(formatEventName(formatAppName(appName), true), data);
|
|
1654
1668
|
}
|
|
1655
1669
|
/**
|
|
1656
1670
|
* clear all listener for specified micro app
|
|
1657
1671
|
* @param appName app.name
|
|
1658
1672
|
*/
|
|
1659
1673
|
clearDataListener(appName) {
|
|
1660
|
-
eventCenter.off(formatEventName(appName, false));
|
|
1674
|
+
eventCenter.off(formatEventName(formatAppName(appName), false));
|
|
1661
1675
|
}
|
|
1662
1676
|
}
|
|
1663
1677
|
// Event center for sub app
|
|
1664
1678
|
class EventCenterForMicroApp extends EventCenterForGlobal {
|
|
1665
1679
|
constructor(appName) {
|
|
1666
1680
|
super();
|
|
1667
|
-
this.appName = appName;
|
|
1681
|
+
this.appName = formatAppName(appName);
|
|
1682
|
+
!this.appName && logError(`Invalid appName ${appName}`);
|
|
1668
1683
|
}
|
|
1669
1684
|
/**
|
|
1670
1685
|
* add listener, monitor the data sent by the base app
|
|
@@ -1680,9 +1695,7 @@ class EventCenterForMicroApp extends EventCenterForGlobal {
|
|
|
1680
1695
|
* @param cb listener
|
|
1681
1696
|
*/
|
|
1682
1697
|
removeDataListener(cb) {
|
|
1683
|
-
|
|
1684
|
-
eventCenter.off(formatEventName(this.appName, true), cb);
|
|
1685
|
-
}
|
|
1698
|
+
isFunction(cb) && eventCenter.off(formatEventName(this.appName, true), cb);
|
|
1686
1699
|
}
|
|
1687
1700
|
/**
|
|
1688
1701
|
* get data from base app
|
|
@@ -1704,11 +1717,7 @@ class EventCenterForMicroApp extends EventCenterForGlobal {
|
|
|
1704
1717
|
data,
|
|
1705
1718
|
}
|
|
1706
1719
|
});
|
|
1707
|
-
|
|
1708
|
-
if (isShadowRoot(element)) {
|
|
1709
|
-
element = element.host;
|
|
1710
|
-
}
|
|
1711
|
-
element.dispatchEvent(event);
|
|
1720
|
+
getRootContainer(app.container).dispatchEvent(event);
|
|
1712
1721
|
}
|
|
1713
1722
|
}
|
|
1714
1723
|
/**
|
|
@@ -1778,8 +1787,7 @@ const unscopables = {
|
|
|
1778
1787
|
*/
|
|
1779
1788
|
let macroTimer;
|
|
1780
1789
|
function macroTask(fn) {
|
|
1781
|
-
|
|
1782
|
-
clearTimeout(macroTimer);
|
|
1790
|
+
macroTimer && clearTimeout(macroTimer);
|
|
1783
1791
|
macroTimer = setTimeout(fn, 0);
|
|
1784
1792
|
}
|
|
1785
1793
|
class SandBox {
|
|
@@ -1880,12 +1888,15 @@ class SandBox {
|
|
|
1880
1888
|
return key in target;
|
|
1881
1889
|
return key in unscopables || key in target || key in rawWindow;
|
|
1882
1890
|
},
|
|
1891
|
+
// Object.getOwnPropertyDescriptor(window, key)
|
|
1892
|
+
// TODO: use set
|
|
1883
1893
|
getOwnPropertyDescriptor: (target, key) => {
|
|
1884
1894
|
if (target.hasOwnProperty(key)) {
|
|
1885
1895
|
descriptorTargetMap.set(key, 'target');
|
|
1886
1896
|
return Object.getOwnPropertyDescriptor(target, key);
|
|
1887
1897
|
}
|
|
1888
1898
|
if (rawWindow.hasOwnProperty(key)) {
|
|
1899
|
+
// like console, alert ...
|
|
1889
1900
|
descriptorTargetMap.set(key, 'rawWindow');
|
|
1890
1901
|
const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
|
|
1891
1902
|
if (descriptor && !descriptor.configurable) {
|
|
@@ -1895,6 +1906,7 @@ class SandBox {
|
|
|
1895
1906
|
}
|
|
1896
1907
|
return undefined;
|
|
1897
1908
|
},
|
|
1909
|
+
// Object.defineProperty(window, key, Descriptor)
|
|
1898
1910
|
defineProperty: (target, key, value) => {
|
|
1899
1911
|
const from = descriptorTargetMap.get(key);
|
|
1900
1912
|
if (from === 'rawWindow') {
|
|
@@ -1902,14 +1914,14 @@ class SandBox {
|
|
|
1902
1914
|
}
|
|
1903
1915
|
return Reflect.defineProperty(target, key, value);
|
|
1904
1916
|
},
|
|
1917
|
+
// Object.getOwnPropertyNames(window)
|
|
1905
1918
|
ownKeys: (target) => {
|
|
1906
1919
|
return unique(Reflect.ownKeys(rawWindow).concat(Reflect.ownKeys(target)));
|
|
1907
1920
|
},
|
|
1908
1921
|
deleteProperty: (target, key) => {
|
|
1909
1922
|
if (target.hasOwnProperty(key)) {
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
}
|
|
1923
|
+
this.injectedKeys.has(key) && this.injectedKeys.delete(key);
|
|
1924
|
+
this.escapeKeys.has(key) && Reflect.deleteProperty(rawWindow, key);
|
|
1913
1925
|
return Reflect.deleteProperty(target, key);
|
|
1914
1926
|
}
|
|
1915
1927
|
return true;
|
|
@@ -1920,8 +1932,8 @@ class SandBox {
|
|
|
1920
1932
|
if (!this.active) {
|
|
1921
1933
|
this.active = true;
|
|
1922
1934
|
this.microWindow.__MICRO_APP_BASE_ROUTE__ = this.microWindow.__MICRO_APP_BASE_URL__ = baseroute;
|
|
1923
|
-
|
|
1924
|
-
|
|
1935
|
+
// BUG FIX: bable-polyfill@6.x
|
|
1936
|
+
globalEnv.rawWindow._babelPolyfill && (globalEnv.rawWindow._babelPolyfill = false);
|
|
1925
1937
|
if (++SandBox.activeCount === 1) {
|
|
1926
1938
|
effectDocumentEvent();
|
|
1927
1939
|
}
|
|
@@ -2042,9 +2054,7 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
|
|
|
2042
2054
|
if (!element) {
|
|
2043
2055
|
return logError(`element does not exist in lifecycle ${lifecycleName}`, appName);
|
|
2044
2056
|
}
|
|
2045
|
-
|
|
2046
|
-
element = element.host;
|
|
2047
|
-
}
|
|
2057
|
+
element = getRootContainer(element);
|
|
2048
2058
|
// clear dom scope before dispatch lifeCycles event to base app, especially mounted & unmount
|
|
2049
2059
|
removeDomScope();
|
|
2050
2060
|
const detail = Object.assign({
|
|
@@ -2077,7 +2087,7 @@ function dispatchUnmountToMicroApp(appName) {
|
|
|
2077
2087
|
// micro app instances
|
|
2078
2088
|
const appInstanceMap = new Map();
|
|
2079
2089
|
class CreateApp {
|
|
2080
|
-
constructor({ name, url, container, inline, scopecss, useSandbox, macro, baseroute }) {
|
|
2090
|
+
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, macro, baseroute, }) {
|
|
2081
2091
|
this.status = appStatus.NOT_LOADED;
|
|
2082
2092
|
this.loadSourceLevel = 0;
|
|
2083
2093
|
this.umdHookMount = null;
|
|
@@ -2092,6 +2102,7 @@ class CreateApp {
|
|
|
2092
2102
|
this.container = container !== null && container !== void 0 ? container : null;
|
|
2093
2103
|
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
2094
2104
|
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : '';
|
|
2105
|
+
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
2095
2106
|
// optional during init👆
|
|
2096
2107
|
this.name = name;
|
|
2097
2108
|
this.url = url;
|
|
@@ -2103,9 +2114,7 @@ class CreateApp {
|
|
|
2103
2114
|
scripts: new Map(),
|
|
2104
2115
|
};
|
|
2105
2116
|
this.loadSourceCode();
|
|
2106
|
-
|
|
2107
|
-
this.sandBox = new SandBox(name, url, this.macro);
|
|
2108
|
-
}
|
|
2117
|
+
this.useSandbox && (this.sandBox = new SandBox(name, url, this.macro));
|
|
2109
2118
|
}
|
|
2110
2119
|
// Load resources
|
|
2111
2120
|
loadSourceCode() {
|
|
@@ -2154,7 +2163,7 @@ class CreateApp {
|
|
|
2154
2163
|
}
|
|
2155
2164
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
|
|
2156
2165
|
this.status = appStatus.MOUNTING;
|
|
2157
|
-
|
|
2166
|
+
cloneContainer(this.source.html, this.container, !this.umdMode);
|
|
2158
2167
|
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.start(this.baseroute);
|
|
2159
2168
|
let umdHookMountResult; // result of mount function
|
|
2160
2169
|
if (!this.umdMode) {
|
|
@@ -2215,12 +2224,7 @@ class CreateApp {
|
|
|
2215
2224
|
dispatchMountedEvent() {
|
|
2216
2225
|
if (appStatus.UNMOUNT !== this.status) {
|
|
2217
2226
|
this.status = appStatus.MOUNTED;
|
|
2218
|
-
// remove defer in v0.4.2
|
|
2219
|
-
// defer(() => {
|
|
2220
|
-
// if (appStatus.UNMOUNT !== this.status) {
|
|
2221
2227
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.MOUNTED);
|
|
2222
|
-
// }
|
|
2223
|
-
// })
|
|
2224
2228
|
}
|
|
2225
2229
|
}
|
|
2226
2230
|
/**
|
|
@@ -2273,21 +2277,24 @@ class CreateApp {
|
|
|
2273
2277
|
// dispatch unmount event to base app
|
|
2274
2278
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.UNMOUNT);
|
|
2275
2279
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.stop();
|
|
2276
|
-
// actions for completely destroy
|
|
2277
2280
|
if (destroy) {
|
|
2278
|
-
|
|
2279
|
-
delete window[this.libraryName];
|
|
2280
|
-
}
|
|
2281
|
-
appInstanceMap.delete(this.name);
|
|
2281
|
+
this.actionsForCompletelyDestory();
|
|
2282
2282
|
}
|
|
2283
2283
|
else if (this.umdMode && this.container.childElementCount) {
|
|
2284
2284
|
/**
|
|
2285
2285
|
* In umd mode, ui frameworks will no longer create style elements to head in lazy load page when render again, so we should save container to keep these elements
|
|
2286
2286
|
*/
|
|
2287
|
-
|
|
2287
|
+
cloneContainer(this.container, this.source.html, false);
|
|
2288
2288
|
}
|
|
2289
2289
|
this.container = null;
|
|
2290
2290
|
}
|
|
2291
|
+
// actions for completely destroy
|
|
2292
|
+
actionsForCompletelyDestory() {
|
|
2293
|
+
if (!this.useSandbox && this.umdMode) {
|
|
2294
|
+
delete window[this.libraryName];
|
|
2295
|
+
}
|
|
2296
|
+
appInstanceMap.delete(this.name);
|
|
2297
|
+
}
|
|
2291
2298
|
/**
|
|
2292
2299
|
* app rendering error
|
|
2293
2300
|
* @param e Error
|
|
@@ -2305,13 +2312,27 @@ class CreateApp {
|
|
|
2305
2312
|
// after execScripts, the app maybe unmounted
|
|
2306
2313
|
if (appStatus.UNMOUNT !== this.status) {
|
|
2307
2314
|
const global = ((_b = (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow) !== null && _b !== void 0 ? _b : globalEnv.rawWindow);
|
|
2308
|
-
this.libraryName = (
|
|
2315
|
+
this.libraryName = getRootContainer(this.container).getAttribute('library') || `micro-app-${this.name}`;
|
|
2309
2316
|
// do not use isObject
|
|
2310
2317
|
return typeof global[this.libraryName] === 'object' ? global[this.libraryName] : {};
|
|
2311
2318
|
}
|
|
2312
2319
|
return {};
|
|
2313
2320
|
}
|
|
2314
2321
|
}
|
|
2322
|
+
// if app not prefetch & not unmount, then app is active
|
|
2323
|
+
function getActiveApps() {
|
|
2324
|
+
const activeApps = [];
|
|
2325
|
+
appInstanceMap.forEach((app, appName) => {
|
|
2326
|
+
if (appStatus.UNMOUNT !== app.getAppStatus() && !app.isPrefetch) {
|
|
2327
|
+
activeApps.push(appName);
|
|
2328
|
+
}
|
|
2329
|
+
});
|
|
2330
|
+
return activeApps;
|
|
2331
|
+
}
|
|
2332
|
+
// get all registered apps
|
|
2333
|
+
function getAllApps() {
|
|
2334
|
+
return Array.from(appInstanceMap.keys());
|
|
2335
|
+
}
|
|
2315
2336
|
|
|
2316
2337
|
// Record element and map element
|
|
2317
2338
|
const dynamicElementInMicroAppMap = new WeakMap();
|
|
@@ -2329,7 +2350,7 @@ function handleNewNode(parent, child, app) {
|
|
|
2329
2350
|
return replaceComment;
|
|
2330
2351
|
}
|
|
2331
2352
|
else if (app.scopecss && !child.hasAttribute('ignore')) {
|
|
2332
|
-
return scopedCSS(child, app
|
|
2353
|
+
return scopedCSS(child, app);
|
|
2333
2354
|
}
|
|
2334
2355
|
return child;
|
|
2335
2356
|
}
|
|
@@ -2339,13 +2360,13 @@ function handleNewNode(parent, child, app) {
|
|
|
2339
2360
|
dynamicElementInMicroAppMap.set(child, linkReplaceComment);
|
|
2340
2361
|
return linkReplaceComment;
|
|
2341
2362
|
}
|
|
2342
|
-
else if (
|
|
2363
|
+
else if (child.hasAttribute('ignore')) {
|
|
2343
2364
|
return child;
|
|
2344
2365
|
}
|
|
2345
|
-
const { url, info, replaceComment } = extractLinkFromHtml(child, parent, app,
|
|
2366
|
+
const { url, info, replaceComment } = extractLinkFromHtml(child, parent, app, true);
|
|
2346
2367
|
if (url && info) {
|
|
2347
2368
|
const replaceStyle = pureCreateElement('style');
|
|
2348
|
-
replaceStyle.
|
|
2369
|
+
replaceStyle.__MICRO_APP_LINK_PATH__ = url;
|
|
2349
2370
|
foramtDynamicLink(url, info, app, child, replaceStyle);
|
|
2350
2371
|
dynamicElementInMicroAppMap.set(child, replaceStyle);
|
|
2351
2372
|
return replaceStyle;
|
|
@@ -2359,8 +2380,8 @@ function handleNewNode(parent, child, app) {
|
|
|
2359
2380
|
else if (child instanceof HTMLScriptElement) {
|
|
2360
2381
|
const { replaceComment, url, info } = extractScriptElement(child, parent, app, true) || {};
|
|
2361
2382
|
if (url && info) {
|
|
2362
|
-
if (info.
|
|
2363
|
-
const replaceElement = runScript(url,
|
|
2383
|
+
if (!info.isExternal) { // inline script
|
|
2384
|
+
const replaceElement = runScript(url, app, info, true);
|
|
2364
2385
|
dynamicElementInMicroAppMap.set(child, replaceElement);
|
|
2365
2386
|
return replaceElement;
|
|
2366
2387
|
}
|
|
@@ -2494,7 +2515,7 @@ function patchElementPrototypeMethods() {
|
|
|
2494
2515
|
logWarn('property data must be an object', this.getAttribute('name'));
|
|
2495
2516
|
}
|
|
2496
2517
|
}
|
|
2497
|
-
else if (((key === 'src' && /^(img|script)$/i.test(this.tagName)) ||
|
|
2518
|
+
else if ((((key === 'src' || key === 'srcset') && /^(img|script)$/i.test(this.tagName)) ||
|
|
2498
2519
|
(key === 'href' && /^link$/i.test(this.tagName))) &&
|
|
2499
2520
|
this.__MICRO_APP_NAME__ &&
|
|
2500
2521
|
appInstanceMap.has(this.__MICRO_APP_NAME__)) {
|
|
@@ -2681,17 +2702,10 @@ function rejectMicroAppStyle() {
|
|
|
2681
2702
|
function unmountNestedApp() {
|
|
2682
2703
|
replaseUnmountOfNestedApp();
|
|
2683
2704
|
appInstanceMap.forEach(app => {
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
if (isShadowRoot(element)) {
|
|
2687
|
-
element = element.host;
|
|
2688
|
-
}
|
|
2689
|
-
// @ts-ignore
|
|
2690
|
-
element.disconnectedCallback();
|
|
2691
|
-
}
|
|
2705
|
+
// @ts-ignore
|
|
2706
|
+
app.container && getRootContainer(app.container).disconnectedCallback();
|
|
2692
2707
|
});
|
|
2693
|
-
|
|
2694
|
-
appInstanceMap.clear();
|
|
2708
|
+
!window.__MICRO_APP_UMD_MODE__ && appInstanceMap.clear();
|
|
2695
2709
|
if (elementInstanceMap.size) {
|
|
2696
2710
|
elementInstanceMap.clear();
|
|
2697
2711
|
releasePatches();
|
|
@@ -2723,8 +2737,9 @@ function defineElement(tagName) {
|
|
|
2723
2737
|
this.isWating = false;
|
|
2724
2738
|
this.cacheData = null;
|
|
2725
2739
|
this.hasConnected = false;
|
|
2726
|
-
this.appName = '';
|
|
2727
|
-
this.appUrl = '';
|
|
2740
|
+
this.appName = ''; // app name
|
|
2741
|
+
this.appUrl = ''; // app url
|
|
2742
|
+
this.ssrUrl = ''; // html path in ssr mode
|
|
2728
2743
|
this.version = version;
|
|
2729
2744
|
/**
|
|
2730
2745
|
* handle for change of name an url after element inited
|
|
@@ -2732,28 +2747,45 @@ function defineElement(tagName) {
|
|
|
2732
2747
|
this.handleAttributeUpdate = () => {
|
|
2733
2748
|
var _a;
|
|
2734
2749
|
this.isWating = false;
|
|
2735
|
-
const
|
|
2736
|
-
const
|
|
2737
|
-
if (this.legalAttribute('name',
|
|
2738
|
-
const existApp = appInstanceMap.get(
|
|
2739
|
-
if (
|
|
2750
|
+
const formatAttrName = formatAppName(this.getAttribute('name'));
|
|
2751
|
+
const formatAttrUrl = formatAppURL(this.getAttribute('url'), this.appName);
|
|
2752
|
+
if (this.legalAttribute('name', formatAttrName) && this.legalAttribute('url', formatAttrUrl)) {
|
|
2753
|
+
const existApp = appInstanceMap.get(formatAttrName);
|
|
2754
|
+
if (formatAttrName !== this.appName && existApp) {
|
|
2740
2755
|
// handling of cached and non-prefetch apps
|
|
2741
2756
|
if (appStatus.UNMOUNT !== existApp.getAppStatus() && !existApp.isPrefetch) {
|
|
2742
2757
|
this.setAttribute('name', this.appName);
|
|
2743
|
-
return logError(`an app named ${
|
|
2758
|
+
return logError(`an app named ${formatAttrName} already exists`, this.appName);
|
|
2744
2759
|
}
|
|
2745
2760
|
}
|
|
2746
|
-
if (
|
|
2747
|
-
this.handleUnmount(
|
|
2748
|
-
|
|
2749
|
-
|
|
2761
|
+
if (formatAttrName !== this.appName || formatAttrUrl !== this.appUrl) {
|
|
2762
|
+
this.handleUnmount(formatAttrName === this.appName);
|
|
2763
|
+
/**
|
|
2764
|
+
* change ssrUrl in ssr mode
|
|
2765
|
+
* do not add judgment of formatAttrUrl === this.appUrl
|
|
2766
|
+
*/
|
|
2767
|
+
if (this.getDisposeResult('ssr')) {
|
|
2768
|
+
this.ssrUrl = CompletionPath(globalEnv.rawWindow.location.pathname, formatAttrUrl);
|
|
2769
|
+
}
|
|
2770
|
+
else if (this.ssrUrl) {
|
|
2771
|
+
this.ssrUrl = '';
|
|
2772
|
+
}
|
|
2773
|
+
this.appName = formatAttrName;
|
|
2774
|
+
this.appUrl = formatAttrUrl;
|
|
2750
2775
|
((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this).innerHTML = '';
|
|
2776
|
+
if (formatAttrName !== this.getAttribute('name')) {
|
|
2777
|
+
this.setAttribute('name', this.appName);
|
|
2778
|
+
}
|
|
2751
2779
|
/**
|
|
2752
|
-
* when existApp not
|
|
2753
|
-
* if
|
|
2754
|
-
* if
|
|
2780
|
+
* when existApp not null:
|
|
2781
|
+
* scene1: if formatAttrName and this.appName are equal: exitApp is the current app, the url must be different, existApp has been unmounted
|
|
2782
|
+
* scene2: if formatAttrName and this.appName are different: existApp must be prefetch or unmounted, if url is equal, then just mount, if url is different, then create new app to replace existApp
|
|
2783
|
+
* scene3: url is different but ssrUrl is equal
|
|
2784
|
+
* scene4: url is equal but ssrUrl is different, if url is equal, name must different
|
|
2755
2785
|
*/
|
|
2756
|
-
if (existApp &&
|
|
2786
|
+
if (existApp &&
|
|
2787
|
+
existApp.url === this.appUrl &&
|
|
2788
|
+
existApp.ssrUrl === this.ssrUrl) {
|
|
2757
2789
|
// mount app
|
|
2758
2790
|
this.handleAppMount(existApp);
|
|
2759
2791
|
}
|
|
@@ -2762,7 +2794,7 @@ function defineElement(tagName) {
|
|
|
2762
2794
|
}
|
|
2763
2795
|
}
|
|
2764
2796
|
}
|
|
2765
|
-
else if (
|
|
2797
|
+
else if (formatAttrName !== this.appName) {
|
|
2766
2798
|
this.setAttribute('name', this.appName);
|
|
2767
2799
|
}
|
|
2768
2800
|
};
|
|
@@ -2804,19 +2836,26 @@ function defineElement(tagName) {
|
|
|
2804
2836
|
if (this.legalAttribute(attr, newVal) &&
|
|
2805
2837
|
this[attr === ObservedAttrName.NAME ? 'appName' : 'appUrl'] !== newVal) {
|
|
2806
2838
|
if (attr === ObservedAttrName.URL && !this.appUrl) {
|
|
2807
|
-
newVal =
|
|
2839
|
+
newVal = formatAppURL(newVal, this.appName);
|
|
2808
2840
|
if (!newVal) {
|
|
2809
|
-
return logError(
|
|
2841
|
+
return logError(`Invalid attribute url ${newVal}`, this.appName);
|
|
2810
2842
|
}
|
|
2811
2843
|
this.appUrl = newVal;
|
|
2812
2844
|
this.handleInitialNameAndUrl();
|
|
2813
2845
|
}
|
|
2814
2846
|
else if (attr === ObservedAttrName.NAME && !this.appName) {
|
|
2847
|
+
const formatNewName = formatAppName(newVal);
|
|
2848
|
+
if (!formatNewName) {
|
|
2849
|
+
return logError(`Invalid attribute name ${newVal}`, this.appName);
|
|
2850
|
+
}
|
|
2815
2851
|
if (this.cacheData) {
|
|
2816
|
-
microApp.setData(
|
|
2852
|
+
microApp.setData(formatNewName, this.cacheData);
|
|
2817
2853
|
this.cacheData = null;
|
|
2818
2854
|
}
|
|
2819
|
-
this.appName =
|
|
2855
|
+
this.appName = formatNewName;
|
|
2856
|
+
if (formatNewName !== newVal) {
|
|
2857
|
+
this.setAttribute('name', this.appName);
|
|
2858
|
+
}
|
|
2820
2859
|
this.handleInitialNameAndUrl();
|
|
2821
2860
|
}
|
|
2822
2861
|
else if (!this.isWating) {
|
|
@@ -2827,9 +2866,7 @@ function defineElement(tagName) {
|
|
|
2827
2866
|
}
|
|
2828
2867
|
// handle for connectedCallback run before attributeChangedCallback
|
|
2829
2868
|
handleInitialNameAndUrl() {
|
|
2830
|
-
|
|
2831
|
-
this.initialMount();
|
|
2832
|
-
}
|
|
2869
|
+
this.hasConnected && this.initialMount();
|
|
2833
2870
|
}
|
|
2834
2871
|
// Perform global initialization when the element count is 1
|
|
2835
2872
|
performWhenFirstCreated() {
|
|
@@ -2849,20 +2886,25 @@ function defineElement(tagName) {
|
|
|
2849
2886
|
if (this.getDisposeResult('shadowDOM') && !this.shadowRoot && isFunction(this.attachShadow)) {
|
|
2850
2887
|
this.attachShadow({ mode: 'open' });
|
|
2851
2888
|
}
|
|
2889
|
+
if (this.getDisposeResult('ssr')) {
|
|
2890
|
+
this.ssrUrl = CompletionPath(globalEnv.rawWindow.location.pathname, this.appUrl);
|
|
2891
|
+
}
|
|
2892
|
+
else if (this.ssrUrl) {
|
|
2893
|
+
this.ssrUrl = '';
|
|
2894
|
+
}
|
|
2852
2895
|
const app = appInstanceMap.get(this.appName);
|
|
2853
2896
|
if (app) {
|
|
2854
|
-
|
|
2897
|
+
const existAppUrl = app.ssrUrl || app.url;
|
|
2898
|
+
const activeAppUrl = this.ssrUrl || this.appUrl;
|
|
2899
|
+
if (existAppUrl === activeAppUrl && (app.isPrefetch ||
|
|
2855
2900
|
app.getAppStatus() === appStatus.UNMOUNT)) {
|
|
2856
2901
|
this.handleAppMount(app);
|
|
2857
2902
|
}
|
|
2858
|
-
else if (app.isPrefetch) {
|
|
2859
|
-
logError(`the url ${this.appUrl} is different from prefetch url ${app.url}`, this.appName);
|
|
2860
|
-
}
|
|
2861
|
-
else if (app.getAppStatus() === appStatus.UNMOUNT) {
|
|
2903
|
+
else if (app.isPrefetch || app.getAppStatus() === appStatus.UNMOUNT) {
|
|
2862
2904
|
/**
|
|
2863
|
-
*
|
|
2864
|
-
* if old app has unmounted and url is different, create new app to replace old one
|
|
2905
|
+
* url is different & old app is unmounted or prefetch, create new app to replace old one
|
|
2865
2906
|
*/
|
|
2907
|
+
logWarn(`the ${app.isPrefetch ? 'prefetch' : 'unmounted'} app with url: ${existAppUrl} is replaced by a new app`, this.appName);
|
|
2866
2908
|
this.handleCreateApp();
|
|
2867
2909
|
}
|
|
2868
2910
|
else {
|
|
@@ -2902,9 +2944,17 @@ function defineElement(tagName) {
|
|
|
2902
2944
|
// create app instance
|
|
2903
2945
|
handleCreateApp() {
|
|
2904
2946
|
var _a;
|
|
2947
|
+
/**
|
|
2948
|
+
* actions for destory old app
|
|
2949
|
+
* fix of unmounted umd app with disableSandbox
|
|
2950
|
+
*/
|
|
2951
|
+
if (appInstanceMap.has(this.appName)) {
|
|
2952
|
+
appInstanceMap.get(this.appName).actionsForCompletelyDestory();
|
|
2953
|
+
}
|
|
2905
2954
|
const instance = new CreateApp({
|
|
2906
2955
|
name: this.appName,
|
|
2907
2956
|
url: this.appUrl,
|
|
2957
|
+
ssrUrl: this.ssrUrl,
|
|
2908
2958
|
container: (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this,
|
|
2909
2959
|
inline: this.getDisposeResult('inline'),
|
|
2910
2960
|
scopecss: !(this.getDisposeResult('disableScopecss') || this.getDisposeResult('shadowDOM')),
|
|
@@ -2972,12 +3022,12 @@ function filterPreFetchTarget(apps) {
|
|
|
2972
3022
|
const validApps = [];
|
|
2973
3023
|
if (isArray(apps)) {
|
|
2974
3024
|
apps.forEach((item) => {
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
item.url &&
|
|
2979
|
-
|
|
2980
|
-
|
|
3025
|
+
if (isPlainObject(item)) {
|
|
3026
|
+
item.name = formatAppName(item.name);
|
|
3027
|
+
item.url = formatAppURL(item.url, item.name);
|
|
3028
|
+
if (item.name && item.url && !appInstanceMap.has(item.name)) {
|
|
3029
|
+
validApps.push(item);
|
|
3030
|
+
}
|
|
2981
3031
|
}
|
|
2982
3032
|
});
|
|
2983
3033
|
}
|
|
@@ -3004,8 +3054,7 @@ function preFetch(apps) {
|
|
|
3004
3054
|
return logError('preFetch is only supported in browser environment');
|
|
3005
3055
|
}
|
|
3006
3056
|
requestIdleCallback(() => {
|
|
3007
|
-
|
|
3008
|
-
apps = apps();
|
|
3057
|
+
isFunction(apps) && (apps = apps());
|
|
3009
3058
|
filterPreFetchTarget(apps).forEach((item) => {
|
|
3010
3059
|
var _a, _b, _c;
|
|
3011
3060
|
const app = new CreateApp({
|
|
@@ -3090,7 +3139,7 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
3090
3139
|
this.destroy = options.destroy;
|
|
3091
3140
|
/**
|
|
3092
3141
|
* compatible with versions below 0.4.2 of destroy
|
|
3093
|
-
*
|
|
3142
|
+
* do not merge with the previous line
|
|
3094
3143
|
*/
|
|
3095
3144
|
// @ts-ignore
|
|
3096
3145
|
this.destory = options.destory;
|
|
@@ -3098,28 +3147,33 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
3098
3147
|
this.disableScopecss = options.disableScopecss;
|
|
3099
3148
|
this.disableSandbox = options.disableSandbox;
|
|
3100
3149
|
this.macro = options.macro;
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
this.lifeCycles = options.lifeCycles;
|
|
3105
|
-
}
|
|
3106
|
-
if (isPlainObject(options.plugins)) {
|
|
3107
|
-
this.plugins = options.plugins;
|
|
3108
|
-
}
|
|
3150
|
+
this.ssr = options.ssr;
|
|
3151
|
+
isFunction(options.fetch) && (this.fetch = options.fetch);
|
|
3152
|
+
isPlainObject(options.lifeCycles) && (this.lifeCycles = options.lifeCycles);
|
|
3109
3153
|
// load app assets when browser is idle
|
|
3110
|
-
|
|
3111
|
-
preFetch(options.preFetchApps);
|
|
3112
|
-
}
|
|
3154
|
+
options.preFetchApps && preFetch(options.preFetchApps);
|
|
3113
3155
|
// load global assets when browser is idle
|
|
3114
|
-
|
|
3115
|
-
|
|
3156
|
+
options.globalAssets && getGlobalAssets(options.globalAssets);
|
|
3157
|
+
if (isPlainObject(options.plugins)) {
|
|
3158
|
+
const modules = options.plugins.modules;
|
|
3159
|
+
if (isPlainObject(modules)) {
|
|
3160
|
+
for (const appName in modules) {
|
|
3161
|
+
const formattedAppName = formatAppName(appName);
|
|
3162
|
+
if (formattedAppName && appName !== formattedAppName) {
|
|
3163
|
+
modules[formattedAppName] = modules[appName];
|
|
3164
|
+
delete modules[appName];
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
this.plugins = options.plugins;
|
|
3116
3169
|
}
|
|
3117
3170
|
}
|
|
3171
|
+
// define customElement after init
|
|
3118
3172
|
defineElement(this.tagName);
|
|
3119
3173
|
}
|
|
3120
3174
|
}
|
|
3121
3175
|
var microApp = new MicroApp();
|
|
3122
3176
|
|
|
3123
3177
|
export default microApp;
|
|
3124
|
-
export { EventCenterForMicroApp, preFetch, pureCreateElement, removeDomScope,
|
|
3178
|
+
export { EventCenterForMicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, removeDomScope, version };
|
|
3125
3179
|
//# sourceMappingURL=index.esm.js.map
|