@tramvai/module-child-app 5.50.0 → 5.53.78

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.
Files changed (91) hide show
  1. package/lib/browser/loader.browser.js +18 -5
  2. package/lib/browser/loader.d.ts +10 -2
  3. package/lib/browser/preload.browser.js +85 -29
  4. package/lib/browser/preload.d.ts +14 -2
  5. package/lib/browser/providers.browser.js +17 -2
  6. package/lib/browser/render.browser.js +15 -1
  7. package/lib/browser/render.d.ts +10 -2
  8. package/lib/browser/runCommand.browser.js +1 -1
  9. package/lib/browser/runCommand.d.ts +1 -1
  10. package/lib/browser/timing.browser.js +100 -0
  11. package/lib/browser/timing.d.ts +4 -0
  12. package/lib/browser.js +2 -1
  13. package/lib/contracts/contractManager.base.browser.js +4 -0
  14. package/lib/contracts/contractManager.base.es.js +4 -0
  15. package/lib/contracts/contractManager.base.js +4 -0
  16. package/lib/contracts/contractManager.server.es.js +1 -0
  17. package/lib/contracts/contractManager.server.js +1 -0
  18. package/lib/server/loader.d.ts +15 -6
  19. package/lib/server/loader.es.js +63 -13
  20. package/lib/server/loader.js +63 -13
  21. package/lib/server/module-federation/best-loaded-shared-modules.d.ts +15 -0
  22. package/lib/server/module-federation/best-loaded-shared-modules.es.js +26 -0
  23. package/lib/server/module-federation/best-loaded-shared-modules.js +30 -0
  24. package/lib/server/module-federation/best-shared-modules.d.ts +15 -0
  25. package/lib/server/module-federation/utils.d.ts +18 -0
  26. package/lib/server/module-federation/utils.es.js +38 -0
  27. package/lib/server/module-federation/utils.js +43 -0
  28. package/lib/server/preload.d.ts +13 -2
  29. package/lib/server/preload.es.js +58 -19
  30. package/lib/server/preload.js +58 -19
  31. package/lib/server/providers.es.js +16 -3
  32. package/lib/server/providers.js +13 -0
  33. package/lib/server/render-slots.es.js +62 -50
  34. package/lib/server/render-slots.js +62 -50
  35. package/lib/server/render.d.ts +9 -2
  36. package/lib/server/render.es.js +13 -2
  37. package/lib/server/render.js +13 -2
  38. package/lib/server/stateManager.es.js +3 -1
  39. package/lib/server/stateManager.js +3 -1
  40. package/lib/shared/command.browser.js +4 -0
  41. package/lib/shared/command.es.js +4 -0
  42. package/lib/shared/command.js +4 -0
  43. package/lib/shared/di.browser.js +5 -1
  44. package/lib/shared/di.es.js +5 -1
  45. package/lib/shared/di.js +5 -1
  46. package/lib/shared/pageService.browser.js +8 -3
  47. package/lib/shared/pageService.es.js +8 -3
  48. package/lib/shared/pageService.js +8 -3
  49. package/lib/shared/providers.browser.js +8 -3
  50. package/lib/shared/providers.es.js +8 -3
  51. package/lib/shared/providers.js +6 -1
  52. package/lib/shared/react/ChildAppErrorBoundary/ChildAppErrorBoundary.browser.js +56 -0
  53. package/lib/shared/react/ChildAppErrorBoundary/ChildAppErrorBoundary.d.ts +45 -0
  54. package/lib/shared/react/ChildAppErrorBoundary/ChildAppErrorBoundary.es.js +56 -0
  55. package/lib/shared/react/ChildAppErrorBoundary/ChildAppErrorBoundary.js +60 -0
  56. package/lib/shared/react/ChildAppErrorBoundary/FallbackError.browser.js +21 -0
  57. package/lib/shared/react/ChildAppErrorBoundary/FallbackError.d.ts +5 -0
  58. package/lib/shared/react/ChildAppErrorBoundary/FallbackError.es.js +21 -0
  59. package/lib/shared/react/ChildAppErrorBoundary/FallbackError.js +25 -0
  60. package/lib/shared/react/ChildAppFallbackWrapper.browser.js +14 -0
  61. package/lib/shared/react/ChildAppFallbackWrapper.d.ts +10 -0
  62. package/lib/shared/react/ChildAppFallbackWrapper.es.js +14 -0
  63. package/lib/shared/react/ChildAppFallbackWrapper.js +18 -0
  64. package/lib/shared/react/childAppErrorBoundaryWrapper.browser.js +22 -0
  65. package/lib/shared/react/childAppErrorBoundaryWrapper.d.ts +8 -0
  66. package/lib/shared/react/childAppErrorBoundaryWrapper.es.js +22 -0
  67. package/lib/shared/react/childAppErrorBoundaryWrapper.js +26 -0
  68. package/lib/shared/react/component.browser.js +31 -6
  69. package/lib/shared/react/component.es.js +31 -6
  70. package/lib/shared/react/component.js +29 -4
  71. package/lib/shared/resolutionConfigManager.browser.js +35 -15
  72. package/lib/shared/resolutionConfigManager.d.ts +8 -2
  73. package/lib/shared/resolutionConfigManager.es.js +35 -15
  74. package/lib/shared/resolutionConfigManager.js +35 -15
  75. package/lib/shared/singletonDi.browser.js +18 -2
  76. package/lib/shared/singletonDi.d.ts +1 -0
  77. package/lib/shared/singletonDi.es.js +18 -2
  78. package/lib/shared/singletonDi.js +18 -2
  79. package/lib/shared/store.browser.js +15 -2
  80. package/lib/shared/store.d.ts +6 -0
  81. package/lib/shared/store.es.js +15 -2
  82. package/lib/shared/store.js +15 -1
  83. package/lib/shared/webpack/moduleFederation.browser.js +42 -0
  84. package/lib/shared/webpack/moduleFederation.d.ts +27 -18
  85. package/lib/shared/webpack/moduleFederation.es.js +42 -0
  86. package/lib/shared/webpack/moduleFederation.js +42 -0
  87. package/package.json +16 -16
  88. package/lib/shared/react/childAppErrorBoundary.browser.js +0 -14
  89. package/lib/shared/react/childAppErrorBoundary.d.ts +0 -8
  90. package/lib/shared/react/childAppErrorBoundary.es.js +0 -14
  91. package/lib/shared/react/childAppErrorBoundary.js +0 -18
