@tramvai/module-child-app 4.3.0 → 4.4.1

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.
@@ -1,6 +1,7 @@
1
1
  import { CHILD_APP_PAGE_SERVICE_TOKEN } from '@tramvai/tokens-child-app';
2
2
  import { optional } from '@tinkoff/dippy';
3
3
  import { ChildAppStore } from '../shared/store.browser.js';
4
+ import { getModuleFromGlobal } from './loader.browser.js';
4
5
 
5
6
  class PreloadManager {
6
7
  constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, diManager, }) {
@@ -111,8 +112,13 @@ class PreloadManager {
111
112
  preloaded.forEach((request) => {
112
113
  const config = this.resolveExternalConfig(request);
113
114
  if (config) {
114
- this.currentlyPreloaded.set(config.key, config);
115
- this.hasPreloadBefore.add(config.key);
115
+ // double check that Child App script is already loaded.
116
+ // in streaming mode with async scripts it may not be loaded yet,
117
+ // and we will run client initialization flow for this Child App, like it was not preloaded
118
+ if (getModuleFromGlobal(config.client.entry)) {
119
+ this.currentlyPreloaded.set(config.key, config);
120
+ this.hasPreloadBefore.add(config.key);
121
+ }
116
122
  }
117
123
  });
118
124
  this.hasInitialized = true;
@@ -14,27 +14,34 @@ const deferScriptAttrs = {
14
14
  defer: 'defer',
15
15
  async: null,
16
16
  };
17
+ // for cases when Child App script was loaded or failed when script was added at server-side,
18
+ // and Child App initialization logic executed after that, we need to get script loading status
19
+ const entryAttrs = {
20
+ onload: `this.setAttribute('loaded', 'true')`,
21
+ onerror: `this.setAttribute('loaded', 'false')`,
22
+ };
17
23
  const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, preloadManager, loader, renderMode, resourcesRegistry, }) => async () => {
18
24
  const log = logger('child-app:render:slots');
19
25
  const result = [];
20
26
  // defer scripts is not suitable for React streaming, we need to ability to run them as early as possible
21
27
  // https://github.com/reactwg/react-18/discussions/114
22
28
  const scriptTypeAttr = renderMode === 'streaming' ? asyncScriptAttrs : deferScriptAttrs;
23
- const addChunk = (entry) => {
24
- if (!entry) {
29
+ const addChunk = (chunk, isEntry = false) => {
30
+ if (!chunk) {
25
31
  return;
26
32
  }
27
- const extension = extname(entry);
33
+ const extension = extname(chunk);
28
34
  switch (extension) {
29
35
  case '.js':
30
36
  result.push({
31
37
  type: ResourceType.script,
32
38
  // we need to load Child Apps scripts before main application scripts
33
39
  slot: ResourceSlot.HEAD_DYNAMIC_SCRIPTS,
34
- payload: entry,
40
+ payload: chunk,
35
41
  attrs: {
36
42
  'data-critical': 'true',
37
43
  ...scriptTypeAttr,
44
+ ...(isEntry ? entryAttrs : {}),
38
45
  },
39
46
  });
40
47
  break;
@@ -42,7 +49,7 @@ const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, pre
42
49
  result.push({
43
50
  type: ResourceType.style,
44
51
  slot: ResourceSlot.HEAD_CORE_STYLES,
45
- payload: entry,
52
+ payload: chunk,
46
53
  attrs: {
47
54
  'data-critical': 'true',
48
55
  },
@@ -86,7 +93,7 @@ const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, pre
86
93
  const stats = 'getStats' in loader ? loader.getStats(config) : undefined;
87
94
  const di = diManager.getChildDi(config);
88
95
  const loadableAssets = (_a = di === null || di === void 0 ? void 0 : di.get(CHILD_APP_INTERNAL_CHUNK_EXTRACTOR)) === null || _a === void 0 ? void 0 : _a.getMainAssets();
89
- addChunk(config.client.entry);
96
+ addChunk(config.client.entry, true);
90
97
  if (config.css) {
91
98
  addChunk(config.css.entry);
92
99
  }
@@ -22,27 +22,34 @@ const deferScriptAttrs = {
22
22
  defer: 'defer',
23
23
  async: null,
24
24
  };
25
+ // for cases when Child App script was loaded or failed when script was added at server-side,
26
+ // and Child App initialization logic executed after that, we need to get script loading status
27
+ const entryAttrs = {
28
+ onload: `this.setAttribute('loaded', 'true')`,
29
+ onerror: `this.setAttribute('loaded', 'false')`,
30
+ };
25
31
  const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, preloadManager, loader, renderMode, resourcesRegistry, }) => async () => {
26
32
  const log = logger('child-app:render:slots');
27
33
  const result = [];
28
34
  // defer scripts is not suitable for React streaming, we need to ability to run them as early as possible
29
35
  // https://github.com/reactwg/react-18/discussions/114
30
36
  const scriptTypeAttr = renderMode === 'streaming' ? asyncScriptAttrs : deferScriptAttrs;
31
- const addChunk = (entry) => {
32
- if (!entry) {
37
+ const addChunk = (chunk, isEntry = false) => {
38
+ if (!chunk) {
33
39
  return;
34
40
  }
35
- const extension = path.extname(entry);
41
+ const extension = path.extname(chunk);
36
42
  switch (extension) {
37
43
  case '.js':
38
44
  result.push({
39
45
  type: tokensRender.ResourceType.script,
40
46
  // we need to load Child Apps scripts before main application scripts
41
47
  slot: tokensRender.ResourceSlot.HEAD_DYNAMIC_SCRIPTS,
42
- payload: entry,
48
+ payload: chunk,
43
49
  attrs: {
44
50
  'data-critical': 'true',
45
51
  ...scriptTypeAttr,
52
+ ...(isEntry ? entryAttrs : {}),
46
53
  },
47
54
  });
48
55
  break;
@@ -50,7 +57,7 @@ const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, pre
50
57
  result.push({
51
58
  type: tokensRender.ResourceType.style,
52
59
  slot: tokensRender.ResourceSlot.HEAD_CORE_STYLES,
53
- payload: entry,
60
+ payload: chunk,
54
61
  attrs: {
55
62
  'data-critical': 'true',
56
63
  },
@@ -94,7 +101,7 @@ const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, pre
94
101
  const stats = 'getStats' in loader ? loader.getStats(config) : undefined;
95
102
  const di = diManager.getChildDi(config);
96
103
  const loadableAssets = (_a = di === null || di === void 0 ? void 0 : di.get(tokensChildApp.CHILD_APP_INTERNAL_CHUNK_EXTRACTOR)) === null || _a === void 0 ? void 0 : _a.getMainAssets();
97
- addChunk(config.client.entry);
104
+ addChunk(config.client.entry, true);
98
105
  if (config.css) {
99
106
  addChunk(config.css.entry);
100
107
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tramvai/module-child-app",
3
- "version": "4.3.0",
3
+ "version": "4.4.1",
4
4
  "description": "Module for child apps",
5
5
  "browser": {
6
6
  "./lib/server.js": "./lib/browser.js",
@@ -33,23 +33,23 @@
33
33
  "@tinkoff/env-validators": "0.3.1",
34
34
  "@tinkoff/module-loader-client": "0.6.1",
35
35
  "@tinkoff/module-loader-server": "0.7.1",
36
- "@tramvai/module-common": "4.3.0",
36
+ "@tramvai/module-common": "4.4.1",
37
37
  "@tinkoff/url": "0.10.1",
38
- "@tramvai/child-app-core": "4.3.0",
38
+ "@tramvai/child-app-core": "4.4.1",
39
39
  "@tramvai/safe-strings": "0.7.1",
40
- "@tramvai/tokens-child-app": "4.3.0"
40
+ "@tramvai/tokens-child-app": "4.4.1"
41
41
  },
42
42
  "devDependencies": {},
43
43
  "peerDependencies": {
44
44
  "@tinkoff/dippy": "0.10.2",
45
- "@tinkoff/router": "0.4.10",
45
+ "@tinkoff/router": "0.4.13",
46
46
  "@tinkoff/utils": "^2.1.2",
47
- "@tramvai/core": "4.3.0",
48
- "@tramvai/state": "4.3.0",
49
- "@tramvai/react": "4.3.0",
50
- "@tramvai/tokens-common": "4.3.0",
51
- "@tramvai/tokens-render": "4.3.0",
52
- "@tramvai/tokens-router": "4.3.0",
47
+ "@tramvai/core": "4.4.1",
48
+ "@tramvai/state": "4.4.1",
49
+ "@tramvai/react": "4.4.1",
50
+ "@tramvai/tokens-common": "4.4.1",
51
+ "@tramvai/tokens-render": "4.4.1",
52
+ "@tramvai/tokens-router": "4.4.1",
53
53
  "react": ">=16.14.0",
54
54
  "react-dom": ">=16.14.0",
55
55
  "object-assign": "^4.1.1",