@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/lib/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = '0.4.3';
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
- * Format URL address
89
- * @param url address
88
+ * format URL address
89
+ * note the scenes:
90
+ * 1. micro-app -> attributeChangedCallback
91
+ * 2. preFetch
90
92
  */
91
- function formatURL(url, appName = null) {
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
- // export function formatName (name: string): string {
109
- // if (!isString(name) || !name) return ''
110
- // return name.replace(/(^\d+)|([^\w\d-_])/gi, '')
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 cloneNode(origin, target, deep) {
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
- const rules = Array.from((_b = (_a = templateStyle.sheet) === null || _a === void 0 ? void 0 : _a.cssRules) !== null && _b !== void 0 ? _b : []);
503
- let result = scopedHost(scopedRule(rules, prefix), baseURI, originContent, linkpath);
504
- /**
505
- * Solve the problem of missing content quotes in some Safari browsers
506
- * docs: https://developer.mozilla.org/zh-CN/docs/Web/CSS/content
507
- * If there are still problems, it is recommended to use the attr()
508
- */
509
- if (isSafari()) {
510
- result = result.replace(/([;{]\s*content:\s*)([^\s"][^";}]*)/gm, (all, $1, $2) => {
511
- if ($2 === 'none' ||
512
- /^(url\()|(counter\()|(attr\()|(open-quote)|(close-quote)/.test($2)) {
513
- return all;
514
- }
515
- return `${$1}"${$2}"`;
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, appName) {
526
- const app = appInstanceMap.get(appName);
527
- if (app === null || app === void 0 ? void 0 : app.scopecss) {
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.linkpath);
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.linkpath);
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, microAppHead, isDynamic = false) {
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: placeholderComment,
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 icon ....
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.linkpath = url;
690
- microAppHead.replaceChild(scopedCSS(styleLink, app.name), info.placeholder);
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.name);
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.name);
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
- if (info.isGlobal)
722
- globalLinks.set(url, data);
740
+ info.isGlobal && globalLinks.set(url, data);
723
741
  replaceStyle.textContent = data;
724
- scopedCSS(replaceStyle, app.name);
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
- if (info.module)
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, info.code, app, info.module, false);
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
- runScript(url, info.code = info.code || code, app, info.module, false, initedHook);
886
- if (!info.module)
887
- initedHook(false);
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 module type='module' of script
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, code, app, module, isDynamic, callback) {
925
+ function runScript(url, app, info, isDynamic, callback) {
909
926
  var _a;
910
927
  try {
911
- code = bindScope(url, code, app, module);
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
- setInlinScriptContent(url, code, module, scriptElement, callback);
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
- Function(code)();
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
- if (!info.module)
942
- defer(dispatchScriptOnLoadEvent);
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
- if (!info.module)
950
- defer(dispatchScriptOnLoadEvent);
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
- if (info.isGlobal)
964
- globalScripts.set(url, code);
979
+ info.isGlobal && globalScripts.set(url, code);
965
980
  try {
966
- code = bindScope(url, code, app, info.module);
981
+ code = bindScope(url, app, code, info.module);
967
982
  if (app.inline || info.module) {
968
- setInlinScriptContent(url, code, info.module, replaceElement, dispatchScriptOnLoadEvent);
983
+ runCode2InlineScript(url, code, info.module, replaceElement, dispatchScriptOnLoadEvent);
969
984
  }
970
985
  else {
971
- Function(code)();
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
- if (!info.module)
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 js 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 setInlinScriptContent(url, code, module, scriptElement, callback) {
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, code, app, module) {
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, microAppHead);
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 (app.scopecss && !dom.hasAttribute('ignore')) {
1080
- extractLinkFromHtml(dom, parent, app, microAppHead);
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
- microAppHead.appendChild(scopedCSS(dom, app.name));
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, microAppHead);
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
- if (rawOnClick) {
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
- if (!hasRewriteDocumentOnClick) {
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
- if (isFunction(cb)) {
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
- if (isFunction(cb)) {
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
- if (isFunction(cb)) {
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
- let element = app.container;
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
- if (macroTimer)
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
- if (this.escapeKeys.has(key)) {
1911
- Reflect.deleteProperty(rawWindow, key);
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
- if (globalEnv.rawWindow._babelPolyfill)
1924
- globalEnv.rawWindow._babelPolyfill = false;
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
- else if (isShadowRoot(element)) {
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
- if (this.useSandbox) {
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
- cloneNode(this.source.html, this.container, !this.umdMode);
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
- if (!this.useSandbox && this.umdMode) {
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
- cloneNode(this.container, this.source.html, false);
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 = (isShadowRoot(this.container) ? this.container.host : this.container).getAttribute('library') || `micro-app-${this.name}`;
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.name);
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 (!app.scopecss || child.hasAttribute('ignore')) {
2363
+ else if (child.hasAttribute('ignore')) {
2343
2364
  return child;
2344
2365
  }
2345
- const { url, info, replaceComment } = extractLinkFromHtml(child, parent, app, null, true);
2366
+ const { url, info, replaceComment } = extractLinkFromHtml(child, parent, app, true);
2346
2367
  if (url && info) {
2347
2368
  const replaceStyle = pureCreateElement('style');
2348
- replaceStyle.linkpath = url;
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.code) { // inline script
2363
- const replaceElement = runScript(url, info.code, app, info.module, true);
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
- let element = app.container;
2685
- if (element) {
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
- if (!window.__MICRO_APP_UMD_MODE__)
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 attrName = this.getAttribute('name');
2736
- const attrUrl = formatURL(this.getAttribute('url'), this.appName);
2737
- if (this.legalAttribute('name', attrName) && this.legalAttribute('url', attrUrl)) {
2738
- const existApp = appInstanceMap.get(attrName);
2739
- if (attrName !== this.appName && existApp) {
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 ${attrName} already exists`, this.appName);
2758
+ return logError(`an app named ${formatAttrName} already exists`, this.appName);
2744
2759
  }
2745
2760
  }
2746
- if (attrName !== this.appName || attrUrl !== this.appUrl) {
2747
- this.handleUnmount(attrName === this.appName);
2748
- this.appName = attrName;
2749
- this.appUrl = attrUrl;
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 undefined
2753
- * if attrName and this.appName are equal, existApp has been unmounted
2754
- * if attrName and this.appName are not equal, existApp is prefetch or unmounted
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 && existApp.url === attrUrl) {
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 (attrName !== this.appName) {
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 = formatURL(newVal, this.appName);
2839
+ newVal = formatAppURL(newVal, this.appName);
2808
2840
  if (!newVal) {
2809
- return logError('Invalid attribute url', this.appName);
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(newVal, this.cacheData);
2852
+ microApp.setData(formatNewName, this.cacheData);
2817
2853
  this.cacheData = null;
2818
2854
  }
2819
- this.appName = newVal;
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
- if (this.hasConnected) {
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
- if (app.url === this.appUrl && (app.isPrefetch ||
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
- * add this logic for SSR
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
- item.url = formatURL(item.url, item.name);
2976
- if (isPlainObject(item) &&
2977
- isString(item.name) &&
2978
- item.url &&
2979
- !appInstanceMap.has(item.name)) {
2980
- validApps.push(item);
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
- if (isFunction(apps))
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
- * Do not merge with the previous line of code
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
- if (isFunction(options.fetch))
3102
- this.fetch = options.fetch;
3103
- if (isPlainObject(options.lifeCycles)) {
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
- if (options.preFetchApps) {
3111
- preFetch(options.preFetchApps);
3112
- }
3154
+ options.preFetchApps && preFetch(options.preFetchApps);
3113
3155
  // load global assets when browser is idle
3114
- if (options.globalAssets) {
3115
- getGlobalAssets(options.globalAssets);
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, setCurrentAppName, version };
3178
+ export { EventCenterForMicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, removeDomScope, version };
3125
3179
  //# sourceMappingURL=index.esm.js.map