@tramvai/module-child-app 1.70.0 → 1.71.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.
package/README.md CHANGED
@@ -108,7 +108,6 @@ Loading of child-app is happens only after preloading child-app with `CHILD_APP_
108
108
  - Calling `PreloadManager.preload(...)` loads a child-app code, executes and marks it as executable to CommandLineRunner
109
109
  - Result of `PreloadManager.preload(...)` must be awaited as it is important to synchronize child-app commands lines execution with a root-app `CommandLinerRunner`
110
110
  - Preloads after root-app `resolvePageDeps` are useless as they wont change page render and wont be used by root-app.
111
- - If child-app was not preloaded at all but still is used on render then the child-app is still preloaded automatically, but it will lead to additional React render and may significantly increase response latency.
112
111
 
113
112
  #### Client
114
113
 
@@ -6,10 +6,10 @@ export declare class PreloadManager implements ChildAppPreloadManager {
6
6
  private store;
7
7
  private resolutionConfigManager;
8
8
  private resolveExternalConfig;
9
+ private pageHasRendered;
9
10
  private pageHasLoaded;
10
11
  private map;
11
12
  private serverPreloaded;
12
- private preloadMap;
13
13
  private hasInitialized;
14
14
  constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, }: {
15
15
  loader: ChildAppLoader;
@@ -21,6 +21,7 @@ export declare class PreloadManager implements ChildAppPreloadManager {
21
21
  preload(request: ChildAppRequestConfig): Promise<void>;
22
22
  isPreloaded(request: ChildAppRequestConfig): boolean;
23
23
  runPreloaded(): Promise<void>;
24
+ pageRender(): void;
24
25
  clearPreloaded(): Promise<void>;
25
26
  getPreloadedList(): ChildAppRequestConfig[];
26
27
  private initServerPreloaded;
@@ -18,6 +18,7 @@ export declare class PreloadManager implements ChildAppPreloadManager {
18
18
  preload(request: ChildAppRequestConfig): Promise<void>;
19
19
  isPreloaded(request: ChildAppRequestConfig): boolean;
20
20
  runPreloaded(): Promise<void>;
21
+ pageRender(): void;
21
22
  clearPreloaded(): Promise<void>;
22
23
  getPreloadedList(): ChildAppRequestConfig[];
23
24
  private run;
@@ -1,11 +1,6 @@
1
- import type { CUSTOM_RENDER } from '@tramvai/tokens-render';
2
1
  import type { Container } from '@tinkoff/dippy';
3
2
  import type { ChildAppDiManager, ChildAppPreloadManager, ChildAppRenderManager, ChildAppRequestConfig, CHILD_APP_RESOLVE_CONFIG_TOKEN } from '@tramvai/tokens-child-app';
4
3
  import type { LOGGER_TOKEN } from '@tramvai/tokens-common';
5
- export declare const customRender: ({ renderManager, diManager, }: {
6
- renderManager: ChildAppRenderManager;
7
- diManager: ChildAppDiManager;
8
- }) => typeof CUSTOM_RENDER;
9
4
  export declare class RenderManager implements ChildAppRenderManager {
10
5
  private readonly preloadManager;
11
6
  private readonly diManager;
@@ -1,5 +1,10 @@
1
1
  import type { ChildAppDiManager, ChildAppStateManager, ChildAppFinalConfig } from '@tramvai/tokens-child-app';
2
- import type { LOGGER_TOKEN } from '@tramvai/tokens-common';
2
+ import type { LOGGER_TOKEN, STORE_TOKEN } from '@tramvai/tokens-common';
3
+ import type { EXTEND_RENDER } from '@tramvai/tokens-render';
4
+ export declare const executeRootStateSubscriptions: ({ store, diManager, }: {
5
+ store: typeof STORE_TOKEN;
6
+ diManager: ChildAppDiManager;
7
+ }) => typeof EXTEND_RENDER[number];
3
8
  export declare class StateManager implements ChildAppStateManager {
4
9
  private readonly log;
5
10
  private readonly diManager;
@@ -14,7 +14,7 @@ import { loadModule } from '@tinkoff/module-loader-client';
14
14
  import noop from '@tinkoff/utils/function/noop';
15
15
  import { useDi } from '@tramvai/react';
16
16
 
17
- const getChildProviders$3 = (appDi) => {
17
+ const getChildProviders$1 = (appDi) => {
18
18
  const context = appDi.get(CONTEXT_TOKEN);
19
19
  return [
20
20
  {
@@ -56,7 +56,7 @@ const getChildProviders$3 = (appDi) => {
56
56
  ];
57
57
  };
58
58
 
59
- const getChildProviders$2 = (appDi) => {
59
+ const getChildProviders = (appDi) => {
60
60
  const logger = appDi.get(LOGGER_TOKEN);
61
61
  return [
62
62
  provide({
@@ -70,7 +70,7 @@ const getChildProviders$2 = (appDi) => {
70
70
  multi: true,
71
71
  useValue: [],
72
72
  }),
73
- ...getChildProviders$3(appDi),
73
+ ...getChildProviders$1(appDi),
74
74
  ];
75
75
  };
76
76
 
@@ -137,7 +137,7 @@ class SingletonDiManager {
137
137
  },
138
138
  ], this.appDi);
139
139
  const { modules = [], providers = [], actions = [] } = children;
140
- const childProviders = getChildProviders$2(this.appDi);
140
+ const childProviders = getChildProviders(this.appDi);
141
141
  childProviders.forEach((provider) => {
142
142
  di.register(provider);
143
143
  });
@@ -171,14 +171,6 @@ class SingletonDiManager {
171
171
  }
172
172
  }
173
173
 
174
- const getChildProviders$1 = (_) => {
175
- return [];
176
- };
177
-
178
- const getChildProviders = (appDi) => {
179
- return getChildProviders$1();
180
- };
181
-
182
174
  class DiManager {
183
175
  constructor({ appDi, loader, singletonDiManager, }) {
184
176
  this.cache = new Map();
@@ -209,12 +201,7 @@ class DiManager {
209
201
  if (!singletonDi) {
210
202
  return;
211
203
  }
212
- const di = new ChildContainer(singletonDi, this.appDi);
213
- const childProviders = getChildProviders(this.appDi);
214
- childProviders.forEach((provider) => {
215
- di.register(provider);
216
- });
217
- return di;
204
+ return new ChildContainer(singletonDi, this.appDi);
218
205
  }
219
206
  }
220
207
 
@@ -301,6 +288,19 @@ const initModuleFederation = async (container, scope = 'default') => {
301
288
  },
302
289
  };
303
290
  }
291
+ if (process.env.NODE_ENV === 'development') {
292
+ // explicitly add react/jsx-runtime to support production builds of the child-app in dev mode
293
+ if (!shareScope['react/jsx-runtime']) {
294
+ shareScope['react/jsx-runtime'] = {
295
+ '*': {
296
+ get: () => () => require('react/jsx-runtime'),
297
+ from: 'tramvai-mf-fix',
298
+ eager: true,
299
+ loaded: true,
300
+ },
301
+ };
302
+ }
303
+ }
304
304
  };
305
305
  const getModuleFederation = async (container, name = 'entry') => {
306
306
  return container.get(name);
@@ -496,6 +496,18 @@ const sharedProviders = [
496
496
  preloadManager: CHILD_APP_PRELOAD_MANAGER_TOKEN,
497
497
  },
498
498
  }),
499
+ provide({
500
+ provide: commandLineListTokens$1.generatePage,
501
+ multi: true,
502
+ useFactory: ({ preloadManager }) => {
503
+ return function childAppPageRender() {
504
+ preloadManager.pageRender();
505
+ };
506
+ },
507
+ deps: {
508
+ preloadManager: CHILD_APP_PRELOAD_MANAGER_TOKEN,
509
+ },
510
+ }),
499
511
  provide({
500
512
  provide: commandLineListTokens$1.clear,
501
513
  multi: true,
@@ -570,6 +582,7 @@ class BrowserLoader extends Loader {
570
582
  this.log = logger('child-app:loader');
571
583
  }
572
584
  async load(config) {
585
+ var _a;
573
586
  const moduleName = config.name;
574
587
  const childApp = await this.get(config);
575
588
  if (childApp) {
@@ -585,7 +598,7 @@ class BrowserLoader extends Loader {
585
598
  event: 'load-fetch',
586
599
  moduleName,
587
600
  });
588
- await loadModule(config.client.entry);
601
+ await loadModule(config.client.entry, { cssUrl: (_a = config.css) === null || _a === void 0 ? void 0 : _a.entry });
589
602
  container = getModuleFromGlobal(config.client.entry);
590
603
  if (container) {
591
604
  this.log.debug({
@@ -620,10 +633,10 @@ class BrowserLoader extends Loader {
620
633
 
621
634
  class PreloadManager {
622
635
  constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, }) {
636
+ this.pageHasRendered = false;
623
637
  this.pageHasLoaded = false;
624
638
  this.map = new Map();
625
639
  this.serverPreloaded = new Map();
626
- this.preloadMap = new Map();
627
640
  this.hasInitialized = false;
628
641
  this.loader = loader;
629
642
  this.runner = runner;
@@ -635,9 +648,11 @@ class PreloadManager {
635
648
  await this.init();
636
649
  const config = this.resolveExternalConfig(request);
637
650
  const { key } = config;
638
- this.preloadMap.set(key, config);
639
- if (!this.map.has(key)) {
640
- if (this.pageHasLoaded) {
651
+ if (!this.isPreloaded(config)) {
652
+ // in case React render yet has not been executed do not load any external child-app app as
653
+ // as it will lead to markup mismatch on markup hydration
654
+ if (this.pageHasRendered) {
655
+ // but in case render has happened load child-app as soon as possible
641
656
  const promise = (async () => {
642
657
  try {
643
658
  await this.loader.load(config);
@@ -648,6 +663,7 @@ class PreloadManager {
648
663
  return config;
649
664
  })();
650
665
  this.map.set(key, promise);
666
+ await promise;
651
667
  }
652
668
  }
653
669
  }
@@ -676,31 +692,20 @@ class PreloadManager {
676
692
  }
677
693
  await Promise.all(promises);
678
694
  }
695
+ pageRender() {
696
+ this.pageHasRendered = true;
697
+ }
679
698
  async clearPreloaded() {
680
699
  this.pageHasLoaded = true;
681
700
  const promises = [];
682
- this.preloadMap.forEach((config) => {
683
- promises.push((async () => {
684
- if (this.serverPreloaded.has(config.key)) {
685
- promises.push(this.run('clear', config));
686
- }
687
- else {
688
- const promise = this.loader
689
- .load(config)
690
- .catch(noop)
691
- .then(() => config);
692
- this.map.set(config.key, promise);
693
- await promise;
694
- await this.run('customer', config);
695
- await this.run('clear', config);
696
- }
697
- })());
701
+ this.serverPreloaded.forEach((config) => {
702
+ promises.push(this.run('clear', config));
698
703
  });
699
704
  this.serverPreloaded.clear();
700
705
  await Promise.all(promises);
701
706
  }
702
707
  getPreloadedList() {
703
- return [...this.preloadMap.values()];
708
+ return [...this.serverPreloaded.values()];
704
709
  }
705
710
  initServerPreloaded() {
706
711
  if (!this.hasInitialized) {
package/lib/server.es.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import { provide, COMMAND_LINE_RUNNER_TOKEN, walkOfModules, getModuleParameters, commandLineListTokens as commandLineListTokens$1, Module } from '@tramvai/core';
3
3
  import { Container, ChildContainer, Scope, DI_TOKEN } from '@tinkoff/dippy';
4
- import { commandLineListTokens, CHILD_APP_INTERNAL_ACTION_TOKEN, CHILD_APP_INTERNAL_CONFIG_TOKEN, IS_CHILD_APP_DI_TOKEN, CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN, CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN, CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, CHILD_APP_RESOLUTION_CONFIGS_TOKEN, CHILD_APP_RESOLVE_CONFIG_TOKEN, CHILD_APP_RESOLVE_BASE_URL_TOKEN, CHILD_APP_SINGLETON_DI_MANAGER_TOKEN, CHILD_APP_LOADER_TOKEN, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, CHILD_APP_STATE_MANAGER_TOKEN, CHILD_APP_INTERNAL_RENDER_TOKEN } from '@tramvai/tokens-child-app';
4
+ import { commandLineListTokens, CHILD_APP_INTERNAL_ACTION_TOKEN, CHILD_APP_INTERNAL_CONFIG_TOKEN, IS_CHILD_APP_DI_TOKEN, CHILD_APP_INTERNAL_ROOT_DI_BORROW_TOKEN, CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, CHILD_APP_RESOLUTION_CONFIGS_TOKEN, CHILD_APP_RESOLVE_CONFIG_TOKEN, CHILD_APP_RESOLVE_BASE_URL_TOKEN, CHILD_APP_SINGLETON_DI_MANAGER_TOKEN, CHILD_APP_LOADER_TOKEN, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, CHILD_APP_STATE_MANAGER_TOKEN, CHILD_APP_INTERNAL_RENDER_TOKEN } from '@tramvai/tokens-child-app';
5
5
  export * from '@tramvai/tokens-child-app';
6
6
  import { ACTION_PAGE_RUNNER_TOKEN, LOGGER_TOKEN, DISPATCHER_TOKEN, STORE_TOKEN, CONTEXT_TOKEN, COMBINE_REDUCERS, ENV_MANAGER_TOKEN, REGISTER_CLEAR_CACHE_TOKEN, CLEAR_CACHE_TOKEN, ENV_USED_TOKEN, CREATE_CACHE_TOKEN } from '@tramvai/tokens-common';
7
- import { RENDER_SLOTS, EXTEND_RENDER, ResourceType, ResourceSlot, RESOURCES_REGISTRY, CUSTOM_RENDER } from '@tramvai/tokens-render';
7
+ import { RENDER_SLOTS, EXTEND_RENDER, ResourceType, ResourceSlot, RESOURCES_REGISTRY } from '@tramvai/tokens-render';
8
8
  import { PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
9
9
  import flatten from '@tinkoff/utils/array/flatten';
10
10
  import { createEvent, createReducer } from '@tramvai/state';
@@ -14,10 +14,9 @@ import { combineValidators, isUrl, endsWith } from '@tinkoff/env-validators';
14
14
  import { safeDehydrate } from '@tramvai/safe-strings';
15
15
  import { ServerLoader as ServerLoader$1 } from '@tinkoff/module-loader-server';
16
16
  import noop from '@tinkoff/utils/function/noop';
17
- import { renderToString } from 'react-dom/server';
18
17
  import { useDi } from '@tramvai/react';
19
18
 
20
- const getChildProviders$3 = (appDi) => {
19
+ const getChildProviders$1 = (appDi) => {
21
20
  return [
22
21
  provide({
23
22
  provide: commandLineListTokens.resolvePageDeps,
@@ -35,7 +34,7 @@ const getChildProviders$3 = (appDi) => {
35
34
  ];
36
35
  };
37
36
 
38
- const getChildProviders$2 = (appDi) => {
37
+ const getChildProviders = (appDi) => {
39
38
  const logger = appDi.get(LOGGER_TOKEN);
40
39
  return [
41
40
  provide({
@@ -49,7 +48,7 @@ const getChildProviders$2 = (appDi) => {
49
48
  multi: true,
50
49
  useValue: [],
51
50
  }),
52
- ...getChildProviders$3(),
51
+ ...getChildProviders$1(),
53
52
  ];
54
53
  };
55
54
 
@@ -116,7 +115,7 @@ class SingletonDiManager {
116
115
  },
117
116
  ], this.appDi);
118
117
  const { modules = [], providers = [], actions = [] } = children;
119
- const childProviders = getChildProviders$2(this.appDi);
118
+ const childProviders = getChildProviders(this.appDi);
120
119
  childProviders.forEach((provider) => {
121
120
  di.register(provider);
122
121
  });
@@ -150,34 +149,6 @@ class SingletonDiManager {
150
149
  }
151
150
  }
152
151
 
153
- const getChildProviders$1 = (appDi) => {
154
- const store = appDi.get(STORE_TOKEN);
155
- return [
156
- {
157
- provide: CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN,
158
- multi: true,
159
- useFactory: ({ subscriptions, }) => {
160
- return function resolveRootStateForChild() {
161
- if (!subscriptions) {
162
- return;
163
- }
164
- const state = store.getState();
165
- return Promise.all(subscriptions.map((sub) => {
166
- return sub.listener(state);
167
- }));
168
- };
169
- },
170
- deps: {
171
- subscriptions: { token: CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, optional: true },
172
- },
173
- },
174
- ];
175
- };
176
-
177
- const getChildProviders = (appDi) => {
178
- return getChildProviders$1(appDi);
179
- };
180
-
181
152
  class DiManager {
182
153
  constructor({ appDi, loader, singletonDiManager, }) {
183
154
  this.cache = new Map();
@@ -208,12 +179,7 @@ class DiManager {
208
179
  if (!singletonDi) {
209
180
  return;
210
181
  }
211
- const di = new ChildContainer(singletonDi, this.appDi);
212
- const childProviders = getChildProviders(this.appDi);
213
- childProviders.forEach((provider) => {
214
- di.register(provider);
215
- });
216
- return di;
182
+ return new ChildContainer(singletonDi, this.appDi);
217
183
  }
218
184
  }
219
185
 
@@ -300,6 +266,19 @@ const initModuleFederation = async (container, scope = 'default') => {
300
266
  },
301
267
  };
302
268
  }
269
+ if (process.env.NODE_ENV === 'development') {
270
+ // explicitly add react/jsx-runtime to support production builds of the child-app in dev mode
271
+ if (!shareScope['react/jsx-runtime']) {
272
+ shareScope['react/jsx-runtime'] = {
273
+ '*': {
274
+ get: () => () => require('react/jsx-runtime'),
275
+ from: 'tramvai-mf-fix',
276
+ eager: true,
277
+ loaded: true,
278
+ },
279
+ };
280
+ }
281
+ }
303
282
  };
304
283
  const getModuleFederation = async (container, name = 'entry') => {
305
284
  return container.get(name);
@@ -495,6 +474,18 @@ const sharedProviders = [
495
474
  preloadManager: CHILD_APP_PRELOAD_MANAGER_TOKEN,
496
475
  },
497
476
  }),
477
+ provide({
478
+ provide: commandLineListTokens$1.generatePage,
479
+ multi: true,
480
+ useFactory: ({ preloadManager }) => {
481
+ return function childAppPageRender() {
482
+ preloadManager.pageRender();
483
+ };
484
+ },
485
+ deps: {
486
+ preloadManager: CHILD_APP_PRELOAD_MANAGER_TOKEN,
487
+ },
488
+ }),
498
489
  provide({
499
490
  provide: commandLineListTokens$1.clear,
500
491
  multi: true,
@@ -628,7 +619,6 @@ class PreloadManager {
628
619
  return this.run('customer', config);
629
620
  }
630
621
  })
631
- .catch(noop)
632
622
  .then(() => config);
633
623
  this.map.set(key, promise);
634
624
  this.preloadMap.set(config.key, config);
@@ -651,6 +641,7 @@ class PreloadManager {
651
641
  });
652
642
  await Promise.all(promises);
653
643
  }
644
+ pageRender() { }
654
645
  async clearPreloaded() {
655
646
  const promises = [];
656
647
  this.map.forEach((childAppPromise) => {
@@ -673,6 +664,21 @@ class PreloadManager {
673
664
  }
674
665
  }
675
666
 
667
+ const executeRootStateSubscriptions = ({ store, diManager, }) => {
668
+ return (render) => {
669
+ const state = store.getState();
670
+ diManager.forEachChildDi((di) => {
671
+ const subscriptions = di.get({
672
+ token: CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN,
673
+ optional: true,
674
+ });
675
+ subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.forEach((sub) => {
676
+ sub.listener(state);
677
+ });
678
+ });
679
+ return render;
680
+ };
681
+ };
676
682
  class StateManager {
677
683
  constructor({ logger, diManager, }) {
678
684
  this.state = Object.create(null);
@@ -703,31 +709,6 @@ class StateManager {
703
709
  }
704
710
  }
705
711
 
706
- const LOAD_TIMEOUT = 500;
707
- const customRender = ({ renderManager, diManager, }) => {
708
- return async (content) => {
709
- const promises = [];
710
- diManager.forEachChildDi((di) => {
711
- const beforeAppRender = di.get(CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN);
712
- if (beforeAppRender) {
713
- promises.push(Promise.all(beforeAppRender.map((fn) => fn())));
714
- }
715
- });
716
- await Promise.all(promises);
717
- let render = renderToString(content);
718
- let timeouted = false;
719
- await Promise.race([
720
- new Promise((resolve) => setTimeout(resolve, LOAD_TIMEOUT)),
721
- (async () => {
722
- while ((await renderManager.flush()) && !timeouted) {
723
- render = renderToString(content);
724
- }
725
- })(),
726
- ]);
727
- timeouted = true;
728
- return render;
729
- };
730
- };
731
712
  class RenderManager {
732
713
  constructor({ logger, preloadManager, diManager, resolveFullConfig, }) {
733
714
  this.hasRenderedSet = new Set();
@@ -894,10 +875,12 @@ const serverProviders = [
894
875
  },
895
876
  }),
896
877
  provide({
897
- provide: CUSTOM_RENDER,
898
- useFactory: customRender,
878
+ provide: EXTEND_RENDER,
879
+ multi: true,
880
+ // execute subscription right before render to get the last actual data
881
+ useFactory: executeRootStateSubscriptions,
899
882
  deps: {
900
- renderManager: CHILD_APP_RENDER_MANAGER_TOKEN,
883
+ store: STORE_TOKEN,
901
884
  diManager: CHILD_APP_DI_MANAGER_TOKEN,
902
885
  },
903
886
  }),
package/lib/server.js CHANGED
@@ -17,7 +17,6 @@ var envValidators = require('@tinkoff/env-validators');
17
17
  var safeStrings = require('@tramvai/safe-strings');
18
18
  var moduleLoaderServer = require('@tinkoff/module-loader-server');
19
19
  var noop = require('@tinkoff/utils/function/noop');
20
- var server = require('react-dom/server');
21
20
  var react = require('@tramvai/react');
22
21
 
23
22
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -27,7 +26,7 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
27
26
  var applyOrReturn__default = /*#__PURE__*/_interopDefaultLegacy(applyOrReturn);
28
27
  var noop__default = /*#__PURE__*/_interopDefaultLegacy(noop);
29
28
 
30
- const getChildProviders$3 = (appDi) => {
29
+ const getChildProviders$1 = (appDi) => {
31
30
  return [
32
31
  core.provide({
33
32
  provide: tokensChildApp.commandLineListTokens.resolvePageDeps,
@@ -45,7 +44,7 @@ const getChildProviders$3 = (appDi) => {
45
44
  ];
46
45
  };
47
46
 
48
- const getChildProviders$2 = (appDi) => {
47
+ const getChildProviders = (appDi) => {
49
48
  const logger = appDi.get(tokensCommon.LOGGER_TOKEN);
50
49
  return [
51
50
  core.provide({
@@ -59,7 +58,7 @@ const getChildProviders$2 = (appDi) => {
59
58
  multi: true,
60
59
  useValue: [],
61
60
  }),
62
- ...getChildProviders$3(),
61
+ ...getChildProviders$1(),
63
62
  ];
64
63
  };
65
64
 
@@ -126,7 +125,7 @@ class SingletonDiManager {
126
125
  },
127
126
  ], this.appDi);
128
127
  const { modules = [], providers = [], actions = [] } = children;
129
- const childProviders = getChildProviders$2(this.appDi);
128
+ const childProviders = getChildProviders(this.appDi);
130
129
  childProviders.forEach((provider) => {
131
130
  di.register(provider);
132
131
  });
@@ -160,34 +159,6 @@ class SingletonDiManager {
160
159
  }
161
160
  }
162
161
 
163
- const getChildProviders$1 = (appDi) => {
164
- const store = appDi.get(tokensCommon.STORE_TOKEN);
165
- return [
166
- {
167
- provide: tokensChildApp.CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN,
168
- multi: true,
169
- useFactory: ({ subscriptions, }) => {
170
- return function resolveRootStateForChild() {
171
- if (!subscriptions) {
172
- return;
173
- }
174
- const state = store.getState();
175
- return Promise.all(subscriptions.map((sub) => {
176
- return sub.listener(state);
177
- }));
178
- };
179
- },
180
- deps: {
181
- subscriptions: { token: tokensChildApp.CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN, optional: true },
182
- },
183
- },
184
- ];
185
- };
186
-
187
- const getChildProviders = (appDi) => {
188
- return getChildProviders$1(appDi);
189
- };
190
-
191
162
  class DiManager {
192
163
  constructor({ appDi, loader, singletonDiManager, }) {
193
164
  this.cache = new Map();
@@ -218,12 +189,7 @@ class DiManager {
218
189
  if (!singletonDi) {
219
190
  return;
220
191
  }
221
- const di = new dippy.ChildContainer(singletonDi, this.appDi);
222
- const childProviders = getChildProviders(this.appDi);
223
- childProviders.forEach((provider) => {
224
- di.register(provider);
225
- });
226
- return di;
192
+ return new dippy.ChildContainer(singletonDi, this.appDi);
227
193
  }
228
194
  }
229
195
 
@@ -310,6 +276,19 @@ const initModuleFederation = async (container, scope = 'default') => {
310
276
  },
311
277
  };
312
278
  }
279
+ if (process.env.NODE_ENV === 'development') {
280
+ // explicitly add react/jsx-runtime to support production builds of the child-app in dev mode
281
+ if (!shareScope['react/jsx-runtime']) {
282
+ shareScope['react/jsx-runtime'] = {
283
+ '*': {
284
+ get: () => () => require('react/jsx-runtime'),
285
+ from: 'tramvai-mf-fix',
286
+ eager: true,
287
+ loaded: true,
288
+ },
289
+ };
290
+ }
291
+ }
313
292
  };
314
293
  const getModuleFederation = async (container, name = 'entry') => {
315
294
  return container.get(name);
@@ -505,6 +484,18 @@ const sharedProviders = [
505
484
  preloadManager: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
506
485
  },
507
486
  }),
487
+ core.provide({
488
+ provide: core.commandLineListTokens.generatePage,
489
+ multi: true,
490
+ useFactory: ({ preloadManager }) => {
491
+ return function childAppPageRender() {
492
+ preloadManager.pageRender();
493
+ };
494
+ },
495
+ deps: {
496
+ preloadManager: tokensChildApp.CHILD_APP_PRELOAD_MANAGER_TOKEN,
497
+ },
498
+ }),
508
499
  core.provide({
509
500
  provide: core.commandLineListTokens.clear,
510
501
  multi: true,
@@ -638,7 +629,6 @@ class PreloadManager {
638
629
  return this.run('customer', config);
639
630
  }
640
631
  })
641
- .catch(noop__default["default"])
642
632
  .then(() => config);
643
633
  this.map.set(key, promise);
644
634
  this.preloadMap.set(config.key, config);
@@ -661,6 +651,7 @@ class PreloadManager {
661
651
  });
662
652
  await Promise.all(promises);
663
653
  }
654
+ pageRender() { }
664
655
  async clearPreloaded() {
665
656
  const promises = [];
666
657
  this.map.forEach((childAppPromise) => {
@@ -683,6 +674,21 @@ class PreloadManager {
683
674
  }
684
675
  }
685
676
 
677
+ const executeRootStateSubscriptions = ({ store, diManager, }) => {
678
+ return (render) => {
679
+ const state = store.getState();
680
+ diManager.forEachChildDi((di) => {
681
+ const subscriptions = di.get({
682
+ token: tokensChildApp.CHILD_APP_INTERNAL_ROOT_STATE_SUBSCRIPTION_TOKEN,
683
+ optional: true,
684
+ });
685
+ subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.forEach((sub) => {
686
+ sub.listener(state);
687
+ });
688
+ });
689
+ return render;
690
+ };
691
+ };
686
692
  class StateManager {
687
693
  constructor({ logger, diManager, }) {
688
694
  this.state = Object.create(null);
@@ -713,31 +719,6 @@ class StateManager {
713
719
  }
714
720
  }
715
721
 
716
- const LOAD_TIMEOUT = 500;
717
- const customRender = ({ renderManager, diManager, }) => {
718
- return async (content) => {
719
- const promises = [];
720
- diManager.forEachChildDi((di) => {
721
- const beforeAppRender = di.get(tokensChildApp.CHILD_APP_INTERNAL_BEFORE_RENDER_TOKEN);
722
- if (beforeAppRender) {
723
- promises.push(Promise.all(beforeAppRender.map((fn) => fn())));
724
- }
725
- });
726
- await Promise.all(promises);
727
- let render = server.renderToString(content);
728
- let timeouted = false;
729
- await Promise.race([
730
- new Promise((resolve) => setTimeout(resolve, LOAD_TIMEOUT)),
731
- (async () => {
732
- while ((await renderManager.flush()) && !timeouted) {
733
- render = server.renderToString(content);
734
- }
735
- })(),
736
- ]);
737
- timeouted = true;
738
- return render;
739
- };
740
- };
741
722
  class RenderManager {
742
723
  constructor({ logger, preloadManager, diManager, resolveFullConfig, }) {
743
724
  this.hasRenderedSet = new Set();
@@ -904,10 +885,12 @@ const serverProviders = [
904
885
  },
905
886
  }),
906
887
  core.provide({
907
- provide: tokensRender.CUSTOM_RENDER,
908
- useFactory: customRender,
888
+ provide: tokensRender.EXTEND_RENDER,
889
+ multi: true,
890
+ // execute subscription right before render to get the last actual data
891
+ useFactory: executeRootStateSubscriptions,
909
892
  deps: {
910
- renderManager: tokensChildApp.CHILD_APP_RENDER_MANAGER_TOKEN,
893
+ store: tokensCommon.STORE_TOKEN,
911
894
  diManager: tokensChildApp.CHILD_APP_DI_MANAGER_TOKEN,
912
895
  },
913
896
  }),
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@tramvai/module-child-app",
3
- "version": "1.70.0",
3
+ "version": "1.71.1",
4
4
  "description": "Module for child apps",
5
5
  "browser": {
6
6
  "./lib/server.js": "./lib/browser.js",
7
7
  "./lib/server/child/singletonProviders.js": "./lib/browser/child/singletonProviders.js",
8
- "./lib/server/child/providers.js": "./lib/browser/child/providers.js",
9
8
  "./lib/server.es.js": "./lib/server.browser.js"
10
9
  },
11
10
  "main": "lib/server.js",
@@ -31,20 +30,20 @@
31
30
  "@tinkoff/env-validators": "0.0.3",
32
31
  "@tinkoff/module-loader-client": "0.3.25",
33
32
  "@tinkoff/module-loader-server": "0.4.41",
34
- "@tramvai/child-app-core": "1.70.0",
33
+ "@tramvai/child-app-core": "1.71.1",
35
34
  "@tramvai/safe-strings": "0.4.3",
36
- "@tramvai/tokens-child-app": "1.70.0"
35
+ "@tramvai/tokens-child-app": "1.71.1"
37
36
  },
38
37
  "devDependencies": {},
39
38
  "peerDependencies": {
40
39
  "@tinkoff/dippy": "0.7.38",
41
40
  "@tinkoff/utils": "^2.1.2",
42
- "@tramvai/core": "1.70.0",
43
- "@tramvai/state": "1.70.0",
44
- "@tramvai/react": "1.70.0",
45
- "@tramvai/tokens-common": "1.70.0",
46
- "@tramvai/tokens-render": "1.70.0",
47
- "@tramvai/tokens-router": "1.70.0",
41
+ "@tramvai/core": "1.71.1",
42
+ "@tramvai/state": "1.71.1",
43
+ "@tramvai/react": "1.71.1",
44
+ "@tramvai/tokens-common": "1.71.1",
45
+ "@tramvai/tokens-render": "1.71.1",
46
+ "@tramvai/tokens-router": "1.71.1",
48
47
  "react": ">=16.8.0",
49
48
  "react-dom": ">=16.8.0",
50
49
  "object-assign": "^4.1.1",
@@ -1,3 +0,0 @@
1
- import type { Container } from '@tinkoff/dippy';
2
- import type { Provider } from '@tramvai/core';
3
- export declare const getChildProviders: (_: Container) => Provider[];
@@ -1,3 +0,0 @@
1
- import type { Container } from '@tinkoff/dippy';
2
- import type { Provider } from '@tramvai/core';
3
- export declare const getChildProviders: (appDi: Container) => Provider[];
@@ -1,3 +0,0 @@
1
- import type { Container } from '@tinkoff/dippy';
2
- import type { Provider } from '@tramvai/core';
3
- export declare const getChildProviders: (appDi: Container) => Provider[];