@micro-zoe/micro-app 1.0.0-beta.7 → 1.0.0-rc.0

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
@@ -62,6 +62,7 @@ declare module '@micro-zoe/micro-app/micro_app' {
62
62
  export function renderApp(options: RenderAppOptions): Promise<boolean>;
63
63
  export class MicroApp extends EventCenterForBaseApp implements MicroAppBaseType {
64
64
  tagName: string;
65
+ hasInit: boolean;
65
66
  options: OptionsType;
66
67
  router: Router;
67
68
  preFetch: typeof preFetch;
package/lib/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = '1.0.0-beta.7';
1
+ const version = '1.0.0-rc.0';
2
2
  // do not use isUndefined
3
3
  const isBrowser = typeof window !== 'undefined';
4
4
  // do not use isUndefined
@@ -357,20 +357,23 @@ function pureCreateElement(tagName, options) {
357
357
  * @param deep deep clone or transfer dom
358
358
  */
359
359
  function cloneContainer(target, origin, deep) {
360
- target.innerHTML = '';
361
- if (deep) {
362
- // TODO: ShadowRoot兼容,ShadowRoot不能直接使用cloneNode
363
- const clonedNode = origin.cloneNode(true);
364
- const fragment = document.createDocumentFragment();
365
- Array.from(clonedNode.childNodes).forEach((node) => {
366
- fragment.appendChild(node);
367
- });
368
- target.appendChild(fragment);
369
- }
370
- else {
371
- Array.from(origin.childNodes).forEach((node) => {
372
- target.appendChild(node);
373
- });
360
+ // 在基座接受到afterhidden方法后立即执行unmount,彻底destroy应用时,因为unmount时同步执行,所以this.container为null后才执行cloneContainer
361
+ if (origin) {
362
+ target.innerHTML = '';
363
+ if (deep) {
364
+ // TODO: ShadowRoot兼容,ShadowRoot不能直接使用cloneNode
365
+ const clonedNode = origin.cloneNode(true);
366
+ const fragment = document.createDocumentFragment();
367
+ Array.from(clonedNode.childNodes).forEach((node) => {
368
+ fragment.appendChild(node);
369
+ });
370
+ target.appendChild(fragment);
371
+ }
372
+ else {
373
+ Array.from(origin.childNodes).forEach((node) => {
374
+ target.appendChild(node);
375
+ });
376
+ }
374
377
  }
375
378
  return target;
376
379
  }
@@ -606,10 +609,11 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
606
609
  * @param detail event detail
607
610
  */
608
611
  function dispatchCustomEventToMicroApp(app, eventName, detail = {}) {
612
+ var _a;
609
613
  const event = new CustomEvent(eventName, {
610
614
  detail,
611
615
  });
612
- app.sandBox.microAppWindow.dispatchEvent(event);
616
+ (_a = app.sandBox) === null || _a === void 0 ? void 0 : _a.microAppWindow.dispatchEvent(event);
613
617
  }
614
618
 
615
619
  /**
@@ -4759,6 +4763,8 @@ class WithSandBox {
4759
4763
  microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
4760
4764
  microAppWindow.__MICRO_APP_PRE_RENDER__ = false;
4761
4765
  microAppWindow.__MICRO_APP_UMD_MODE__ = false;
4766
+ microAppWindow.__MICRO_APP_SANDBOX__ = this;
4767
+ microAppWindow.__MICRO_APP_SANDBOX_TYPE__ = 'with';
4762
4768
  microAppWindow.rawWindow = globalEnv.rawWindow;
4763
4769
  microAppWindow.rawDocument = globalEnv.rawDocument;
4764
4770
  microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
@@ -5832,7 +5838,7 @@ class IframeSandbox {
5832
5838
  * 1. execute as early as possible
5833
5839
  * 2. run after patchRouter & createProxyWindow
5834
5840
  */
5835
- this.initStaticGlobalKeys(appName, url);
5841
+ this.initStaticGlobalKeys(appName, url, this.microAppWindow);
5836
5842
  resolve();
5837
5843
  });
5838
5844
  }
@@ -5939,20 +5945,21 @@ class IframeSandbox {
5939
5945
  * 1. execute as early as possible
5940
5946
  * 2. run after patchRouter & createProxyWindow
5941
5947
  */
5942
- initStaticGlobalKeys(appName, url) {
5943
- this.microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
5944
- this.microAppWindow.__MICRO_APP_NAME__ = appName;
5945
- this.microAppWindow.__MICRO_APP_URL__ = url;
5946
- this.microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
5947
- this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = '';
5948
- this.microAppWindow.__MICRO_APP_WINDOW__ = this.microAppWindow;
5949
- this.microAppWindow.__MICRO_APP_PRE_RENDER__ = false;
5950
- this.microAppWindow.__MICRO_APP_UMD_MODE__ = false;
5951
- this.microAppWindow.__MICRO_APP_SANDBOX__ = this;
5952
- this.microAppWindow.__MICRO_APP_PROXY_WINDOW__ = this.proxyWindow;
5953
- this.microAppWindow.rawWindow = globalEnv.rawWindow;
5954
- this.microAppWindow.rawDocument = globalEnv.rawDocument;
5955
- this.microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
5948
+ initStaticGlobalKeys(appName, url, microAppWindow) {
5949
+ microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
5950
+ microAppWindow.__MICRO_APP_NAME__ = appName;
5951
+ microAppWindow.__MICRO_APP_URL__ = url;
5952
+ microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
5953
+ microAppWindow.__MICRO_APP_BASE_ROUTE__ = '';
5954
+ microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
5955
+ microAppWindow.__MICRO_APP_PRE_RENDER__ = false;
5956
+ microAppWindow.__MICRO_APP_UMD_MODE__ = false;
5957
+ microAppWindow.__MICRO_APP_PROXY_WINDOW__ = this.proxyWindow;
5958
+ microAppWindow.__MICRO_APP_SANDBOX__ = this;
5959
+ microAppWindow.__MICRO_APP_SANDBOX_TYPE__ = 'iframe';
5960
+ microAppWindow.rawWindow = globalEnv.rawWindow;
5961
+ microAppWindow.rawDocument = globalEnv.rawDocument;
5962
+ microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
5956
5963
  removeDomScope,
5957
5964
  pureCreateElement,
5958
5965
  location: this.proxyLocation,
@@ -6049,7 +6056,12 @@ class IframeSandbox {
6049
6056
  (function iframeLocationReady() {
6050
6057
  setTimeout(() => {
6051
6058
  try {
6052
- if (microAppWindow.document === oldMicroDocument) {
6059
+ /**
6060
+ * NOTE:
6061
+ * 1. In browser, iframe document will be recreated after iframe initial
6062
+ * 2. In jest, iframe document is always the same
6063
+ */
6064
+ if (microAppWindow.document === oldMicroDocument && !false) {
6053
6065
  iframeLocationReady();
6054
6066
  }
6055
6067
  else {
@@ -6264,6 +6276,7 @@ class CreateApp {
6264
6276
  return this.setAppState(appStates.LOADING);
6265
6277
  }
6266
6278
  this.createSandbox();
6279
+ // place outside of nextAction, as nextAction may execute async
6267
6280
  this.setAppState(appStates.BEFORE_MOUNT);
6268
6281
  const nextAction = () => {
6269
6282
  var _a, _b, _c, _d, _e, _f, _g;
@@ -6345,6 +6358,11 @@ class CreateApp {
6345
6358
  this.handleMounted(this.umdHookMount(microApp.getData(this.name, true)));
6346
6359
  }
6347
6360
  catch (e) {
6361
+ /**
6362
+ * TODO:
6363
+ * 1. 是否应该直接抛出错误
6364
+ * 2. 是否应该触发error生命周期
6365
+ */
6348
6366
  logError('An error occurred in window.mount \n', this.name, e);
6349
6367
  }
6350
6368
  }
@@ -6533,8 +6551,12 @@ class CreateApp {
6533
6551
  var _a, _b;
6534
6552
  this.setKeepAliveState(keepAliveStates.KEEP_ALIVE_HIDDEN);
6535
6553
  /**
6536
- * event should dispatch before clone node
6537
- * dispatch afterHidden event to micro-app
6554
+ * afterhidden事件需要提前发送,原因如下:
6555
+ * 1. 此时发送this.container还指向micro-app元素,而不是临时div元素
6556
+ * 2. 沙箱执行recordAndReleaseEffect后会将appstate-change方法也清空,之后再发送子应用也接受不到了
6557
+ * 3. 对于this.loadSourceLevel !== 2的情况,unmount是同步执行的,所以也会出现2的问题
6558
+ * TODO: 有可能导致的问题
6559
+ * 1. 在基座接受到afterhidden方法后立即执行unmount,彻底destroy应用时,因为unmount时同步执行,所以this.container为null后才执行cloneContainer
6538
6560
  */
6539
6561
  dispatchCustomEventToMicroApp(this, 'appstate-change', {
6540
6562
  appState: 'afterhidden',
@@ -7376,8 +7398,6 @@ function defineElement(tagName) {
7376
7398
  */
7377
7399
  this.handleAttributeUpdate = () => {
7378
7400
  this.isWaiting = false;
7379
- if (!this.connectStateMap.get(this.connectedCount))
7380
- return;
7381
7401
  const formatAttrName = formatAppName(this.getAttribute('name'));
7382
7402
  const formatAttrUrl = formatAppURL(this.getAttribute('url'), this.appName);
7383
7403
  if (this.legalAttribute('name', formatAttrName) && this.legalAttribute('url', formatAttrUrl)) {
@@ -7487,7 +7507,9 @@ function defineElement(tagName) {
7487
7507
  attributeChangedCallback(attr, _oldVal, newVal) {
7488
7508
  if (this.legalAttribute(attr, newVal) &&
7489
7509
  this[attr === ObservedAttrName.NAME ? 'appName' : 'appUrl'] !== newVal) {
7490
- if (attr === ObservedAttrName.URL && !this.appUrl) {
7510
+ if (attr === ObservedAttrName.URL && (!this.appUrl ||
7511
+ !this.connectStateMap.get(this.connectedCount) // TODO: 这里的逻辑可否再优化一下
7512
+ )) {
7491
7513
  newVal = formatAppURL(newVal, this.appName);
7492
7514
  if (!newVal) {
7493
7515
  return logError(`Invalid attribute url ${newVal}`, this.appName);
@@ -7495,11 +7517,14 @@ function defineElement(tagName) {
7495
7517
  this.appUrl = newVal;
7496
7518
  this.handleInitialNameAndUrl();
7497
7519
  }
7498
- else if (attr === ObservedAttrName.NAME && !this.appName) {
7520
+ else if (attr === ObservedAttrName.NAME && (!this.appName ||
7521
+ !this.connectStateMap.get(this.connectedCount) // TODO: 这里的逻辑可否再优化一下
7522
+ )) {
7499
7523
  const formatNewName = formatAppName(newVal);
7500
7524
  if (!formatNewName) {
7501
7525
  return logError(`Invalid attribute name ${newVal}`, this.appName);
7502
7526
  }
7527
+ // TODO: 当micro-app还未插入文档中就修改name,逻辑可否再优化一下
7503
7528
  if (this.cacheData) {
7504
7529
  microApp.setData(formatNewName, this.cacheData);
7505
7530
  this.cacheData = null;
@@ -8223,6 +8248,7 @@ class MicroApp extends EventCenterForBaseApp {
8223
8248
  constructor() {
8224
8249
  super(...arguments);
8225
8250
  this.tagName = 'micro-app';
8251
+ this.hasInit = false;
8226
8252
  this.options = {};
8227
8253
  this.router = router;
8228
8254
  this.preFetch = preFetch;
@@ -8238,6 +8264,15 @@ class MicroApp extends EventCenterForBaseApp {
8238
8264
  if (!isBrowser || !window.customElements) {
8239
8265
  return logError('micro-app is not supported in this environment');
8240
8266
  }
8267
+ /**
8268
+ * TODO: 优化代码和逻辑
8269
+ * 1、同一个基座中initGlobalEnv不能被多次执行,否则会导致死循环
8270
+ * 2、判断逻辑是否放在initGlobalEnv中合适?--- 不合适
8271
+ */
8272
+ if (this.hasInit) {
8273
+ return logError('microApp.start executed repeatedly');
8274
+ }
8275
+ this.hasInit = true;
8241
8276
  if (options === null || options === void 0 ? void 0 : options.tagName) {
8242
8277
  if (/^micro-app(-\S+)?/.test(options.tagName)) {
8243
8278
  this.tagName = options.tagName;