@micro-zoe/micro-app 1.0.0-alpha.8 → 1.0.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -84,16 +84,21 @@ declare module '@micro-zoe/micro-app/prefetch' {
84
84
  * {
85
85
  * name: string,
86
86
  * url: string,
87
- * disableScopecss?: boolean,
88
- * disableSandbox?: boolean,
89
- * disableMemoryRouter?: boolean,
87
+ * esmodule: boolean,
88
+ * inline: boolean,
89
+ * 'disable-scopecss': boolean,
90
+ * 'disable-sandbox': boolean,
91
+ * level: number,
92
+ * 'default-page': string,
93
+ * 'disable-patch-request': boolean,
90
94
  * },
91
95
  * ...
92
96
  * ])
93
97
  * Note:
94
- * 1: preFetch is asynchronous and is performed only when the browser is idle
95
- * 2: disableScopecss, disableSandbox, disableMemoryRouter must be same with micro-app element, if conflict, the one who executes first shall prevail
96
- * @param apps micro apps
98
+ * 1: preFetch is async and is performed only when the browser is idle
99
+ * 2: options of prefetch preferably match the config of the micro-app element, although this is not required
100
+ * @param apps micro app options
101
+ * @param delay delay time
97
102
  */
98
103
  export default function preFetch(apps: prefetchParamList, delay?: number): void;
99
104
  /**
package/lib/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = '1.0.0-alpha.8';
1
+ const version = '1.0.0-alpha.9';
2
2
  // do not use isUndefined
3
3
  const isBrowser = typeof window !== 'undefined';
4
4
  // do not use isUndefined
@@ -344,7 +344,8 @@ function isInvalidQuerySelectorKey(key) {
344
344
  function isUniqueElement(key) {
345
345
  return (/^body$/i.test(key) ||
346
346
  /^head$/i.test(key) ||
347
- /^html$/i.test(key));
347
+ /^html$/i.test(key) ||
348
+ /^title$/i.test(key));
348
349
  }
349
350
  /**
350
351
  * get micro-app element
@@ -578,7 +579,7 @@ const PREFETCH_LEVEL = [1, 2, 3];
578
579
  * NOTE:
579
580
  * 1. Do not add fetch, XMLHttpRequest, EventSource
580
581
  */
581
- const globalKeyToBeCached = 'window,self,globalThis,Array,Object,String,Boolean,Math,Number,Symbol,Date,Function,Proxy,WeakMap,WeakSet,Set,Map,Reflect,Element,Node,Document,RegExp,Error,TypeError,JSON,isNaN,parseFloat,parseInt,performance,console,decodeURI,encodeURI,decodeURIComponent,encodeURIComponent,navigator,undefined,location,history';
582
+ const globalKeyToBeCached = 'window,self,globalThis,document,Document,Array,Object,String,Boolean,Math,Number,Symbol,Date,Function,Proxy,WeakMap,WeakSet,Set,Map,Reflect,Element,Node,RegExp,Error,TypeError,JSON,isNaN,parseFloat,parseInt,performance,console,decodeURI,encodeURI,decodeURIComponent,encodeURIComponent,navigator,undefined,location,history';
582
583
 
583
584
  /**
584
585
  * fetch source of html, js, css
@@ -2576,12 +2577,20 @@ function flatChildren(parent, app, microAppHead, fiberStyleTasks) {
2576
2577
  else if (dom instanceof HTMLScriptElement) {
2577
2578
  extractScriptElement(dom, parent, app);
2578
2579
  }
2579
- else if (dom instanceof HTMLMetaElement || dom instanceof HTMLTitleElement) {
2580
- parent.removeChild(dom);
2581
- }
2582
2580
  else if (dom instanceof HTMLImageElement && dom.hasAttribute('src')) {
2583
2581
  dom.setAttribute('src', CompletionPath(dom.getAttribute('src'), app.url));
2584
2582
  }
2583
+ /**
2584
+ * Don't remove meta and title, they have some special scenes
2585
+ * e.g.
2586
+ * document.querySelector('meta[name="viewport"]') // for flexible
2587
+ * document.querySelector('meta[name="baseurl"]').baseurl // for api request
2588
+ *
2589
+ * Title point to main app title, child app title used to be compatible with some special scenes
2590
+ */
2591
+ // else if (dom instanceof HTMLMetaElement || dom instanceof HTMLTitleElement) {
2592
+ // parent.removeChild(dom)
2593
+ // }
2585
2594
  }
