@tramvai/module-child-app 5.49.1 → 6.59.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/browser/loader.browser.js +18 -5
- package/lib/browser/loader.d.ts +10 -2
- package/lib/browser/preload.browser.js +85 -29
- package/lib/browser/preload.d.ts +14 -2
- package/lib/browser/providers.browser.js +17 -2
- package/lib/browser/render.browser.js +15 -1
- package/lib/browser/render.d.ts +10 -2
- package/lib/browser/runCommand.browser.js +1 -1
- package/lib/browser/runCommand.d.ts +1 -1
- package/lib/browser/timing.browser.js +100 -0
- package/lib/browser/timing.d.ts +4 -0
- package/lib/browser.js +2 -1
- package/lib/contracts/contractManager.base.browser.js +4 -0
- package/lib/contracts/contractManager.base.es.js +4 -0
- package/lib/contracts/contractManager.base.js +4 -0
- package/lib/contracts/contractManager.server.es.js +1 -0
- package/lib/contracts/contractManager.server.js +1 -0
- package/lib/server/cache/cache.d.ts +39 -0
- package/lib/server/cache/cache.es.js +76 -0
- package/lib/server/cache/cache.js +80 -0
- package/lib/server/cache/cacheCleanup.d.ts +4 -0
- package/lib/server/cache/cacheCleanup.es.js +16 -0
- package/lib/server/cache/cacheCleanup.js +21 -0
- package/lib/server/loader.d.ts +14 -7
- package/lib/server/loader.es.js +34 -19
- package/lib/server/loader.js +34 -19
- package/lib/server/module-federation/best-loaded-shared-modules.d.ts +15 -0
- package/lib/server/module-federation/best-loaded-shared-modules.es.js +26 -0
- package/lib/server/module-federation/best-loaded-shared-modules.js +30 -0
- package/lib/server/module-federation/best-shared-modules.d.ts +15 -0
- package/lib/server/module-federation/utils.d.ts +18 -0
- package/lib/server/module-federation/utils.es.js +38 -0
- package/lib/server/module-federation/utils.js +43 -0
- package/lib/server/preload.d.ts +13 -2
- package/lib/server/preload.es.js +58 -19
- package/lib/server/preload.js +58 -19
- package/lib/server/providers.es.js +17 -4
- package/lib/server/providers.js +14 -1
- package/lib/server/render-slots.es.js +62 -50
- package/lib/server/render-slots.js +62 -50
- package/lib/server/render.d.ts +9 -2
- package/lib/server/render.es.js +13 -2
- package/lib/server/render.js +13 -2
- package/lib/server/stateManager.es.js +3 -1
- package/lib/server/stateManager.js +3 -1
- package/lib/shared/command.browser.js +4 -0
- package/lib/shared/command.es.js +4 -0
- package/lib/shared/command.js +4 -0
- package/lib/shared/di.browser.js +5 -1
- package/lib/shared/di.es.js +5 -1
- package/lib/shared/di.js +5 -1
- package/lib/shared/pageService.browser.js +8 -3
- package/lib/shared/pageService.es.js +8 -3
- package/lib/shared/pageService.js +8 -3
- package/lib/shared/providers.browser.js +8 -3
- package/lib/shared/providers.es.js +8 -3
- package/lib/shared/providers.js +6 -1
- package/lib/shared/react/ChildAppErrorBoundary/ChildAppErrorBoundary.browser.js +56 -0
- package/lib/shared/react/ChildAppErrorBoundary/ChildAppErrorBoundary.d.ts +45 -0
- package/lib/shared/react/ChildAppErrorBoundary/ChildAppErrorBoundary.es.js +56 -0
- package/lib/shared/react/ChildAppErrorBoundary/ChildAppErrorBoundary.js +60 -0
- package/lib/shared/react/ChildAppErrorBoundary/FallbackError.browser.js +21 -0
- package/lib/shared/react/ChildAppErrorBoundary/FallbackError.d.ts +5 -0
- package/lib/shared/react/ChildAppErrorBoundary/FallbackError.es.js +21 -0
- package/lib/shared/react/ChildAppErrorBoundary/FallbackError.js +25 -0
- package/lib/shared/react/ChildAppFallbackWrapper.browser.js +14 -0
- package/lib/shared/react/ChildAppFallbackWrapper.d.ts +10 -0
- package/lib/shared/react/ChildAppFallbackWrapper.es.js +14 -0
- package/lib/shared/react/ChildAppFallbackWrapper.js +18 -0
- package/lib/shared/react/childAppErrorBoundaryWrapper.browser.js +22 -0
- package/lib/shared/react/childAppErrorBoundaryWrapper.d.ts +8 -0
- package/lib/shared/react/childAppErrorBoundaryWrapper.es.js +22 -0
- package/lib/shared/react/childAppErrorBoundaryWrapper.js +26 -0
- package/lib/shared/react/component.browser.js +31 -6
- package/lib/shared/react/component.es.js +31 -6
- package/lib/shared/react/component.js +29 -4
- package/lib/shared/resolutionConfigManager.browser.js +35 -15
- package/lib/shared/resolutionConfigManager.d.ts +8 -2
- package/lib/shared/resolutionConfigManager.es.js +35 -15
- package/lib/shared/resolutionConfigManager.js +35 -15
- package/lib/shared/singletonDi.browser.js +18 -2
- package/lib/shared/singletonDi.d.ts +1 -0
- package/lib/shared/singletonDi.es.js +18 -2
- package/lib/shared/singletonDi.js +18 -2
- package/lib/shared/store.browser.js +15 -2
- package/lib/shared/store.d.ts +6 -0
- package/lib/shared/store.es.js +15 -2
- package/lib/shared/store.js +15 -1
- package/lib/shared/webpack/moduleFederation.browser.js +42 -0
- package/lib/shared/webpack/moduleFederation.d.ts +27 -18
- package/lib/shared/webpack/moduleFederation.es.js +42 -0
- package/lib/shared/webpack/moduleFederation.js +42 -0
- package/package.json +22 -23
- package/lib/shared/react/childAppErrorBoundary.browser.js +0 -14
- package/lib/shared/react/childAppErrorBoundary.d.ts +0 -8
- package/lib/shared/react/childAppErrorBoundary.es.js +0 -14
- package/lib/shared/react/childAppErrorBoundary.js +0 -18
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var path = require('path');
|
|
6
|
-
var semver = require('semver');
|
|
7
6
|
var flatten = require('@tinkoff/utils/array/flatten');
|
|
8
7
|
var url = require('@tinkoff/url');
|
|
9
8
|
var tokensChildApp = require('@tramvai/tokens-child-app');
|
|
10
9
|
var tokensRender = require('@tramvai/tokens-render');
|
|
11
10
|
var moduleFederation = require('../shared/webpack/moduleFederation.js');
|
|
11
|
+
var utils = require('./module-federation/utils.js');
|
|
12
|
+
var bestLoadedSharedModules = require('./module-federation/best-loaded-shared-modules.js');
|
|
12
13
|
|
|
13
14
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
15
|
|
|
@@ -26,14 +27,16 @@ const deferScriptAttrs = {
|
|
|
26
27
|
// and Child App initialization logic executed after that, we need to get script loading status
|
|
27
28
|
const entryAttrs = {
|
|
28
29
|
onload: `this.setAttribute('loaded', 'true')`,
|
|
29
|
-
onerror: `this.setAttribute('loaded', '
|
|
30
|
+
onerror: `this.setAttribute('loaded', 'error')`,
|
|
30
31
|
};
|
|
31
32
|
// for cases when preloaded chunk loading is failed before webpack add this script loading handlers,
|
|
32
33
|
// we need to remove script and webpack will try to load it itself https://github.com/webpack/webpack/issues/14874
|
|
33
34
|
const chunkAttrs = {
|
|
34
35
|
onerror: `this.remove()`,
|
|
35
36
|
};
|
|
36
|
-
const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, preloadManager, loader, renderMode, resourcesRegistry, }) =>
|
|
37
|
+
const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, preloadManager, loader, renderMode, resourcesRegistry, }) =>
|
|
38
|
+
// eslint-disable-next-line max-statements
|
|
39
|
+
async () => {
|
|
37
40
|
const log = logger('child-app:render:slots');
|
|
38
41
|
const result = [];
|
|
39
42
|
// defer scripts is not suitable for React streaming, we need to ability to run them as early as possible
|
|
@@ -72,36 +75,25 @@ const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, pre
|
|
|
72
75
|
};
|
|
73
76
|
const preloadedList = new Set(preloadManager.getPreloadedList());
|
|
74
77
|
const sharedScope = moduleFederation.getSharedScope();
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// if versions are equal then module federation will pick
|
|
93
|
-
// the dep with eager prop (it's set in root-app) of with the child-app with highest name in alphabetical order
|
|
94
|
-
(semver.eq(version, last.version) && (eager !== last.eager ? eager : name > last.name))) {
|
|
95
|
-
mapSharedToChildApp.set(shareKey, { version, type, name, eager });
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
78
|
+
const preloadedConfigs = Array.from(preloadedList)
|
|
79
|
+
.map((requestConfig) => {
|
|
80
|
+
return resolveFullConfig(requestConfig);
|
|
81
|
+
})
|
|
82
|
+
.filter(Boolean);
|
|
83
|
+
// flat list of all shared items initialized in shared scope
|
|
84
|
+
const sharedScopeItems = utils.getFlatSharedScopeItemsList(sharedScope);
|
|
85
|
+
// flat list of all preloaded Child Apps shared modules
|
|
86
|
+
const sharedModules = utils.getFlatSharedModulesList({
|
|
87
|
+
preloadedConfigs,
|
|
88
|
+
loader: loader,
|
|
89
|
+
});
|
|
90
|
+
// optimal shared dependencies for preloaded Child Apps
|
|
91
|
+
const bestSharedModules = bestLoadedSharedModules.resolveBestLoadedSharedModules({
|
|
92
|
+
sharedModules,
|
|
93
|
+
sharedScopeItems,
|
|
94
|
+
});
|
|
99
95
|
// eslint-disable-next-line max-statements
|
|
100
|
-
|
|
101
|
-
const config = resolveFullConfig(requestConfig);
|
|
102
|
-
if (!config) {
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
96
|
+
preloadedConfigs.forEach((config) => {
|
|
105
97
|
const stats = 'getStats' in loader ? loader.getStats(config) : undefined;
|
|
106
98
|
const di = diManager.getChildDi(config);
|
|
107
99
|
const loadableAssets = di?.get(tokensChildApp.CHILD_APP_INTERNAL_CHUNK_EXTRACTOR)?.getMainAssets();
|
|
@@ -131,21 +123,6 @@ const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, pre
|
|
|
131
123
|
for (const file of files) {
|
|
132
124
|
addChunk(url.resolve(config.client.baseUrl, file));
|
|
133
125
|
}
|
|
134
|
-
for (const sharedModule of federatedModule.sharedModules) {
|
|
135
|
-
const { shareKey } = sharedModule.provides?.[0] ?? {};
|
|
136
|
-
const { chunks } = sharedModule;
|
|
137
|
-
const bestShared = mapSharedToChildApp.get(shareKey);
|
|
138
|
-
if (!bestShared?.eager && bestShared?.name === config.name) {
|
|
139
|
-
for (const chunk of chunks) {
|
|
140
|
-
addChunk(url.resolve(config.client.baseUrl, chunk));
|
|
141
|
-
}
|
|
142
|
-
// in stats.json federated stats could contain 2 sets of chunks for shared modules
|
|
143
|
-
// there usual one and fallback. For shared module there could be used any of this
|
|
144
|
-
// and the other one will be useless. So delete entry from map after its usage in order
|
|
145
|
-
// to add only single set of chunks for the same shared dep
|
|
146
|
-
mapSharedToChildApp.delete(shareKey);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
126
|
}
|
|
150
127
|
}
|
|
151
128
|
if (!di) {
|
|
@@ -161,13 +138,48 @@ const registerChildAppRenderSlots = ({ logger, diManager, resolveFullConfig, pre
|
|
|
161
138
|
log.error({
|
|
162
139
|
event: 'get-slots-failed',
|
|
163
140
|
childApp: {
|
|
164
|
-
name:
|
|
165
|
-
version:
|
|
166
|
-
tag:
|
|
141
|
+
name: config.name,
|
|
142
|
+
version: config.version,
|
|
143
|
+
tag: config.tag,
|
|
167
144
|
},
|
|
168
145
|
});
|
|
169
146
|
}
|
|
170
147
|
});
|
|
148
|
+
// shared chunks deduplication
|
|
149
|
+
const addedSharedChunks = new Set();
|
|
150
|
+
// preloaded chunks we need to pass to client
|
|
151
|
+
const serializableSharedModules = [];
|
|
152
|
+
bestSharedModules.forEach(({ shareKey, version, chunks, childAppName, childAppVersion }) => {
|
|
153
|
+
const childAppConfig = preloadedConfigs.find((config) => {
|
|
154
|
+
return config.name === childAppName && config.version === childAppVersion;
|
|
155
|
+
});
|
|
156
|
+
// if it is application shared dependency, we don't have any extra chunks
|
|
157
|
+
if (childAppConfig && chunks) {
|
|
158
|
+
for (const chunk of chunks) {
|
|
159
|
+
if (!addedSharedChunks.has(chunk)) {
|
|
160
|
+
addedSharedChunks.add(chunk);
|
|
161
|
+
addChunk(url.resolve(childAppConfig.client.baseUrl, chunk));
|
|
162
|
+
const containerName = `child-app__${childAppConfig.client.entry}`;
|
|
163
|
+
serializableSharedModules.push({
|
|
164
|
+
containerName,
|
|
165
|
+
shareKey,
|
|
166
|
+
version,
|
|
167
|
+
childAppName: childAppName,
|
|
168
|
+
childAppVersion: childAppVersion,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
result.push({
|
|
175
|
+
type: tokensRender.ResourceType.inlineScript,
|
|
176
|
+
slot: tokensRender.ResourceSlot.HEAD_POLYFILLS,
|
|
177
|
+
payload: `window.__webpack_share_preloaded__ = [
|
|
178
|
+
${serializableSharedModules.map((m) => {
|
|
179
|
+
return `${JSON.stringify(m)}`;
|
|
180
|
+
})}
|
|
181
|
+
];`,
|
|
182
|
+
});
|
|
171
183
|
result.map((item) => resourcesRegistry.register(item));
|
|
172
184
|
};
|
|
173
185
|
|
package/lib/server/render.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Container } from '@tinkoff/dippy';
|
|
2
|
-
import
|
|
2
|
+
import { SyncTapableHookInstance, TAPABLE_HOOK_FACTORY_TOKEN } from '@tramvai/core';
|
|
3
|
+
import type { ChildAppDiManager, ChildAppPreloadManager, ChildAppRenderManager, ChildAppRequestConfig, CHILD_APP_RESOLVE_CONFIG_TOKEN, ChildAppConfigArgs } 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;
|
|
@@ -7,7 +8,13 @@ export declare class RenderManager implements ChildAppRenderManager {
|
|
|
7
8
|
private readonly resolveFullConfig;
|
|
8
9
|
private readonly log;
|
|
9
10
|
private readonly hasRenderedSet;
|
|
10
|
-
|
|
11
|
+
private hookFactory;
|
|
12
|
+
hooks: {
|
|
13
|
+
mounted: SyncTapableHookInstance<ChildAppConfigArgs>;
|
|
14
|
+
mountFailed: SyncTapableHookInstance<ChildAppConfigArgs>;
|
|
15
|
+
};
|
|
16
|
+
constructor({ logger, preloadManager, diManager, resolveFullConfig, hookFactory, }: {
|
|
17
|
+
hookFactory: typeof TAPABLE_HOOK_FACTORY_TOKEN;
|
|
11
18
|
logger: typeof LOGGER_TOKEN;
|
|
12
19
|
preloadManager: ChildAppPreloadManager;
|
|
13
20
|
diManager: ChildAppDiManager;
|
package/lib/server/render.es.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
class RenderManager {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
preloadManager;
|
|
3
|
+
diManager;
|
|
4
|
+
resolveFullConfig;
|
|
5
|
+
log;
|
|
6
|
+
hasRenderedSet = new Set();
|
|
7
|
+
hookFactory;
|
|
8
|
+
hooks;
|
|
9
|
+
constructor({ logger, preloadManager, diManager, resolveFullConfig, hookFactory, }) {
|
|
10
|
+
this.hookFactory = hookFactory;
|
|
11
|
+
this.hooks = {
|
|
12
|
+
mounted: this.hookFactory.createSync('childAppMounted'),
|
|
13
|
+
mountFailed: this.hookFactory.createSync('childAppMountFailed'),
|
|
14
|
+
};
|
|
4
15
|
this.log = logger('child-app:render');
|
|
5
16
|
this.preloadManager = preloadManager;
|
|
6
17
|
this.diManager = diManager;
|
package/lib/server/render.js
CHANGED
|
@@ -3,8 +3,19 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
class RenderManager {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
preloadManager;
|
|
7
|
+
diManager;
|
|
8
|
+
resolveFullConfig;
|
|
9
|
+
log;
|
|
10
|
+
hasRenderedSet = new Set();
|
|
11
|
+
hookFactory;
|
|
12
|
+
hooks;
|
|
13
|
+
constructor({ logger, preloadManager, diManager, resolveFullConfig, hookFactory, }) {
|
|
14
|
+
this.hookFactory = hookFactory;
|
|
15
|
+
this.hooks = {
|
|
16
|
+
mounted: this.hookFactory.createSync('childAppMounted'),
|
|
17
|
+
mountFailed: this.hookFactory.createSync('childAppMountFailed'),
|
|
18
|
+
};
|
|
8
19
|
this.log = logger('child-app:render');
|
|
9
20
|
this.preloadManager = preloadManager;
|
|
10
21
|
this.diManager = diManager;
|
|
@@ -17,8 +17,10 @@ const executeRootStateSubscriptions = ({ store, diManager, }) => {
|
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
class StateManager {
|
|
20
|
+
log;
|
|
21
|
+
diManager;
|
|
22
|
+
state = Object.create(null);
|
|
20
23
|
constructor({ logger, diManager, }) {
|
|
21
|
-
this.state = Object.create(null);
|
|
22
24
|
this.log = logger('child-app:state-manager');
|
|
23
25
|
this.diManager = diManager;
|
|
24
26
|
}
|
|
@@ -21,8 +21,10 @@ const executeRootStateSubscriptions = ({ store, diManager, }) => {
|
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
class StateManager {
|
|
24
|
+
log;
|
|
25
|
+
diManager;
|
|
26
|
+
state = Object.create(null);
|
|
24
27
|
constructor({ logger, diManager, }) {
|
|
25
|
-
this.state = Object.create(null);
|
|
26
28
|
this.log = logger('child-app:state-manager');
|
|
27
29
|
this.diManager = diManager;
|
|
28
30
|
}
|
|
@@ -3,6 +3,10 @@ import { COMMAND_LINE_RUNNER_TOKEN, provide } from '@tramvai/core';
|
|
|
3
3
|
import { ROOT_EXECUTION_CONTEXT_TOKEN } from '@tramvai/tokens-common';
|
|
4
4
|
|
|
5
5
|
class CommandLineRunner {
|
|
6
|
+
log;
|
|
7
|
+
rootCommandLineRunner;
|
|
8
|
+
diManager;
|
|
9
|
+
commandLineExecutionContext;
|
|
6
10
|
constructor({ logger, rootCommandLineRunner, diManager, commandLineExecutionContext, }) {
|
|
7
11
|
this.log = logger('child-app:command-line-runner');
|
|
8
12
|
this.rootCommandLineRunner = rootCommandLineRunner;
|
package/lib/shared/command.es.js
CHANGED
|
@@ -3,6 +3,10 @@ import { COMMAND_LINE_RUNNER_TOKEN, provide } from '@tramvai/core';
|
|
|
3
3
|
import { ROOT_EXECUTION_CONTEXT_TOKEN } from '@tramvai/tokens-common';
|
|
4
4
|
|
|
5
5
|
class CommandLineRunner {
|
|
6
|
+
log;
|
|
7
|
+
rootCommandLineRunner;
|
|
8
|
+
diManager;
|
|
9
|
+
commandLineExecutionContext;
|
|
6
10
|
constructor({ logger, rootCommandLineRunner, diManager, commandLineExecutionContext, }) {
|
|
7
11
|
this.log = logger('child-app:command-line-runner');
|
|
8
12
|
this.rootCommandLineRunner = rootCommandLineRunner;
|
package/lib/shared/command.js
CHANGED
|
@@ -7,6 +7,10 @@ var core = require('@tramvai/core');
|
|
|
7
7
|
var tokensCommon = require('@tramvai/tokens-common');
|
|
8
8
|
|
|
9
9
|
class CommandLineRunner {
|
|
10
|
+
log;
|
|
11
|
+
rootCommandLineRunner;
|
|
12
|
+
diManager;
|
|
13
|
+
commandLineExecutionContext;
|
|
10
14
|
constructor({ logger, rootCommandLineRunner, diManager, commandLineExecutionContext, }) {
|
|
11
15
|
this.log = logger('child-app:command-line-runner');
|
|
12
16
|
this.rootCommandLineRunner = rootCommandLineRunner;
|
package/lib/shared/di.browser.js
CHANGED
|
@@ -2,8 +2,12 @@ import { ChildContainer } from '@tinkoff/dippy';
|
|
|
2
2
|
import { shouldIsolateDi } from './isolatedDi.browser.js';
|
|
3
3
|
|
|
4
4
|
class DiManager {
|
|
5
|
+
appDi;
|
|
6
|
+
loader;
|
|
7
|
+
singletonDiManager;
|
|
8
|
+
rootDiAccessMode;
|
|
9
|
+
cache = new Map();
|
|
5
10
|
constructor({ appDi, loader, singletonDiManager, rootDiAccessMode, }) {
|
|
6
|
-
this.cache = new Map();
|
|
7
11
|
this.appDi = appDi;
|
|
8
12
|
this.loader = loader;
|
|
9
13
|
this.singletonDiManager = singletonDiManager;
|
package/lib/shared/di.es.js
CHANGED
|
@@ -2,8 +2,12 @@ import { ChildContainer } from '@tinkoff/dippy';
|
|
|
2
2
|
import { shouldIsolateDi } from './isolatedDi.es.js';
|
|
3
3
|
|
|
4
4
|
class DiManager {
|
|
5
|
+
appDi;
|
|
6
|
+
loader;
|
|
7
|
+
singletonDiManager;
|
|
8
|
+
rootDiAccessMode;
|
|
9
|
+
cache = new Map();
|
|
5
10
|
constructor({ appDi, loader, singletonDiManager, rootDiAccessMode, }) {
|
|
6
|
-
this.cache = new Map();
|
|
7
11
|
this.appDi = appDi;
|
|
8
12
|
this.loader = loader;
|
|
9
13
|
this.singletonDiManager = singletonDiManager;
|
package/lib/shared/di.js
CHANGED
|
@@ -6,8 +6,12 @@ var dippy = require('@tinkoff/dippy');
|
|
|
6
6
|
var isolatedDi = require('./isolatedDi.js');
|
|
7
7
|
|
|
8
8
|
class DiManager {
|
|
9
|
+
appDi;
|
|
10
|
+
loader;
|
|
11
|
+
singletonDiManager;
|
|
12
|
+
rootDiAccessMode;
|
|
13
|
+
cache = new Map();
|
|
9
14
|
constructor({ appDi, loader, singletonDiManager, rootDiAccessMode, }) {
|
|
10
|
-
this.cache = new Map();
|
|
11
15
|
this.appDi = appDi;
|
|
12
16
|
this.loader = loader;
|
|
13
17
|
this.singletonDiManager = singletonDiManager;
|
|
@@ -2,6 +2,10 @@ import isArray from '@tinkoff/utils/is/array';
|
|
|
2
2
|
import { resolveLazyComponent } from '@tramvai/react';
|
|
3
3
|
|
|
4
4
|
class ChildAppPageService {
|
|
5
|
+
actionsRegistry;
|
|
6
|
+
config;
|
|
7
|
+
componentRegistry;
|
|
8
|
+
pageService;
|
|
5
9
|
constructor({ actionsRegistry, config, componentRegistry, pageService, pageComponents, }) {
|
|
6
10
|
this.actionsRegistry = actionsRegistry;
|
|
7
11
|
this.config = config;
|
|
@@ -11,9 +15,10 @@ class ChildAppPageService {
|
|
|
11
15
|
(pageComponents || []).forEach((record) => {
|
|
12
16
|
Object.keys(record).forEach((pageComponentName) => {
|
|
13
17
|
const pageComponent = record[pageComponentName];
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
// to prevent memory leaks, always register Child App components,
|
|
19
|
+
// because if Child App server JS is loaded again after eviction from server loader cache,
|
|
20
|
+
// we want to load new instance of components and actions and clear memory references to old server JS
|
|
21
|
+
this.componentRegistry.add(pageComponentName, pageComponent, componentsGroupName);
|
|
17
22
|
});
|
|
18
23
|
});
|
|
19
24
|
}
|
|
@@ -2,6 +2,10 @@ import isArray from '@tinkoff/utils/is/array';
|
|
|
2
2
|
import { resolveLazyComponent } from '@tramvai/react';
|
|
3
3
|
|
|
4
4
|
class ChildAppPageService {
|
|
5
|
+
actionsRegistry;
|
|
6
|
+
config;
|
|
7
|
+
componentRegistry;
|
|
8
|
+
pageService;
|
|
5
9
|
constructor({ actionsRegistry, config, componentRegistry, pageService, pageComponents, }) {
|
|
6
10
|
this.actionsRegistry = actionsRegistry;
|
|
7
11
|
this.config = config;
|
|
@@ -11,9 +15,10 @@ class ChildAppPageService {
|
|
|
11
15
|
(pageComponents || []).forEach((record) => {
|
|
12
16
|
Object.keys(record).forEach((pageComponentName) => {
|
|
13
17
|
const pageComponent = record[pageComponentName];
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
// to prevent memory leaks, always register Child App components,
|
|
19
|
+
// because if Child App server JS is loaded again after eviction from server loader cache,
|
|
20
|
+
// we want to load new instance of components and actions and clear memory references to old server JS
|
|
21
|
+
this.componentRegistry.add(pageComponentName, pageComponent, componentsGroupName);
|
|
17
22
|
});
|
|
18
23
|
});
|
|
19
24
|
}
|
|
@@ -10,6 +10,10 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
10
10
|
var isArray__default = /*#__PURE__*/_interopDefaultLegacy(isArray);
|
|
11
11
|
|
|
12
12
|
class ChildAppPageService {
|
|
13
|
+
actionsRegistry;
|
|
14
|
+
config;
|
|
15
|
+
componentRegistry;
|
|
16
|
+
pageService;
|
|
13
17
|
constructor({ actionsRegistry, config, componentRegistry, pageService, pageComponents, }) {
|
|
14
18
|
this.actionsRegistry = actionsRegistry;
|
|
15
19
|
this.config = config;
|
|
@@ -19,9 +23,10 @@ class ChildAppPageService {
|
|
|
19
23
|
(pageComponents || []).forEach((record) => {
|
|
20
24
|
Object.keys(record).forEach((pageComponentName) => {
|
|
21
25
|
const pageComponent = record[pageComponentName];
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
// to prevent memory leaks, always register Child App components,
|
|
27
|
+
// because if Child App server JS is loaded again after eviction from server loader cache,
|
|
28
|
+
// we want to load new instance of components and actions and clear memory references to old server JS
|
|
29
|
+
this.componentRegistry.add(pageComponentName, pageComponent, componentsGroupName);
|
|
25
30
|
});
|
|
26
31
|
});
|
|
27
32
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Scope, DI_TOKEN, optional } from '@tinkoff/dippy';
|
|
2
|
-
import { provide, commandLineListTokens, COMMAND_LINE_RUNNER_TOKEN } from '@tramvai/core';
|
|
3
|
-
import { 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_ROOT_DI_ACCESS_MODE_TOKEN, CHILD_APP_CONTRACT_MANAGER, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, HOST_PROVIDED_CONTRACTS, CHILD_APP_ERROR_BOUNDARY_TOKEN } from '@tramvai/tokens-child-app';
|
|
2
|
+
import { provide, commandLineListTokens, TAPABLE_HOOK_FACTORY_TOKEN, COMMAND_LINE_RUNNER_TOKEN } from '@tramvai/core';
|
|
3
|
+
import { CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, CHILD_APP_CONFIG_RESOLUTION_PLUGIN, 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_ROOT_DI_ACCESS_MODE_TOKEN, CHILD_APP_CONTRACT_MANAGER, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, HOST_PROVIDED_CONTRACTS, CHILD_APP_ERROR_BOUNDARY_TOKEN } from '@tramvai/tokens-child-app';
|
|
4
4
|
import { COMBINE_REDUCERS, LOGGER_TOKEN, ENV_MANAGER_TOKEN, COMMAND_LINE_EXECUTION_CONTEXT_TOKEN, REGISTER_CLEAR_CACHE_TOKEN, CLEAR_CACHE_TOKEN, ENV_USED_TOKEN, COMPONENT_REGISTRY_TOKEN, LIMIT_ACTION_GLOBAL_TIME_RUN, ACTION_CONDITIONALS } from '@tramvai/tokens-common';
|
|
5
5
|
import { EXTEND_RENDER } from '@tramvai/tokens-render';
|
|
6
6
|
import { ROUTER_TOKEN, PAGE_SERVICE_TOKEN, LINK_PREFETCH_MANAGER_TOKEN, ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN } from '@tramvai/tokens-router';
|
|
@@ -18,7 +18,7 @@ const sharedProviders = [
|
|
|
18
18
|
provide({
|
|
19
19
|
provide: COMBINE_REDUCERS,
|
|
20
20
|
multi: true,
|
|
21
|
-
useValue: ChildAppStore,
|
|
21
|
+
useValue: [ChildAppStore],
|
|
22
22
|
}),
|
|
23
23
|
provide({
|
|
24
24
|
provide: commandLineListTokens.init,
|
|
@@ -29,6 +29,11 @@ const sharedProviders = [
|
|
|
29
29
|
provide: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
30
30
|
useClass: ChildAppResolutionConfigManager,
|
|
31
31
|
deps: {
|
|
32
|
+
hookFactory: TAPABLE_HOOK_FACTORY_TOKEN,
|
|
33
|
+
plugins: {
|
|
34
|
+
optional: true,
|
|
35
|
+
token: CHILD_APP_CONFIG_RESOLUTION_PLUGIN,
|
|
36
|
+
},
|
|
32
37
|
configs: { token: CHILD_APP_RESOLUTION_CONFIGS_TOKEN, optional: true },
|
|
33
38
|
logger: LOGGER_TOKEN,
|
|
34
39
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Scope, DI_TOKEN, optional } from '@tinkoff/dippy';
|
|
2
|
-
import { provide, commandLineListTokens, COMMAND_LINE_RUNNER_TOKEN } from '@tramvai/core';
|
|
3
|
-
import { 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_ROOT_DI_ACCESS_MODE_TOKEN, CHILD_APP_CONTRACT_MANAGER, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, HOST_PROVIDED_CONTRACTS, CHILD_APP_ERROR_BOUNDARY_TOKEN } from '@tramvai/tokens-child-app';
|
|
2
|
+
import { provide, commandLineListTokens, TAPABLE_HOOK_FACTORY_TOKEN, COMMAND_LINE_RUNNER_TOKEN } from '@tramvai/core';
|
|
3
|
+
import { CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN, CHILD_APP_CONFIG_RESOLUTION_PLUGIN, 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_ROOT_DI_ACCESS_MODE_TOKEN, CHILD_APP_CONTRACT_MANAGER, CHILD_APP_DI_MANAGER_TOKEN, CHILD_APP_COMMAND_LINE_RUNNER_TOKEN, CHILD_APP_PRELOAD_MANAGER_TOKEN, CHILD_APP_RENDER_MANAGER_TOKEN, HOST_PROVIDED_CONTRACTS, CHILD_APP_ERROR_BOUNDARY_TOKEN } from '@tramvai/tokens-child-app';
|
|
4
4
|
import { COMBINE_REDUCERS, LOGGER_TOKEN, ENV_MANAGER_TOKEN, COMMAND_LINE_EXECUTION_CONTEXT_TOKEN, REGISTER_CLEAR_CACHE_TOKEN, CLEAR_CACHE_TOKEN, ENV_USED_TOKEN, COMPONENT_REGISTRY_TOKEN, LIMIT_ACTION_GLOBAL_TIME_RUN, ACTION_CONDITIONALS } from '@tramvai/tokens-common';
|
|
5
5
|
import { EXTEND_RENDER } from '@tramvai/tokens-render';
|
|
6
6
|
import { ROUTER_TOKEN, PAGE_SERVICE_TOKEN, LINK_PREFETCH_MANAGER_TOKEN, ROUTER_SPA_ACTIONS_RUN_MODE_TOKEN } from '@tramvai/tokens-router';
|
|
@@ -18,7 +18,7 @@ const sharedProviders = [
|
|
|
18
18
|
provide({
|
|
19
19
|
provide: COMBINE_REDUCERS,
|
|
20
20
|
multi: true,
|
|
21
|
-
useValue: ChildAppStore,
|
|
21
|
+
useValue: [ChildAppStore],
|
|
22
22
|
}),
|
|
23
23
|
provide({
|
|
24
24
|
provide: commandLineListTokens.init,
|
|
@@ -29,6 +29,11 @@ const sharedProviders = [
|
|
|
29
29
|
provide: CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
30
30
|
useClass: ChildAppResolutionConfigManager,
|
|
31
31
|
deps: {
|
|
32
|
+
hookFactory: TAPABLE_HOOK_FACTORY_TOKEN,
|
|
33
|
+
plugins: {
|
|
34
|
+
optional: true,
|
|
35
|
+
token: CHILD_APP_CONFIG_RESOLUTION_PLUGIN,
|
|
36
|
+
},
|
|
32
37
|
configs: { token: CHILD_APP_RESOLUTION_CONFIGS_TOKEN, optional: true },
|
|
33
38
|
logger: LOGGER_TOKEN,
|
|
34
39
|
},
|
package/lib/shared/providers.js
CHANGED
|
@@ -22,7 +22,7 @@ const sharedProviders = [
|
|
|
22
22
|
core.provide({
|
|
23
23
|
provide: tokensCommon.COMBINE_REDUCERS,
|
|
24
24
|
multi: true,
|
|
25
|
-
useValue: store.ChildAppStore,
|
|
25
|
+
useValue: [store.ChildAppStore],
|
|
26
26
|
}),
|
|
27
27
|
core.provide({
|
|
28
28
|
provide: core.commandLineListTokens.init,
|
|
@@ -33,6 +33,11 @@ const sharedProviders = [
|
|
|
33
33
|
provide: tokensChildApp.CHILD_APP_RESOLUTION_CONFIG_MANAGER_TOKEN,
|
|
34
34
|
useClass: resolutionConfigManager.ChildAppResolutionConfigManager,
|
|
35
35
|
deps: {
|
|
36
|
+
hookFactory: core.TAPABLE_HOOK_FACTORY_TOKEN,
|
|
37
|
+
plugins: {
|
|
38
|
+
optional: true,
|
|
39
|
+
token: tokensChildApp.CHILD_APP_CONFIG_RESOLUTION_PLUGIN,
|
|
40
|
+
},
|
|
36
41
|
configs: { token: tokensChildApp.CHILD_APP_RESOLUTION_CONFIGS_TOKEN, optional: true },
|
|
37
42
|
logger: tokensCommon.LOGGER_TOKEN,
|
|
38
43
|
},
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Component } from 'react';
|
|
3
|
+
import { FallbackError } from './FallbackError.browser.js';
|
|
4
|
+
import { ChildAppFallbackWrapper } from '../ChildAppFallbackWrapper.browser.js';
|
|
5
|
+
|
|
6
|
+
class ChildAppErrorBoundary extends Component {
|
|
7
|
+
constructor(props) {
|
|
8
|
+
super(props);
|
|
9
|
+
this.state = {
|
|
10
|
+
error: props.error || null,
|
|
11
|
+
childAppLoadingStatus: null,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
static displayName = 'ChildAppErrorBoundary';
|
|
15
|
+
static getDerivedStateFromProps(props, state) {
|
|
16
|
+
if (!props.childAppLoadingStatus) {
|
|
17
|
+
return { error: props.error || state.error };
|
|
18
|
+
}
|
|
19
|
+
if (state.childAppLoadingStatus &&
|
|
20
|
+
props.childAppLoadingStatus &&
|
|
21
|
+
props.childAppLoadingStatus !== state.childAppLoadingStatus) {
|
|
22
|
+
return { error: props.error || null, childAppLoadingStatus: props.childAppLoadingStatus };
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
error: props.error || state.error,
|
|
26
|
+
childAppLoadingStatus: props.childAppLoadingStatus,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
static getDerivedStateFromError(error) {
|
|
30
|
+
return { error };
|
|
31
|
+
}
|
|
32
|
+
componentDidCatch(error, errorInfo) {
|
|
33
|
+
const { errorHandlers } = this.props;
|
|
34
|
+
if (errorHandlers) {
|
|
35
|
+
errorHandlers.forEach((handler) => {
|
|
36
|
+
handler(error, errorInfo);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
render() {
|
|
41
|
+
const { children, fallback: Fallback, fallbackFromDi, config } = this.props;
|
|
42
|
+
const { error } = this.state;
|
|
43
|
+
if (!error) {
|
|
44
|
+
return children;
|
|
45
|
+
}
|
|
46
|
+
if (Fallback) {
|
|
47
|
+
return jsx(ChildAppFallbackWrapper, { fallback: Fallback, ...config, error: error });
|
|
48
|
+
}
|
|
49
|
+
if (fallbackFromDi) {
|
|
50
|
+
return fallbackFromDi;
|
|
51
|
+
}
|
|
52
|
+
return jsx(FallbackError, {});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { ChildAppErrorBoundary };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import type { ExtractDependencyType } from '@tinkoff/dippy';
|
|
3
|
+
import type { ERROR_BOUNDARY_TOKEN } from '@tramvai/react';
|
|
4
|
+
import { ChildAppReactConfig } from '@tramvai/tokens-child-app';
|
|
5
|
+
type AnyError = Error & {
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
};
|
|
8
|
+
export interface ChildAppErrorBoundaryFallbackProps {
|
|
9
|
+
error: AnyError;
|
|
10
|
+
}
|
|
11
|
+
export interface ChildAppErrorBoundaryProps {
|
|
12
|
+
config: ChildAppReactConfig;
|
|
13
|
+
childAppLoadingStatus?: string;
|
|
14
|
+
error?: AnyError | null;
|
|
15
|
+
fallback?: React.ComponentType<ChildAppErrorBoundaryFallbackProps>;
|
|
16
|
+
errorHandlers?: ExtractDependencyType<typeof ERROR_BOUNDARY_TOKEN> | null;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated
|
|
19
|
+
*/
|
|
20
|
+
fallbackFromDi?: React.ReactElement | null;
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
}
|
|
23
|
+
interface State {
|
|
24
|
+
error: AnyError | null;
|
|
25
|
+
childAppLoadingStatus?: string | null;
|
|
26
|
+
}
|
|
27
|
+
type Props = ChildAppErrorBoundaryProps;
|
|
28
|
+
export declare class ChildAppErrorBoundary extends Component<Props, State> {
|
|
29
|
+
constructor(props: Props);
|
|
30
|
+
static displayName: string;
|
|
31
|
+
static getDerivedStateFromProps(props: Props, state: State): {
|
|
32
|
+
error: AnyError | null;
|
|
33
|
+
childAppLoadingStatus?: undefined;
|
|
34
|
+
} | {
|
|
35
|
+
error: AnyError | null;
|
|
36
|
+
childAppLoadingStatus: string;
|
|
37
|
+
};
|
|
38
|
+
static getDerivedStateFromError(error: AnyError): {
|
|
39
|
+
error: AnyError;
|
|
40
|
+
};
|
|
41
|
+
componentDidCatch(error: AnyError, errorInfo: React.ErrorInfo): void;
|
|
42
|
+
render(): React.ReactNode;
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=ChildAppErrorBoundary.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Component } from 'react';
|
|
3
|
+
import { FallbackError } from './FallbackError.es.js';
|
|
4
|
+
import { ChildAppFallbackWrapper } from '../ChildAppFallbackWrapper.es.js';
|
|
5
|
+
|
|
6
|
+
class ChildAppErrorBoundary extends Component {
|
|
7
|
+
constructor(props) {
|
|
8
|
+
super(props);
|
|
9
|
+
this.state = {
|
|
10
|
+
error: props.error || null,
|
|
11
|
+
childAppLoadingStatus: null,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
static displayName = 'ChildAppErrorBoundary';
|
|
15
|
+
static getDerivedStateFromProps(props, state) {
|
|
16
|
+
if (!props.childAppLoadingStatus) {
|
|
17
|
+
return { error: props.error || state.error };
|
|
18
|
+
}
|
|
19
|
+
if (state.childAppLoadingStatus &&
|
|
20
|
+
props.childAppLoadingStatus &&
|
|
21
|
+
props.childAppLoadingStatus !== state.childAppLoadingStatus) {
|
|
22
|
+
return { error: props.error || null, childAppLoadingStatus: props.childAppLoadingStatus };
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
error: props.error || state.error,
|
|
26
|
+
childAppLoadingStatus: props.childAppLoadingStatus,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
static getDerivedStateFromError(error) {
|
|
30
|
+
return { error };
|
|
31
|
+
}
|
|
32
|
+
componentDidCatch(error, errorInfo) {
|
|
33
|
+
const { errorHandlers } = this.props;
|
|
34
|
+
if (errorHandlers) {
|
|
35
|
+
errorHandlers.forEach((handler) => {
|
|
36
|
+
handler(error, errorInfo);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
render() {
|
|
41
|
+
const { children, fallback: Fallback, fallbackFromDi, config } = this.props;
|
|
42
|
+
const { error } = this.state;
|
|
43
|
+
if (!error) {
|
|
44
|
+
return children;
|
|
45
|
+
}
|
|
46
|
+
if (Fallback) {
|
|
47
|
+
return jsx(ChildAppFallbackWrapper, { fallback: Fallback, ...config, error: error });
|
|
48
|
+
}
|
|
49
|
+
if (fallbackFromDi) {
|
|
50
|
+
return fallbackFromDi;
|
|
51
|
+
}
|
|
52
|
+
return jsx(FallbackError, {});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { ChildAppErrorBoundary };
|