@@ -6,14 +6,24 @@ const getModuleFromGlobal = (entry) => {
6
6
  return window[`child-app__${entry}`];
7
7
  };
8
8
  class BrowserLoader extends Loader {
9
- constructor({ logger }) {
9
+ log;
10
+ initializedMap = new WeakMap();
11
+ map = new Map();
12
+ hookFactory;
13
+ loadModuleHook;
14
+ constructor({ logger, hookFactory, plugins, }) {
10
15
  super();
11
- this.initializedMap = new WeakMap();
12
- this.map = new Map();
16
+ this.hookFactory = hookFactory;
13
17
  this.log = logger('child-app:loader');
18
+ this.loadModuleHook = this.hookFactory.createAsync('childAppLoadModule');
19
+ this.loadModuleHook.tapPromise('childAppLoadModule', async (_, { config }) => {
20
+ return this.loadModule({ config });
21
+ });
22
+ plugins?.forEach((plugin) => {
23
+ plugin.apply({ loadModule: this.loadModuleHook });
24
+ });
14
25
  }
15
- // eslint-disable-next-line max-statements
16
- async load(config) {
26
+ async loadModule({ config }) {
17
27
  const moduleName = config.name;
18
28
  const childApp = await this.get(config);
19
29
  if (childApp) {
@@ -63,6 +73,9 @@ class BrowserLoader extends Loader {
63
73
  });
64
74
  return Promise.reject(new Error(`Error resolving child-app ${moduleName}`));
65
75
  }
76
+ async load(config) {
77
+ return this.loadModuleHook.callPromise({ config });
78
+ }
66
79
  async init(config) {
67
80
  const container = getModuleFromGlobal(config.client.entry);
68
81
  if (container) {
@@ -1,6 +1,7 @@
1
1
  import type { ChildApp } from '@tramvai/child-app-core';
2
- import type { ChildAppFinalConfig } from '@tramvai/tokens-child-app';
2
+ import type { CHILD_APP_LOADER_PLUGIN, ChildAppFinalConfig } from '@tramvai/tokens-child-app';
3
3
  import type { LOGGER_TOKEN } from '@tramvai/tokens-common';
4
+ import { AsyncTapableHookInstance, TAPABLE_HOOK_FACTORY_TOKEN } from '@tramvai/core';
4
5
  import { Loader } from '../shared/loader';
5
6
  import type { ModuleFederationContainer } from '../shared/webpack/moduleFederation';
6
7
  export declare const getModuleFromGlobal: (entry: string) => ModuleFederationContainer | undefined;
@@ -8,9 +9,16 @@ export declare class BrowserLoader extends Loader {
8
9
  private readonly log;
9
10
  private readonly initializedMap;
10
11
  private map;
11
- constructor({ logger }: {
12
+ private hookFactory;
13
+ loadModuleHook: AsyncTapableHookInstance<{
14
+ config: ChildAppFinalConfig;
15
+ }, ChildApp | undefined>;
16
+ constructor({ logger, hookFactory, plugins, }: {
12
17
  logger: typeof LOGGER_TOKEN;
18
+ hookFactory: typeof TAPABLE_HOOK_FACTORY_TOKEN;
19
+ plugins: (typeof CHILD_APP_LOADER_PLUGIN)[] | null;
13
20
  });
21
+ private loadModule;
14
22
  load(config: ChildAppFinalConfig): Promise<ChildApp | undefined>;
15
23
  init(config: ChildAppFinalConfig): Promise<void>;
16
24
  get(config: ChildAppFinalConfig): ChildApp | undefined;
@@ -1,23 +1,76 @@
1
1
  import { CHILD_APP_PAGE_SERVICE_TOKEN } from '@tramvai/tokens-child-app';
2
2
  import { optional } from '@tinkoff/dippy';
3
- import { ChildAppStore } from '../shared/store.browser.js';
3
+ import { setChildAppPreloadStatusOnClient, ChildAppStore } from '../shared/store.browser.js';
4
4
  import { getModuleFromGlobal } from './loader.browser.js';
5
5
 
6
6
  class PreloadManager {
7
- constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, diManager, }) {
8
- this.pageHasRendered = false;
9
- this.pageHasLoaded = false;
10
- this.currentlyPreloaded = new Map();
11
- this.hasPreloadBefore = new Set();
12
- this.notPreloadedForCurrentSpaNavigation = new Set();
13
- this.hasInitialized = false;
14
- this.map = new Map();
7
+ loader;
8
+ runner;
9
+ store;
10
+ resolutionConfigManager;
11
+ resolveExternalConfig;
12
+ diManager;
13
+ pageHasRendered = false;
14
+ pageHasLoaded = false;
15
+ currentlyPreloaded = new Map();
16
+ hasPreloadBefore = new Set();
17
+ notPreloadedForCurrentSpaNavigation = new Set();
18
+ hasInitialized = false;
19
+ map = new Map();
20
+ hookFactory;
21
+ hooks;
22
+ constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, diManager, hookFactory, plugins, }) {
15
23
  this.loader = loader;
16
24
  this.runner = runner;
17
25
  this.store = store;
18
26
  this.resolutionConfigManager = resolutionConfigManager;
19
27
  this.resolveExternalConfig = resolveExternalConfig;
20
28
  this.diManager = diManager;
29
+ this.hookFactory = hookFactory;
30
+ this.hooks = {
31
+ preloadChildApp: this.hookFactory.createAsync('preloadChildApp'),
32
+ prefetchChildApp: this.hookFactory.createAsync('prefetchChildApp'),
33
+ runChildAppCommandLine: this.hookFactory.createAsync('runChildAppCommandLine'),
34
+ };
35
+ this.hooks.prefetchChildApp.tapPromise('prefetchChildApp', async (_, payload) => {
36
+ await this.prefetchChildAppHook(payload);
37
+ });
38
+ this.hooks.preloadChildApp.tapPromise('preloadChildApp', async (_, payload) => {
39
+ await this.preloadChildAppHook(payload);
40
+ });
41
+ this.hooks.runChildAppCommandLine.tapPromise('runChildAppCommandLine', async (_, payload) => {
42
+ await this.runChildAppCommandLineHook(payload);
43
+ });
44
+ plugins?.forEach((plugin) => {
45
+ plugin.apply(this.hooks);
46
+ });
47
+ }
48
+ async runChildAppCommandLineHook({ status, config, }) {
49
+ const childApp = this.loader.get(config);
50
+ if (!childApp) {
51
+ return;
52
+ }
53
+ await this.runner.run('client', status, config);
54
+ }
55
+ async prefetchChildAppHook({ config, route, }) {
56
+ await this.loader.load(config);
57
+ await this.resolveComponent(config, route);
58
+ }
59
+ async preloadChildAppHook({ config, route, }) {
60
+ await this.loader.load(config);
61
+ await this.resolveComponent(config, route);
62
+ await this.run('customer', config);
63
+ // do not block Child App preloading by "clear" stage (where actions executed),
64
+ // because in will delay Child App rendering
65
+ // TODO: do we need to wait this Child App stage in "afterSpaTransition"?
66
+ // TODO: Can be a race condition between Child App render and actions?
67
+ this.run('clear', config).catch((error) => {
68
+ if (process.env.NODE_ENV === 'development') {
69
+ // eslint-disable-next-line no-console
70
+ console.error('Child App command line error', error);
71
+ }
72
+ });
73
+ this.hasPreloadBefore.add(config.key);
21
74
  }
22
75
  async preload(request, route) {
23
76
  await this.init();
@@ -40,27 +93,30 @@ class PreloadManager {
40
93
  // but in case render has happened load child-app as soon as possible
41
94
  const promise = (async () => {
42
95
  try {
43
- await this.loader.load(config);
44
- await this.resolveComponent(config, route);
45
- await this.run('customer', config);
46
- // do not block Child App preloading by "clear" stage (where actions executed),
47
- // because in will delay Child App rendering
48
- // TODO: do we need to wait this Child App stage in "afterSpaTransition"?
49
- // TODO: Can be a race condition between Child App render and actions?
50
- this.run('clear', config).catch((error) => {
51
- if (process.env.NODE_ENV === 'development') {
52
- // eslint-disable-next-line no-console
53
- console.error('Child App command line error', error);
54
- }
96
+ await this.hooks.preloadChildApp.callPromise({
97
+ config,
98
+ route,
55
99
  });
100
+ this.store.dispatch(setChildAppPreloadStatusOnClient({
101
+ [key]: {
102
+ status: 'loaded',
103
+ },
104
+ }));
56
105
  }
57
106
  catch (error) {
58
107
  if (process.env.NODE_ENV === 'development') {
59
108
  // eslint-disable-next-line no-console
60
109
  console.error('Child App loading error', error);
61
110
  }
111
+ this.hasPreloadBefore.delete(config.key);
112
+ this.map.delete(config.key);
113
+ this.store.dispatch(setChildAppPreloadStatusOnClient({
114
+ [key]: {
115
+ status: 'error',
116
+ },
117
+ }));
118
+ return Promise.reject(error);
62
119
  }
63
- this.hasPreloadBefore.add(key);
64
120
  })();
65
121
  this.map.set(key, promise);
66
122
  return promise;
@@ -79,14 +135,14 @@ class PreloadManager {
79
135
  }
80
136
  if (!this.isPreloaded(config)) {
81
137
  try {
82
- await this.loader.load(config);
83
- await this.resolveComponent(config, route);
138
+ await this.hooks.prefetchChildApp.callPromise({ config, route });
84
139
  }
85
140
  catch (error) {
86
141
  if (process.env.NODE_ENV === 'development') {
87
142
  // eslint-disable-next-line no-console
88
143
  console.error('Child App prefetch error', error);
89
144
  }
145
+ return Promise.reject(error);
90
146
  }
91
147
  }
92
148
  }
@@ -176,11 +232,11 @@ class PreloadManager {
176
232
  await this.initServerPreloaded();
177
233
  }
178
234
  async run(status, config) {
179
- const childApp = this.loader.get(config);
180
- if (!childApp) {
181
- return;
182
- }
183
- await this.runner.run('client', status, config);
235
+ await this.hooks.runChildAppCommandLine.callPromise({
236
+ config,
237
+ status,
238
+ line: 'client',
239
+ });
184
240
  }
185
241
  // preload child app page component - we need to register page actions before running all child app actions
186
242
  async resolveComponent(config, route) {
@@ -1,6 +1,7 @@
1
- import { type ChildAppCommandLineRunner, type ChildAppRequestConfig, type ChildAppLoader, type ChildAppPreloadManager, type CHILD_APP_RESOLVE_CONFIG_TOKEN, type ChildAppFinalConfig, type CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, type CHILD_APP_DI_MANAGER_TOKEN } from '@tramvai/tokens-child-app';
1
+ import { type ChildAppCommandLineRunner, type ChildAppRequestConfig, type ChildAppLoader, type ChildAppPreloadManager, type CHILD_APP_RESOLVE_CONFIG_TOKEN, type ChildAppFinalConfig, type CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, type CHILD_APP_DI_MANAGER_TOKEN, PreloadArgs, RunChildAppCommandLineArgs, CHILD_APP_PRELOAD_MANAGER_PLUGIN } from '@tramvai/tokens-child-app';
2
2
  import type { STORE_TOKEN } from '@tramvai/tokens-common';
3
3
  import type { Route } from '@tinkoff/router';
4
+ import { AsyncTapableHookInstance, TAPABLE_HOOK_FACTORY_TOKEN } from '@tramvai/core';
4
5
  export declare class PreloadManager implements ChildAppPreloadManager {
5
6
  private loader;
6
7
  private runner;
@@ -15,14 +16,25 @@ export declare class PreloadManager implements ChildAppPreloadManager {
15
16
  private notPreloadedForCurrentSpaNavigation;
16
17
  private hasInitialized;
17
18
  private map;
18
- constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, diManager, }: {
19
+ private hookFactory;
20
+ hooks: {
21
+ preloadChildApp: AsyncTapableHookInstance<PreloadArgs>;
22
+ prefetchChildApp: AsyncTapableHookInstance<PreloadArgs>;
23
+ runChildAppCommandLine: AsyncTapableHookInstance<RunChildAppCommandLineArgs>;
24
+ };
25
+ constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, diManager, hookFactory, plugins, }: {
19
26
  loader: ChildAppLoader;
20
27
  runner: ChildAppCommandLineRunner;
21
28
  resolutionConfigManager: typeof CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN;
22
29
  resolveExternalConfig: typeof CHILD_APP_RESOLVE_CONFIG_TOKEN;
23
30
  store: typeof STORE_TOKEN;
24
31
  diManager: typeof CHILD_APP_DI_MANAGER_TOKEN;
32
+ hookFactory: typeof TAPABLE_HOOK_FACTORY_TOKEN;
33
+ plugins: (typeof CHILD_APP_PRELOAD_MANAGER_PLUGIN)[] | null;
25
34
  });
35
+ private runChildAppCommandLineHook;
36
+ private prefetchChildAppHook;
37
+ private preloadChildAppHook;
26
38
  preload(request: ChildAppRequestConfig, route?: Route): Promise<void>;
27
39
  prefetch(request: ChildAppRequestConfig, route?: Route): Promise<void>;
28
40
  isPreloaded(request: ChildAppRequestConfig): boolean;
@@ -1,6 +1,6 @@
1
1
  import { Scope, DI_TOKEN, optional } from '@tinkoff/dippy';
2
- import { provide, commandLineListTokens } from '@tramvai/core';
3
- import { CHILD_APP_LOADER_TOKEN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, CHILD_APP_RESOLVE_CONFIG_TOKEN, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMON_INITIAL_STATE_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, CHILD_APP_CONTRACT_MANAGER, HOST_PROVIDED_CONTRACTS, HOST_REQUIRED_CONTRACTS } from '@tramvai/tokens-child-app';
2
+ import { provide, TAPABLE_HOOK_FACTORY_TOKEN, commandLineListTokens } from '@tramvai/core';
3
+ import { CHILD_APP_LOADER_TOKEN, CHILD_APP_LOADER_PLUGIN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_PRELOAD_MANAGER_PLUGIN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, CHILD_APP_RESOLVE_CONFIG_TOKEN, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMON_INITIAL_STATE_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, CHILD_APP_RENDER_PLUGIN, CHILD_APP_CONTRACT_MANAGER, HOST_PROVIDED_CONTRACTS, HOST_REQUIRED_CONTRACTS } from '@tramvai/tokens-child-app';
4
4
  import { LOGGER_TOKEN, STORE_TOKEN } from '@tramvai/tokens-common';
5
5
  import { ROUTER_TOKEN, PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
6
6
  import { ChildAppContractManager } from '../contracts/contractManager.browser.browser.js';
@@ -16,6 +16,11 @@ const browserProviders = [
16
16
  useClass: BrowserLoader,
17
17
  scope: Scope.SINGLETON,
18
18
  deps: {
19
+ plugins: {
20
+ optional: true,
21
+ token: CHILD_APP_LOADER_PLUGIN,
22
+ },
23
+ hookFactory: TAPABLE_HOOK_FACTORY_TOKEN,
19
24
  logger: LOGGER_TOKEN,
20
25
  },
21
26
  }),
@@ -23,6 +28,11 @@ const browserProviders = [
23
28
  provide: CHILD_APP_PRELOAD_MANAGER_TOKEN,
24
29
  useClass: PreloadManager,
25
30
  deps: {
31
+ plugins: {
32
+ optional: true,
33
+ token: CHILD_APP_PRELOAD_MANAGER_PLUGIN,
34
+ },
35
+ hookFactory: TAPABLE_HOOK_FACTORY_TOKEN,
26
36
  loader: CHILD_APP_LOADER_TOKEN,
27
37
  runner: CHILD_APP_COMMAND_LINE_RUNNER_TOKEN,
28
38
  resolutionConfigManager: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
@@ -39,6 +49,11 @@ const browserProviders = [
39
49
  provide: CHILD_APP_RENDER_MANAGER_TOKEN,
40
50
  useClass: RenderManager,
41
51
  deps: {
52
+ plugins: {
53
+ optional: true,
54
+ token: CHILD_APP_RENDER_PLUGIN,
55
+ },
56
+ hookFactory: TAPABLE_HOOK_FACTORY_TOKEN,
42
57
  logger: LOGGER_TOKEN,
43
58
  diManager: CHILD_APP_DI_MANAGER_TOKEN,
44
59
  preloadManager: CHILD_APP_PRELOAD_MANAGER_TOKEN,
@@ -1,9 +1,23 @@
1
1
  class RenderManager {
2
- constructor({ logger, preloadManager, diManager, resolveExternalConfig, }) {
2
+ preloadManager;
3
+ diManager;
4
+ resolveExternalConfig;
5
+ log;
6
+ hookFactory;
7
+ hooks;
8
+ constructor({ logger, preloadManager, diManager, resolveExternalConfig, hookFactory, plugins, }) {
9
+ this.hookFactory = hookFactory;
10
+ this.hooks = {
11
+ mounted: this.hookFactory.createSync('childAppMounted'),
12
+ mountFailed: this.hookFactory.createSync('childAppMountFailed'),
13
+ };
3
14
  this.log = logger('child-app:render');
4
15
  this.preloadManager = preloadManager;
5
16
  this.diManager = diManager;
6
17
  this.resolveExternalConfig = resolveExternalConfig;
18
+ plugins?.forEach((plugin) => {
19
+ plugin.apply(this.hooks);
20
+ });
7
21
  }
8
22
  getChildDi(request) {
9
23
  const config = this.resolveExternalConfig(request);
@@ -1,16 +1,24 @@
1
1
  import type { Container } from '@tinkoff/dippy';
2
- import type { ChildAppDiManager, ChildAppPreloadManager, ChildAppRenderManager, ChildAppRequestConfig, CHILD_APP_RESOLVE_CONFIG_TOKEN } from '@tramvai/tokens-child-app';
2
+ import { SyncTapableHookInstance, TAPABLE_HOOK_FACTORY_TOKEN } from '@tramvai/core';
3
+ import type { ChildAppDiManager, ChildAppPreloadManager, ChildAppRenderManager, ChildAppRequestConfig, CHILD_APP_RESOLVE_CONFIG_TOKEN, ChildAppConfigArgs, CHILD_APP_RENDER_PLUGIN } from '@tramvai/tokens-child-app';
3
4
  import type { LOGGER_TOKEN } from '@tramvai/tokens-common';
4
5
  export declare class RenderManager implements ChildAppRenderManager {
5
6
  private readonly preloadManager;
6
7
  private readonly diManager;
7
8
  private readonly resolveExternalConfig;
8
9
  private readonly log;
9
- constructor({ logger, preloadManager, diManager, resolveExternalConfig, }: {
10
+ private hookFactory;
11
+ hooks: {
12
+ mounted: SyncTapableHookInstance<ChildAppConfigArgs>;
13
+ mountFailed: SyncTapableHookInstance<ChildAppConfigArgs>;
14
+ };
15
+ constructor({ logger, preloadManager, diManager, resolveExternalConfig, hookFactory, plugins, }: {
10
16
  logger: typeof LOGGER_TOKEN;
11
17
  preloadManager: ChildAppPreloadManager;
12
18
  diManager: ChildAppDiManager;
13
19
  resolveExternalConfig: typeof CHILD_APP_RESOLVE_CONFIG_TOKEN;
20
+ hookFactory: typeof TAPABLE_HOOK_FACTORY_TOKEN;
21
+ plugins: (typeof CHILD_APP_RENDER_PLUGIN)[] | null;
14
22
  });
15
23
  getChildDi(request: ChildAppRequestConfig): [Container | undefined, undefined | Promise<Container | undefined>];
16
24
  clear(): void;
@@ -1,4 +1,4 @@
1
- const runCommand = async ({ status, forcePreload, runner, preloader, diManager, pageService, logger, }) => {
1
+ const runCommand = async ({ status, forcePreload, runner, preloader, pageService, logger, }) => {
2
2
  const childApps = preloader.getPreloadedList();
3
3
  const log = logger('child-app:run-preloaded');
4
4
  await Promise.all(childApps.map(async (config) => {
@@ -2,7 +2,7 @@ import type { CHILD_APP_DI_MANAGER_TOKEN } from '@tramvai/tokens-child-app';
2
2
  import { type CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, type CHILD_APP_PRELOAD_MANAGER_TOKEN } from '@tramvai/tokens-child-app';
3
3
  import type { LOGGER_TOKEN } from '@tramvai/tokens-common';
4
4
  import type { PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
5
- export declare const runCommand: ({ status, forcePreload, runner, preloader, diManager, pageService, logger, }: {
5
+ export declare const runCommand: ({ status, forcePreload, runner, preloader, pageService, logger, }: {
6
6
  status: string;
7
7
  forcePreload: boolean;
8
8
  runner: typeof CHILD_APP_COMMAND_LINE_RUNNER_TOKEN;
@@ -0,0 +1,100 @@
1
+ import { declareModule, provide, Scope } from '@tramvai/core';
2
+ import { CHILD_APP_LOADER_PLUGIN, CHILD_APP_PRELOAD_MANAGER_PLUGIN, CHILD_APP_CONFIG_RESOLUTION_PLUGIN } from '@tramvai/tokens-child-app';
3
+
4
+ const ChildAppMonitoringTimingModule = declareModule({
5
+ name: 'ChildAppMonitoringTiming',
6
+ providers: [
7
+ provide({
8
+ scope: Scope.SINGLETON,
9
+ provide: CHILD_APP_LOADER_PLUGIN,
10
+ useFactory: () => {
11
+ return {
12
+ apply(hooks) {
13
+ hooks.loadModule.wrap(async (_, payload, next) => {
14
+ const childAppName = payload.config.name;
15
+ const startKey = `child-app:load-module:${childAppName}:start`;
16
+ const measureKey = `child-app:load-module:${childAppName}`;
17
+ performance.mark(startKey);
18
+ const childApp = await next(payload);
19
+ const endKey = `child-app:load-module:${childAppName}:end`;
20
+ performance.mark(endKey);
21
+ performance.measure(measureKey, startKey, endKey);
22
+ [startKey, endKey].forEach((name) => performance.clearMarks(name));
23
+ return childApp;
24
+ });
25
+ },
26
+ };
27
+ },
28
+ }),
29
+ provide({
30
+ provide: CHILD_APP_PRELOAD_MANAGER_PLUGIN,
31
+ useFactory: () => {
32
+ return {
33
+ apply(hooks) {
34
+ hooks.prefetchChildApp.wrap(async (_, payload, next) => {
35
+ const childAppName = payload.config.name;
36
+ const startKey = `child-app:prefetch:${childAppName}:start`;
37
+ const endKey = `child-app:prefetch:${childAppName}:end`;
38
+ const measureKey = `child-app:prefetch:${childAppName}`;
39
+ performance.mark(startKey);
40
+ await next(payload);
41
+ performance.mark(endKey);
42
+ performance.measure(measureKey, startKey, endKey);
43
+ [startKey, endKey].forEach((name) => {
44
+ performance.clearMarks(name);
45
+ });
46
+ });
47
+ hooks.preloadChildApp.wrap(async (_, payload, next) => {
48
+ const childAppName = payload.config.name;
49
+ const startKey = `child-app:preload:${childAppName}:start`;
50
+ const endKey = `child-app:preload:${childAppName}:end`;
51
+ const measureKey = `child-app:preload:${childAppName}`;
52
+ performance.mark(startKey);
53
+ await next(payload);
54
+ performance.mark(endKey);
55
+ performance.measure(measureKey, startKey, endKey);
56
+ [startKey, endKey].forEach((name) => {
57
+ performance.clearMarks(name);
58
+ });
59
+ });
60
+ hooks.runChildAppCommandLine.wrap(async (_, payload, next) => {
61
+ const childAppName = payload.config.name;
62
+ const startKey = `child-app:command-line-run:${childAppName}:${payload.line}:${payload.status}:start`;
63
+ const endKey = `child-app:command-line-run:${childAppName}:${payload.line}:${payload.status}:end`;
64
+ const measureKey = `child-app:command-line-run:${childAppName}:${payload.line}:${payload.status}`;
65
+ performance.mark(startKey);
66
+ await next(payload);
67
+ performance.mark(endKey);
68
+ performance.measure(measureKey, startKey, endKey);
69
+ [startKey, endKey].forEach((name) => {
70
+ performance.clearMarks(name);
71
+ });
72
+ });
73
+ },
74
+ };
75
+ },
76
+ }),
77
+ provide({
78
+ provide: CHILD_APP_CONFIG_RESOLUTION_PLUGIN,
79
+ useFactory: () => {
80
+ return {
81
+ apply(hooks) {
82
+ hooks.fetchConfig.wrap(async (_, payload, next) => {
83
+ const startKey = `child-app:fetch-config:start`;
84
+ const measureKey = `child-app:fetch-config`;
85
+ performance.mark(startKey);
86
+ const configs = await next(payload);
87
+ const endKey = `child-app:fetch-config:end`;
88
+ performance.mark(endKey);
89
+ performance.measure(measureKey, startKey, endKey);
90
+ [startKey, endKey].forEach((name) => performance.clearMarks(name));
91
+ return configs;
92
+ });
93
+ },
94
+ };
95
+ },
96
+ }),
97
+ ],
98
+ });
99
+
100
+ export { ChildAppMonitoringTimingModule };
@@ -0,0 +1,4 @@
1
+ export declare const ChildAppMonitoringTimingModule: import("@tinkoff/dippy/lib/modules/module.h").ModuleClass & Partial<import("@tinkoff/dippy/lib/modules/module.h").ModuleSecretParameters> & {
2
+ [x: string]: (...args: any[]) => import("@tramvai/core").ModuleType;
3
+ };
4
+ //# sourceMappingURL=timing.d.ts.map
package/lib/browser.js CHANGED
@@ -2,6 +2,7 @@ import { __decorate } from 'tslib';
2
2
  import { Module } from '@tramvai/core';
3
3
  import { sharedProviders } from './shared/providers.browser.js';
4
4
  import { browserProviders } from './browser/providers.browser.js';
5
+ import { ChildAppMonitoringTimingModule } from './browser/timing.browser.js';
5
6
  export { Assert } from './export.browser.js';
6
7
  export { ChildApp } from './shared/react/component.browser.js';
7
8
  export * from '@tramvai/tokens-child-app';
@@ -10,7 +11,7 @@ let ChildAppModule = class ChildAppModule {
10
11
  };
11
12
  ChildAppModule = __decorate([
12
13
  Module({
13
- imports: [],
14
+ imports: process.env.NODE_ENV === 'development' ? [ChildAppMonitoringTimingModule] : [],
14
15
  providers: [...sharedProviders, ...browserProviders],
15
16
  })
16
17
  ], ChildAppModule);
@@ -5,6 +5,10 @@ import { CHILD_APP_INTERNAL_CONFIG_TOKEN, IS_CHILD_APP_CONTRACTS_COMPATIBLE_TOKE
5
5
 
6
6
  /* eslint-disable no-console */
7
7
  class BaseChildAppContractManager {
8
+ appDi;
9
+ hostProvidedContracts;
10
+ hostRequiredContracts;
11
+ log;
8
12
  constructor({ appDi, hostProvidedContracts, hostRequiredContracts, logger, }) {
9
13
  this.appDi = appDi;
10
14
  this.hostProvidedContracts = hostProvidedContracts ?? [];
@@ -5,6 +5,10 @@ import { CHILD_APP_INTERNAL_CONFIG_TOKEN, IS_CHILD_APP_CONTRACTS_COMPATIBLE_TOKE
5
5
 
6
6
  /* eslint-disable no-console */
7
7
  class BaseChildAppContractManager {
8
+ appDi;
9
+ hostProvidedContracts;
10
+ hostRequiredContracts;
11
+ log;
8
12
  constructor({ appDi, hostProvidedContracts, hostRequiredContracts, logger, }) {
9
13
  this.appDi = appDi;
10
14
  this.hostProvidedContracts = hostProvidedContracts ?? [];
@@ -14,6 +14,10 @@ var isNil__default = /*#__PURE__*/_interopDefaultLegacy(isNil);
14
14
 
15
15
  /* eslint-disable no-console */
16
16
  class BaseChildAppContractManager {
17
+ appDi;
18
+ hostProvidedContracts;
19
+ hostRequiredContracts;
20
+ log;
17
21
  constructor({ appDi, hostProvidedContracts, hostRequiredContracts, logger, }) {
18
22
  this.appDi = appDi;
19
23
  this.hostProvidedContracts = hostProvidedContracts ?? [];
@@ -4,6 +4,7 @@ import { CHILD_APP_INTERNAL_CONFIG_TOKEN, CHILD_APP_DI_MANAGER_TOKEN } from '@tr
4
4
  import { BaseChildAppContractManager } from './contractManager.base.es.js';
5
5
 
6
6
  class ChildAppContractManager extends BaseChildAppContractManager {
7
+ asyncLocalStorage;
7
8
  constructor({ appDi, asyncLocalStorage, hostProvidedContracts, hostRequiredContracts, logger, }) {
8
9
  super({
9
10
  appDi,
@@ -12,6 +12,7 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
12
12
  var isNil__default = /*#__PURE__*/_interopDefaultLegacy(isNil);
13
13
 
14
14
  class ChildAppContractManager extends contractManager_base.BaseChildAppContractManager {
15
+ asyncLocalStorage;
15
16
  constructor({ appDi, asyncLocalStorage, hostProvidedContracts, hostRequiredContracts, logger, }) {
16
17
  super({
17
18
  appDi,
@@ -1,21 +1,30 @@
1
- import type { ChildApp } from '@tramvai/child-app-core';
2
- import type { ChildAppFinalConfig } from '@tramvai/tokens-child-app';
3
- import type { CREATE_CACHE_TOKEN, LOGGER_TOKEN, ENV_MANAGER_TOKEN } from '@tramvai/tokens-common';
1
+ import type { CHILD_APP_LOADER_PLUGIN, ChildApp } from '@tramvai/child-app-core';
2
+ import { CHILD_APP_LOADER_CACHE_OPTIONS_TOKEN, type ChildAppFinalConfig } from '@tramvai/tokens-child-app';
3
+ import type { CREATE_CACHE_TOKEN, LOGGER_TOKEN, ENV_MANAGER_TOKEN, ASYNC_LOCAL_STORAGE_TOKEN } from '@tramvai/tokens-common';
4
+ import { AsyncTapableHookInstance, TAPABLE_HOOK_FACTORY_TOKEN } from '@tramvai/core';
4
5
  import { Loader } from '../shared/loader';
5
6
  import type { LoadableStats, ModuleFederationStats } from '../shared/webpack/moduleFederation';
6
7
  export declare class ServerLoader extends Loader {
7
8
  private readonly loader;
8
9
  private readonly initializedMap;
9
- private internalLoadCache;
10
10
  private log;
11
- constructor({ logger, createCache, envManager, }: {
11
+ private hookFactory;
12
+ loadModuleHook: AsyncTapableHookInstance<{
13
+ config: ChildAppFinalConfig;
14
+ }, ChildApp | undefined>;
15
+ constructor({ logger, createCache, envManager, cacheOptions, asyncLocalStorage, hookFactory, plugins, }: {
16
+ hookFactory: typeof TAPABLE_HOOK_FACTORY_TOKEN;
12
17
  logger: typeof LOGGER_TOKEN;
13
18
  createCache: typeof CREATE_CACHE_TOKEN;
14
19
  envManager: typeof ENV_MANAGER_TOKEN;
20
+ cacheOptions: typeof CHILD_APP_LOADER_CACHE_OPTIONS_TOKEN | null;
21
+ asyncLocalStorage: typeof ASYNC_LOCAL_STORAGE_TOKEN | null;
22
+ plugins: (typeof CHILD_APP_LOADER_PLUGIN)[] | null;
15
23
  });
24
+ private loadModule;
16
25
  load(config: ChildAppFinalConfig): Promise<ChildApp | void>;
17
26
  init(config: ChildAppFinalConfig): Promise<void>;
18
- get(config: ChildAppFinalConfig): ChildApp | void;
27
+ get(config: ChildAppFinalConfig): ChildApp | undefined;
19
28
  getStats(config: ChildAppFinalConfig): ModuleFederationStats | void;
20
29
  getLoadableStats(config: ChildAppFinalConfig): LoadableStats | void;
21
30
  waitFor(): Promise<void>;