2586
2595
  }
2587
2596
  /**
@@ -4335,8 +4344,6 @@ function createMicroFetch(url, target) {
4335
4344
  * When fetch rewrite by baseApp, domScope still active when exec rawWindow.fetch
4336
4345
  * If baseApp operate dom in fetch, it will cause error
4337
4346
  * The same for XMLHttpRequest, EventSource
4338
- * e.g.
4339
- * baseApp: <script crossorigin src="https://sgm-static.jd.com/sgm-2.8.0.js" name="SGMH5" sid="6f88a6e4ba4b4ae5acef2ec22c075085" appKey="jdb-adminb2b-pc"></script>
4340
4347
  */
4341
4348
  removeDomScope();
4342
4349
  return rawFetch.call(globalEnv.rawWindow, input, init, ...rests);
@@ -4471,8 +4478,9 @@ class SandBox {
4471
4478
  this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
4472
4479
  }
4473
4480
  /**
4474
- * 1. prevent the key deleted during sandBox.stop after rewrite
4475
- * 2. umd mode will not delete any keys during sandBox.stop
4481
+ * 1. Prevent the key deleted during sandBox.stop after rewrite
4482
+ * 2. Umd mode will not delete any keys during sandBox.stop
4483
+ * 3. It must not be umd mode when call sandbox.start at the first time
4476
4484
  */
4477
4485
  if (!umdMode) {
4478
4486
  this.initGlobalKeysWhenStart(this.microAppWindow, this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.__MICRO_APP_URL__, disablePatchRequest);
@@ -4725,7 +4733,6 @@ class SandBox {
4725
4733
  configurable: false,
4726
4734
  enumerable: true,
4727
4735
  get() {
4728
- throttleDeferForSetAppName(appName);
4729
4736
  // return globalEnv.rawDocument
4730
4737
  return proxyDocument;
4731
4738
  },
@@ -4734,7 +4741,6 @@ class SandBox {
4734
4741
  configurable: false,
4735
4742
  enumerable: false,
4736
4743
  get() {
4737
- throttleDeferForSetAppName(appName);
4738
4744
  // return globalEnv.rawRootDocument
4739
4745
  return MicroDocument;
4740
4746
  },
@@ -4780,6 +4786,7 @@ class SandBox {
4780
4786
  this.setHijackProperty(microAppWindow, appName);
4781
4787
  if (!disablePatchRequest)
4782
4788
  this.patchRequestApi(microAppWindow, appName, url);
4789
+ this.setScopeProperties(microAppWindow);
4783
4790
  }
4784
4791
  // set hijack Properties to microAppWindow
4785
4792
  setHijackProperty(microAppWindow, appName) {
@@ -4847,6 +4854,18 @@ class SandBox {
4847
4854
  },
4848
4855
  });
4849
4856
  }
4857
+ /**
4858
+ * Init scope keys to microAppWindow, prevent fall to rawWindow from with(microAppWindow)
4859
+ * like: if (!xxx) {}
4860
+ * NOTE:
4861
+ * 1. Symbol.unscopables cannot affect undefined keys
4862
+ * 2. Doesn't use for window.xxx because it fall to proxyWindow
4863
+ */
4864
+ setScopeProperties(microAppWindow) {
4865
+ this.scopeProperties.forEach((key) => {
4866
+ Reflect.set(microAppWindow, key, microAppWindow[key]);
4867
+ });
4868
+ }
4850
4869
  // set location & history for memory router
4851
4870
  setMicroAppRouter(microAppWindow, appName, url) {
4852
4871
  const { microLocation, microHistory } = createMicroRouter(appName, url);
@@ -4907,11 +4926,11 @@ class SandBox {
4907
4926
  return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
4908
4927
  },
4909
4928
  set: (target, key, value) => {
4910
- // Fix TypeError: Illegal invocation when set document.title
4911
- Reflect.set(target, key, value);
4912
4929
  /**
4913
- * If the set method returns false, and the assignment happened in strict-mode code, a TypeError will be thrown.
4930
+ * 1. Fix TypeError: Illegal invocation when set document.title
4931
+ * 2. If the set method returns false, and the assignment happened in strict-mode code, a TypeError will be thrown.
4914
4932
  */
4933
+ Reflect.set(target, key, value);
4915
4934
  return true;
4916
4935
  }
4917
4936
  });
