@tramvai/module-child-app 4.26.5 → 4.26.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.
@@ -9,6 +9,7 @@ class PreloadManager {
9
9
  this.pageHasLoaded = false;
10
10
  this.currentlyPreloaded = new Map();
11
11
  this.hasPreloadBefore = new Set();
12
+ this.notPreloadedForCurrentSpaNavigation = new Set();
12
13
  this.hasInitialized = false;
13
14
  this.map = new Map();
14
15
  this.loader = loader;
@@ -18,7 +19,7 @@ class PreloadManager {
18
19
  this.resolveExternalConfig = resolveExternalConfig;
19
20
  this.diManager = diManager;
20
21
  }
21
- async preload(request, route, onlyPrefetch = false) {
22
+ async preload(request, route) {
22
23
  await this.init();
23
24
  const config = this.resolveExternalConfig(request);
24
25
  if (!config) {
@@ -41,10 +42,8 @@ class PreloadManager {
41
42
  try {
42
43
  await this.loader.load(config);
43
44
  await this.resolveComponent(config, route);
44
- if (!onlyPrefetch) {
45
- await this.run('customer', config);
46
- await this.run('clear', config);
47
- }
45
+ await this.run('customer', config);
46
+ await this.run('clear', config);
48
47
  }
49
48
  catch (error) {
50
49
  if (process.env.NODE_ENV === 'development') {
@@ -63,7 +62,22 @@ class PreloadManager {
63
62
  }
64
63
  }
65
64
  async prefetch(request, route) {
66
- return this.preload(request, route, true);
65
+ await this.init();
66
+ const config = this.resolveExternalConfig(request);
67
+ if (!config) {
68
+ return;
69
+ }
70
+ if (!this.isPreloaded(config)) {
71
+ try {
72
+ await this.loader.load(config);
73
+ await this.resolveComponent(config, route);
74
+ }
75
+ catch (error) {
76
+ if (process.env.NODE_ENV === 'development') {
77
+ console.error('Child App prefetch error', error);
78
+ }
79
+ }
80
+ }
67
81
  }
68
82
  isPreloaded(request) {
69
83
  const config = this.resolveExternalConfig(request);
@@ -102,6 +116,7 @@ class PreloadManager {
102
116
  async clearPreloaded() {
103
117
  if (this.pageHasLoaded) {
104
118
  this.currentlyPreloaded.clear();
119
+ this.notPreloadedForCurrentSpaNavigation.clear();
105
120
  this.map.clear();
106
121
  return;
107
122
  }
@@ -111,12 +126,27 @@ class PreloadManager {
111
126
  promises.push(this.run('clear', config));
112
127
  });
113
128
  this.currentlyPreloaded.clear();
129
+ this.notPreloadedForCurrentSpaNavigation.clear();
114
130
  this.map.clear();
115
131
  await Promise.all(promises);
116
132
  }
117
133
  getPreloadedList() {
118
134
  return Array.from(this.currentlyPreloaded.values());
119
135
  }
136
+ saveNotPreloadedForSpaNavigation(request) {
137
+ const config = this.resolveExternalConfig(request);
138
+ if (!config) {
139
+ return;
140
+ }
141
+ this.notPreloadedForCurrentSpaNavigation.add(config.key);
142
+ }
143
+ isNotPreloadedForSpaNavigation(request) {
144
+ const config = this.resolveExternalConfig(request);
145
+ if (!config) {
146
+ return false;
147
+ }
148
+ return this.notPreloadedForCurrentSpaNavigation.has(config.key);
149
+ }
120
150
  initServerPreloaded() {
121
151
  if (!this.hasInitialized) {
122
152
  const { preloaded } = this.store.getState(ChildAppStore);
@@ -12,6 +12,7 @@ export declare class PreloadManager implements ChildAppPreloadManager {
12
12
  private pageHasLoaded;
13
13
  private currentlyPreloaded;
14
14
  private hasPreloadBefore;
15
+ private notPreloadedForCurrentSpaNavigation;
15
16
  private hasInitialized;
16
17
  private map;
17
18
  constructor({ loader, runner, resolutionConfigManager, resolveExternalConfig, store, diManager, }: {
@@ -22,13 +23,15 @@ export declare class PreloadManager implements ChildAppPreloadManager {
22
23
  store: typeof STORE_TOKEN;
23
24
  diManager: typeof CHILD_APP_DI_MANAGER_TOKEN;
24
25
  });
25
- preload(request: ChildAppRequestConfig, route?: Route, onlyPrefetch?: boolean): Promise<void>;
26
+ preload(request: ChildAppRequestConfig, route?: Route): Promise<void>;
26
27
  prefetch(request: ChildAppRequestConfig, route?: Route): Promise<void>;
27
28
  isPreloaded(request: ChildAppRequestConfig): boolean;
28
29
  runPreloaded(): Promise<void>;
29
30
  pageRender(): void;
30
31
  clearPreloaded(): Promise<void>;
31
32
  getPreloadedList(): ChildAppFinalConfig[];
33
+ saveNotPreloadedForSpaNavigation(request: ChildAppRequestConfig): void;
34
+ isNotPreloadedForSpaNavigation(request: ChildAppRequestConfig): boolean;
32
35
  private initServerPreloaded;
33
36
  private init;
34
37
  private run;
@@ -5,6 +5,11 @@ const runCommand = async ({ status, forcePreload, runner, preloader, diManager,
5
5
  // need to wait while actual child-app is loaded in case it wasn't preloaded before
6
6
  await preloader.preload(config, pageService.getCurrentRoute());
7
7
  }
8
+ // if Child Apps was not preloaded, prevent running `spa` and `afterSpa` lines for it,
9
+ // because it trigger actions or resolveUserDeps/resolvePageDeps commands second execution on the same navigation
10
+ if (preloader.isNotPreloadedForSpaNavigation(config)) {
11
+ return;
12
+ }
8
13
  return runner.run('client', status, config);
9
14
  })).catch((error) => {
10
15
  const log = logger('child-app:run-preloaded');
@@ -26,5 +26,7 @@ export declare class PreloadManager implements ChildAppPreloadManager {
26
26
  clearPreloaded(): Promise<void>;
27
27
  getPreloadedList(): ChildAppFinalConfig[];
28
28
  private run;
29
+ saveNotPreloadedForSpaNavigation(request: ChildAppRequestConfig): void;
30
+ isNotPreloadedForSpaNavigation(request: ChildAppRequestConfig): boolean;
29
31
  }
30
32
  //# sourceMappingURL=preload.d.ts.map
@@ -48,7 +48,7 @@ class PreloadManager {
48
48
  }
49
49
  }
50
50
  async prefetch(request, route) {
51
- return this.preload(request, route);
51
+ // do nothing at server-side
52
52
  }
53
53
  isPreloaded(request) {
54
54
  const config = this.resolveFullConfig(request);
@@ -85,6 +85,13 @@ class PreloadManager {
85
85
  await this.runner.run('server', status, config);
86
86
  await this.stateManager.registerChildApp(config);
87
87
  }
88
+ saveNotPreloadedForSpaNavigation(request) {
89
+ // do nothing at server-side
90
+ }
91
+ isNotPreloadedForSpaNavigation(request) {
92
+ // do nothing at server-side
93
+ return false;
94
+ }
88
95
  }
89
96
 
90
97
  export { PreloadManager };
@@ -52,7 +52,7 @@ class PreloadManager {
52
52
  }
53
53
  }
54
54
  async prefetch(request, route) {
55
- return this.preload(request, route);
55
+ // do nothing at server-side
56
56
  }
57
57
  isPreloaded(request) {
58
58
  const config = this.resolveFullConfig(request);
@@ -89,6 +89,13 @@ class PreloadManager {
89
89
  await this.runner.run('server', status, config);
90
90
  await this.stateManager.registerChildApp(config);
91
91
  }
92
+ saveNotPreloadedForSpaNavigation(request) {
93
+ // do nothing at server-side
94
+ }
95
+ isNotPreloadedForSpaNavigation(request) {
96
+ // do nothing at server-side
97
+ return false;
98
+ }
92
99
  }
93
100
 
94
101
  exports.PreloadManager = PreloadManager;
@@ -3,7 +3,7 @@ import { resolveLazyComponent } from '@tramvai/react';
3
3
  import { CHILD_APP_PRELOAD_MANAGER_TOKEN } from '@tramvai/tokens-child-app';
4
4
  import { LINK_PREFETCH_HANDLER_TOKEN, PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
5
5
 
6
- const pagePreload = async ({ pageService, preloadManager, }, route) => {
6
+ const pagePreload = async ({ pageService, preloadManager, }, mode, isSpaNavigation = false, route) => {
7
7
  const components = await Promise.all([
8
8
  resolveLazyComponent(pageService.resolveComponentFromConfig('layout', route)),
9
9
  resolveLazyComponent(pageService.resolveComponentFromConfig('nestedLayout', route)),
@@ -11,9 +11,16 @@ const pagePreload = async ({ pageService, preloadManager, }, route) => {
11
11
  ]);
12
12
  await Promise.all(components.map(async (component) => {
13
13
  if (component === null || component === void 0 ? void 0 : component.childApps) {
14
- await Promise.all(component.childApps.map((request) => preloadManager.prefetch(request, route).catch(() => {
15
- // actual error will be logged internally
16
- })));
14
+ await Promise.all(component.childApps.map((request) => {
15
+ // for first preload on SPA-navigation, we need to prevent double action execution,
16
+ // and need to mark this Child App as not preloaded, to prevent running `spa` and `afterSpa` commands for it
17
+ if (mode === 'preload' && isSpaNavigation && !preloadManager.isPreloaded(request)) {
18
+ preloadManager.saveNotPreloadedForSpaNavigation(request);
19
+ }
20
+ return preloadManager[mode](request, route).catch(() => {
21
+ // actual error will be logged internally
22
+ });
23
+ }));
17
24
  }
18
25
  }));
19
26
  };
@@ -22,7 +29,7 @@ const pagePreloadProviders = [
22
29
  provide: LINK_PREFETCH_HANDLER_TOKEN,
23
30
  useFactory: (deps) => {
24
31
  return function prefetchChildApps(route) {
25
- return pagePreload(deps, route);
32
+ return pagePreload(deps, 'prefetch', false, route);
26
33
  };
27
34
  },
28
35
  multi: true,
@@ -36,7 +43,7 @@ const pagePreloadProviders = [
36
43
  useFactory: (deps) => {
37
44
  let isSpaNavigation = false;
38
45
  return function preloadChildApps() {
39
- const promise = pagePreload(deps);
46
+ const promise = pagePreload(deps, 'preload', isSpaNavigation);
40
47
  if (!isSpaNavigation) {
41
48
  isSpaNavigation = true;
42
49
  return promise;
@@ -3,7 +3,7 @@ import { resolveLazyComponent } from '@tramvai/react';
3
3
  import { CHILD_APP_PRELOAD_MANAGER_TOKEN } from '@tramvai/tokens-child-app';
4
4
  import { LINK_PREFETCH_HANDLER_TOKEN, PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
5
5
 
6
- const pagePreload = async ({ pageService, preloadManager, }, route) => {
6
+ const pagePreload = async ({ pageService, preloadManager, }, mode, isSpaNavigation = false, route) => {
7
7
  const components = await Promise.all([
8
8
  resolveLazyComponent(pageService.resolveComponentFromConfig('layout', route)),
9
9
  resolveLazyComponent(pageService.resolveComponentFromConfig('nestedLayout', route)),
@@ -11,9 +11,16 @@ const pagePreload = async ({ pageService, preloadManager, }, route) => {
11
11
  ]);
12
12
  await Promise.all(components.map(async (component) => {
13
13
  if (component === null || component === void 0 ? void 0 : component.childApps) {
14
- await Promise.all(component.childApps.map((request) => preloadManager.prefetch(request, route).catch(() => {
15
- // actual error will be logged internally
16
- })));
14
+ await Promise.all(component.childApps.map((request) => {
15
+ // for first preload on SPA-navigation, we need to prevent double action execution,
16
+ // and need to mark this Child App as not preloaded, to prevent running `spa` and `afterSpa` commands for it
17
+ if (mode === 'preload' && isSpaNavigation && !preloadManager.isPreloaded(request)) {
18
+ preloadManager.saveNotPreloadedForSpaNavigation(request);
19
+ }
20
+ return preloadManager[mode](request, route).catch(() => {
21
+ // actual error will be logged internally
22
+ });
23
+ }));
17
24
  }
18
25
  }));
19
26
  };
@@ -22,7 +29,7 @@ const pagePreloadProviders = [
22
29
  provide: LINK_PREFETCH_HANDLER_TOKEN,
23
30
  useFactory: (deps) => {
24
31
  return function prefetchChildApps(route) {
25
- return pagePreload(deps, route);
32
+ return pagePreload(deps, 'prefetch', false, route);
26
33
  };
27
34
  },
28
35
  multi: true,
@@ -36,7 +43,7 @@ const pagePreloadProviders = [
36
43
  useFactory: (deps) => {
37
44
  let isSpaNavigation = false;
38
45
  return function preloadChildApps() {
39
- const promise = pagePreload(deps);
46
+ const promise = pagePreload(deps, 'preload', isSpaNavigation);
40
47
  if (!isSpaNavigation) {
41
48
  isSpaNavigation = true;
42
49
  return promise;
@@ -7,7 +7,7 @@ var react = require('@tramvai/react');
7
7
  var tokensChildApp = require('@tramvai/tokens-child-app');
8
8
  var tokensRouter = require('@tramvai/tokens-router');
9
9
 
10
- const pagePreload = async ({ pageService, preloadManager, }, route) => {
10
+ const pagePreload = async ({ pageService, preloadManager, }, mode, isSpaNavigation = false, route) => {
11
11
  const components = await Promise.all([
12
12
  react.resolveLazyComponent(pageService.resolveComponentFromConfig('layout', route)),
13
13
  react.resolveLazyComponent(pageService.resolveComponentFromConfig('nestedLayout', route)),
@@ -15,9 +15,16 @@ const pagePreload = async ({ pageService, preloadManager, }, route) => {
15
15
  ]);
16
16
  await Promise.all(components.map(async (component) => {
17
17
  if (component === null || component === void 0 ? void 0 : component.childApps) {
18
- await Promise.all(component.childApps.map((request) => preloadManager.prefetch(request, route).catch(() => {
19
- // actual error will be logged internally
20
- })));
18
+ await Promise.all(component.childApps.map((request) => {
19
+ // for first preload on SPA-navigation, we need to prevent double action execution,
20
+ // and need to mark this Child App as not preloaded, to prevent running `spa` and `afterSpa` commands for it
21
+ if (mode === 'preload' && isSpaNavigation && !preloadManager.isPreloaded(request)) {
22
+ preloadManager.saveNotPreloadedForSpaNavigation(request);
23
+ }
24
+ return preloadManager[mode](request, route).catch(() => {
25
+ // actual error will be logged internally
26
+ });
27
+ }));
21
28
  }
22
29
  }));
23
30
  };
@@ -26,7 +33,7 @@ const pagePreloadProviders = [
26
33
  provide: tokensRouter.LINK_PREFETCH_HANDLER_TOKEN,
27
34
  useFactory: (deps) => {
28
35
  return function prefetchChildApps(route) {
29
- return pagePreload(deps, route);
36
+ return pagePreload(deps, 'prefetch', false, route);
30
37
  };
31
38
  },
32
39
  multi: true,
@@ -40,7 +47,7 @@ const pagePreloadProviders = [
40
47
  useFactory: (deps) => {
41
48
  let isSpaNavigation = false;
42
49
  return function preloadChildApps() {
43
- const promise = pagePreload(deps);
50
+ const promise = pagePreload(deps, 'preload', isSpaNavigation);
44
51
  if (!isSpaNavigation) {
45
52
  isSpaNavigation = true;
46
53
  return promise;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tramvai/module-child-app",
3
- "version": "4.26.5",
3
+ "version": "4.26.9",
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.3",
35
35
  "@tinkoff/module-loader-server": "0.7.2",
36
- "@tramvai/module-common": "4.26.5",
36
+ "@tramvai/module-common": "4.26.9",
37
37
  "@tinkoff/url": "0.10.1",
38
- "@tramvai/child-app-core": "4.26.5",
38
+ "@tramvai/child-app-core": "4.26.9",
39
39
  "@tramvai/safe-strings": "0.7.2",
40
- "@tramvai/tokens-child-app": "4.26.5"
40
+ "@tramvai/tokens-child-app": "4.26.9"
41
41
  },
42
42
  "devDependencies": {},
43
43
  "peerDependencies": {
44
44
  "@tinkoff/dippy": "0.10.8",
45
- "@tinkoff/router": "0.4.85",
45
+ "@tinkoff/router": "0.4.89",
46
46
  "@tinkoff/utils": "^2.1.2",
47
- "@tramvai/core": "4.26.5",
48
- "@tramvai/state": "4.26.5",
49
- "@tramvai/react": "4.26.5",
50
- "@tramvai/tokens-common": "4.26.5",
51
- "@tramvai/tokens-render": "4.26.5",
52
- "@tramvai/tokens-router": "4.26.5",
47
+ "@tramvai/core": "4.26.9",
48
+ "@tramvai/state": "4.26.9",
49
+ "@tramvai/react": "4.26.9",
50
+ "@tramvai/tokens-common": "4.26.9",
51
+ "@tramvai/tokens-render": "4.26.9",
52
+ "@tramvai/tokens-router": "4.26.9",
53
53
  "react": ">=16.14.0",
54
54
  "react-dom": ">=16.14.0",
55
55
  "object-assign": "^4.1.1",