@@ -5403,8 +5422,10 @@ class CreateApp {
5403
5422
  });
5404
5423
  // dispatch afterHidden event to base app
5405
5424
  dispatchLifecyclesEvent(oldContainer, this.name, lifeCycles.AFTERHIDDEN);
5406
- // called after lifeCyclesEvent
5407
- (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.removeRouteInfoForKeepAliveApp();
5425
+ if (this.useMemoryRouter) {
5426
+ // called after lifeCyclesEvent
5427
+ (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.removeRouteInfoForKeepAliveApp();
5428
+ }
5408
5429
  this.recordAndReleaseEffect();
5409
5430
  callback && callback();
5410
5431
  }
@@ -5421,8 +5442,10 @@ class CreateApp {
5421
5442
  cloneContainer(this.container, container, false);
5422
5443
  this.container = container;
5423
5444
  this.keepAliveState = keepAliveStates.KEEP_ALIVE_SHOW;
5424
- // called before lifeCyclesEvent
5425
- (_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.setRouteInfoForKeepAliveApp();
5445
+ if (this.useMemoryRouter) {
5446
+ // called before lifeCyclesEvent
5447
+ (_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.setRouteInfoForKeepAliveApp();
5448
+ }
5426
5449
  // dispatch afterShow event to micro-app
5427
5450
  dispatchCustomEventToMicroApp('appstate-change', this.name, {
5428
5451
  appState: 'aftershow',
@@ -5561,10 +5584,16 @@ function defineElement(tagName) {
5561
5584
  * In some special scenes, such as vue's keep-alive, the micro-app will be inserted and deleted twice in an instant
5562
5585
  * So we execute the mount method async and record connectState to prevent repeated rendering
5563
5586
  */
5587
+ const effectiveApp = this.appName && this.appUrl;
5564
5588
  defer(() => {
5565
5589
  if (this.connectStateMap.get(cacheCount)) {
5566
5590
  dispatchLifecyclesEvent(this, this.appName, lifeCycles.CREATED);
5567
- this.handleConnected();
5591
+ /**
5592
+ * If insert micro-app element without name or url, and set them in next action like angular,
5593
+ * handleConnected will be executed twice, causing the app render repeatedly,
5594
+ * so we only execute handleConnected() if url and name exist when connectedCallback
5595
+ */
5596
+ effectiveApp && this.handleConnected();
5568
5597
  }
5569
5598
  });
5570
5599
  }
@@ -5943,23 +5972,32 @@ function defineElement(tagName) {
5943
5972
  * {
5944
5973
  * name: string,
5945
5974
  * url: string,
5946
- * disableScopecss?: boolean,
5947
- * disableSandbox?: boolean,
5948
- * disableMemoryRouter?: boolean,
5975
+ * esmodule: boolean,
5976
+ * inline: boolean,
5977
+ * 'disable-scopecss': boolean,
5978
+ * 'disable-sandbox': boolean,
5979
+ * level: number,
5980
+ * 'default-page': string,
5981
+ * 'disable-patch-request': boolean,
5949
5982
  * },
5950
5983
  * ...
5951
5984
  * ])
5952
5985
  * Note:
5953
- * 1: preFetch is asynchronous and is performed only when the browser is idle
5954
- * 2: disableScopecss, disableSandbox, disableMemoryRouter must be same with micro-app element, if conflict, the one who executes first shall prevail
5955
- * @param apps micro apps
5986
+ * 1: preFetch is async and is performed only when the browser is idle
5987
+ * 2: options of prefetch preferably match the config of the micro-app element, although this is not required
5988
+ * @param apps micro app options
5989
+ * @param delay delay time
5956
5990
  */
5957
5991
  function preFetch(apps, delay) {
5958
5992
  if (!isBrowser) {
5959
5993
  return logError('preFetch is only supported in browser environment');
5960
5994
  }
5961
5995
  requestIdleCallback(() => {
5962
- const delayTime = delay !== null && delay !== void 0 ? delay : microApp.options.prefetchDelay;
5996
+ const delayTime = isNumber(delay) ? delay : microApp.options.prefetchDelay;
5997
+ /**
5998
+ * TODO: remove setTimeout
5999
+ * Is there a better way?
6000
+ */
5963
6001
  setTimeout(() => {
5964
6002
  // releasePrefetchEffect()
5965
6003
  preFetchInSerial(apps);