@softarc/native-federation 4.0.0-RC7 → 4.0.0-RC9
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/package.json +1 -1
- package/src/index.d.ts +1 -2
- package/src/index.js +1 -2
- package/src/internal.d.ts +3 -2
- package/src/internal.js +1 -0
- package/src/lib/config/default-skip-list.js +3 -15
- package/src/lib/config/remove-unused-deps.d.ts +3 -0
- package/src/lib/config/remove-unused-deps.js +10 -0
- package/src/lib/config/share-utils.d.ts +0 -1
- package/src/lib/config/share-utils.js +7 -13
- package/src/lib/config/with-native-federation.js +40 -61
- package/src/lib/core/build-for-federation.js +30 -30
- package/src/lib/core/bundle-exposed-and-mappings.js +15 -17
- package/src/lib/core/bundle-shared.d.ts +1 -0
- package/src/lib/core/bundle-shared.js +8 -7
- package/src/lib/core/federation-builder.d.ts +6 -1
- package/src/lib/core/federation-builder.js +18 -8
- package/src/lib/core/get-externals.js +1 -1
- package/src/lib/core/normalize-options.d.ts +12 -0
- package/src/lib/core/normalize-options.js +90 -0
- package/src/lib/core/rebuild-for-federation.js +2 -2
- package/src/lib/domain/config/external-config.contract.d.ts +3 -1
- package/src/lib/domain/config/federation-config.contract.d.ts +8 -2
- package/src/lib/domain/config/with-native-federation.contract.d.ts +2 -0
- package/src/lib/domain/config/with-native-federation.contract.js +1 -0
- package/src/lib/domain/core/build-adapter.contract.d.ts +12 -6
- package/src/lib/domain/core/federation-options.contract.d.ts +4 -5
- package/src/lib/domain/core/index.d.ts +1 -1
- package/src/lib/domain/utils/index.d.ts +1 -1
- package/src/lib/domain/utils/mapped-path.contract.d.ts +1 -4
- package/src/lib/domain/utils/mapped-path.contract.js +4 -0
- package/src/lib/domain/utils/used-dependencies.contract.d.ts +5 -0
- package/src/lib/domain/utils/used-dependencies.contract.js +1 -0
- package/src/lib/utils/get-used-dependencies.d.ts +7 -0
- package/src/lib/utils/get-used-dependencies.js +123 -0
- package/src/lib/utils/mapped-paths.d.ts +7 -7
- package/src/lib/utils/mapped-paths.js +14 -12
- package/src/lib/utils/rebuild-queue.d.ts +14 -1
- package/src/lib/utils/rebuild-queue.js +32 -12
- package/src/lib/utils/resolve-wildcard-keys.d.ts +29 -2
- package/src/lib/utils/resolve-wildcard-keys.js +105 -38
- package/src/lib/core/default-server-deps-list.d.ts +0 -2
- package/src/lib/core/default-server-deps-list.js +0 -6
- package/src/lib/core/load-federation-config.d.ts +0 -3
- package/src/lib/core/load-federation-config.js +0 -18
- package/src/lib/core/normalize-federation-options.d.ts +0 -4
- package/src/lib/core/normalize-federation-options.js +0 -10
- package/src/lib/core/remove-unused-deps.d.ts +0 -2
- package/src/lib/core/remove-unused-deps.js +0 -90
- package/src/lib/utils/config-utils.d.ts +0 -2
- package/src/lib/utils/config-utils.js +0 -9
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
export { setBuildAdapter } from './lib/core/build-adapter.js';
|
|
2
2
|
export { buildForFederation } from './lib/core/build-for-federation.js';
|
|
3
3
|
export { rebuildForFederation } from './lib/core/rebuild-for-federation.js';
|
|
4
|
-
export { normalizeFederationOptions } from './lib/core/normalize-federation-options.js';
|
|
5
4
|
export { createFederationCache } from './lib/core/federation-cache.js';
|
|
6
5
|
export { bundleExposedAndMappings } from './lib/core/bundle-exposed-and-mappings.js';
|
|
7
6
|
export { getExternals } from './lib/core/get-externals.js';
|
|
8
|
-
export {
|
|
7
|
+
export { normalizeFederationOptions } from './lib/core/normalize-options.js';
|
|
9
8
|
export { writeFederationInfo } from './lib/core/write-federation-info.js';
|
|
10
9
|
export { type BuildHelperParams, federationBuilder } from './lib/core/federation-builder.js';
|
|
11
10
|
export * from './domain.js';
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
export { setBuildAdapter } from './lib/core/build-adapter.js';
|
|
2
2
|
export { buildForFederation } from './lib/core/build-for-federation.js';
|
|
3
3
|
export { rebuildForFederation } from './lib/core/rebuild-for-federation.js';
|
|
4
|
-
export { normalizeFederationOptions } from './lib/core/normalize-federation-options.js';
|
|
5
4
|
export { createFederationCache } from './lib/core/federation-cache.js';
|
|
6
5
|
export { bundleExposedAndMappings } from './lib/core/bundle-exposed-and-mappings.js';
|
|
7
6
|
export { getExternals } from './lib/core/get-externals.js';
|
|
8
|
-
export {
|
|
7
|
+
export { normalizeFederationOptions } from './lib/core/normalize-options.js';
|
|
9
8
|
export { writeFederationInfo } from './lib/core/write-federation-info.js';
|
|
10
9
|
export { federationBuilder } from './lib/core/federation-builder.js';
|
|
11
10
|
export * from './domain.js';
|
package/src/internal.d.ts
CHANGED
|
@@ -2,11 +2,12 @@ export * from './lib/utils/build-result-map.js';
|
|
|
2
2
|
export { hashFile } from './lib/utils/hash-file.js';
|
|
3
3
|
export * from './lib/utils/errors.js';
|
|
4
4
|
export { logger, setLogLevel } from './lib/utils/logger.js';
|
|
5
|
-
export type {
|
|
6
|
-
export { RebuildQueue } from './lib/utils/rebuild-queue.js';
|
|
5
|
+
export type { PathToImport } from './lib/domain/utils/mapped-path.contract.js';
|
|
6
|
+
export { RebuildQueue, type TrackResult } from './lib/utils/rebuild-queue.js';
|
|
7
7
|
export { AbortedError } from './lib/utils/errors.js';
|
|
8
8
|
export { createBuildResultMap, lookupInResultMap, popFromResultMap, } from './lib/utils/build-result-map.js';
|
|
9
9
|
export { writeImportMap } from './lib/core/write-import-map.js';
|
|
10
10
|
export type { NormalizedExternalConfig, NormalizedSharedExternalsConfig, } from './lib/domain/config/external-config.contract.js';
|
|
11
11
|
export type { NormalizedFederationConfig } from './lib/domain/config/federation-config.contract.js';
|
|
12
12
|
export { getDefaultCachePath, getChecksum } from './lib/utils/cache-persistence.js';
|
|
13
|
+
export { isInSkipList, prepareSkipList } from './lib/config/default-skip-list.js';
|
package/src/internal.js
CHANGED
|
@@ -7,3 +7,4 @@ export { AbortedError } from './lib/utils/errors.js';
|
|
|
7
7
|
export { createBuildResultMap, lookupInResultMap, popFromResultMap, } from './lib/utils/build-result-map.js';
|
|
8
8
|
export { writeImportMap } from './lib/core/write-import-map.js';
|
|
9
9
|
export { getDefaultCachePath, getChecksum } from './lib/utils/cache-persistence.js';
|
|
10
|
+
export { isInSkipList, prepareSkipList } from './lib/config/default-skip-list.js';
|
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
export const DEFAULT_SKIP_LIST = [
|
|
2
|
-
'@softarc/native-federation-runtime',
|
|
3
2
|
'@softarc/native-federation',
|
|
4
3
|
'@softarc/native-federation-core',
|
|
5
4
|
'@softarc/native-federation-node',
|
|
6
5
|
'@softarc/native-federation-esbuild',
|
|
7
|
-
'@
|
|
8
|
-
'@
|
|
6
|
+
'@softarc/native-federation-runtime',
|
|
7
|
+
'@softarc/native-federation-orchestrator',
|
|
8
|
+
'vanilla-native-federation',
|
|
9
9
|
'es-module-shims',
|
|
10
|
-
'zone.js',
|
|
11
10
|
'tslib/',
|
|
12
|
-
'@angular/localize',
|
|
13
|
-
'@angular/localize/init',
|
|
14
|
-
'@angular/localize/tools',
|
|
15
|
-
// '@angular/platform-server',
|
|
16
|
-
// '@angular/platform-server/init',
|
|
17
|
-
// '@angular/ssr',
|
|
18
|
-
/\/schematics(\/|$)/,
|
|
19
|
-
/^@nx\/angular/,
|
|
20
|
-
pkg => pkg.startsWith('@angular/') && !!pkg.match(/\/testing(\/|$)/),
|
|
21
11
|
pkg => pkg.startsWith('@types/'),
|
|
22
|
-
'express',
|
|
23
|
-
// (pkg) => pkg.startsWith('@angular/common/locales'),
|
|
24
12
|
];
|
|
25
13
|
export function prepareSkipList(skipList) {
|
|
26
14
|
return {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { NormalizedFederationConfig } from '../domain/config/federation-config.contract.js';
|
|
2
|
+
import type { UsedDependencies } from '../domain/utils/used-dependencies.contract.js';
|
|
3
|
+
export declare function removeUnusedDeps(usedDependencies: UsedDependencies, config: NormalizedFederationConfig): NormalizedFederationConfig;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function removeUnusedDeps(usedDependencies, config) {
|
|
2
|
+
const filteredDependencies = Object.entries(config.shared)
|
|
3
|
+
.filter(([shared, meta]) => !!meta.includeSecondaries || usedDependencies.external.has(shared))
|
|
4
|
+
.reduce((acc, [shared, meta]) => ({ ...acc, [shared]: meta }), {});
|
|
5
|
+
return {
|
|
6
|
+
...config,
|
|
7
|
+
shared: filteredDependencies,
|
|
8
|
+
sharedMappings: usedDependencies.internal,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type SkipList } from '../domain/config/skip-list.contract.js';
|
|
2
2
|
import type { ShareAllExternalsOptions, ShareExternalsOptions } from '../domain/config/external-config.contract.js';
|
|
3
|
-
export declare const DEFAULT_SECONDARIES_SKIP_LIST: string[];
|
|
4
3
|
export declare function findRootTsConfigJson(): string;
|
|
5
4
|
export declare function shareAll(config: ShareAllExternalsOptions, opts?: {
|
|
6
5
|
skipList?: SkipList;
|
|
@@ -5,9 +5,8 @@ import { DEFAULT_SKIP_LIST, isInSkipList, prepareSkipList } from './default-skip
|
|
|
5
5
|
import { findDepPackageJson, getVersionMaps } from '../utils/package-info.js';
|
|
6
6
|
import { getConfigContext } from './configuration-context.js';
|
|
7
7
|
import { logger } from '../utils/logger.js';
|
|
8
|
-
import {
|
|
8
|
+
import { resolvePackageJsonExportsWildcard } from '../utils/resolve-wildcard-keys.js';
|
|
9
9
|
let inferVersion = false;
|
|
10
|
-
export const DEFAULT_SECONDARIES_SKIP_LIST = ['@angular/router/upgrade', '@angular/common/upgrade'];
|
|
11
10
|
export function findRootTsConfigJson() {
|
|
12
11
|
const packageJson = findPackageJson(cwd());
|
|
13
12
|
const projectRoot = path.dirname(packageJson);
|
|
@@ -49,9 +48,6 @@ function lookupVersionInMap(key, versions) {
|
|
|
49
48
|
else {
|
|
50
49
|
key = parts[0];
|
|
51
50
|
}
|
|
52
|
-
if (key.toLowerCase() === '@angular-architects/module-federation-runtime') {
|
|
53
|
-
key = '@angular-architects/module-federation';
|
|
54
|
-
}
|
|
55
51
|
if (!versions[key]) {
|
|
56
52
|
return null;
|
|
57
53
|
}
|
|
@@ -82,7 +78,7 @@ function findSecondaries(libPath, excludes, shareObject, preparedSkipList) {
|
|
|
82
78
|
return acc;
|
|
83
79
|
}
|
|
84
80
|
function getSecondaries(includeSecondaries, libPath, key, shareObject, preparedSkipList) {
|
|
85
|
-
let exclude = [
|
|
81
|
+
let exclude = [];
|
|
86
82
|
let resolveGlob = false;
|
|
87
83
|
if (typeof includeSecondaries === 'object') {
|
|
88
84
|
if (Array.isArray(includeSecondaries.skip)) {
|
|
@@ -166,7 +162,7 @@ function resolveGlobSecondaries(key, libPath, parent, secondaryName, entry, excl
|
|
|
166
162
|
if (key.includes('*')) {
|
|
167
163
|
if (!resolveGlob)
|
|
168
164
|
return items;
|
|
169
|
-
const expanded =
|
|
165
|
+
const expanded = resolvePackageJsonExportsWildcard(key, entry, libPath);
|
|
170
166
|
items = expanded
|
|
171
167
|
.map(e => ({
|
|
172
168
|
key: path.join(parent, e.key),
|
|
@@ -221,10 +217,10 @@ export function shareAll(config, opts = {}) {
|
|
|
221
217
|
// }
|
|
222
218
|
const versionMaps = getVersionMaps(projectPath, projectPath);
|
|
223
219
|
const sharedExternals = {};
|
|
224
|
-
const
|
|
220
|
+
const skipList = opts.skipList ?? DEFAULT_SKIP_LIST;
|
|
225
221
|
for (const versions of versionMaps) {
|
|
226
222
|
for (const key in versions) {
|
|
227
|
-
if (isInSkipList(key,
|
|
223
|
+
if (isInSkipList(key, prepareSkipList(skipList))) {
|
|
228
224
|
continue;
|
|
229
225
|
}
|
|
230
226
|
if (!!opts.overrides && Object.keys(opts.overrides).some(o => key.startsWith(o))) {
|
|
@@ -238,10 +234,8 @@ export function shareAll(config, opts = {}) {
|
|
|
238
234
|
}
|
|
239
235
|
}
|
|
240
236
|
return {
|
|
241
|
-
...share(sharedExternals, opts.projectPath,
|
|
242
|
-
...(!opts.overrides
|
|
243
|
-
? {}
|
|
244
|
-
: share(opts.overrides, opts.projectPath, opts.skipList ?? DEFAULT_SKIP_LIST)),
|
|
237
|
+
...share(sharedExternals, opts.projectPath, skipList),
|
|
238
|
+
...(!opts.overrides ? {} : share(opts.overrides, opts.projectPath, skipList)),
|
|
245
239
|
};
|
|
246
240
|
}
|
|
247
241
|
function inferProjectPath(projectPath) {
|
|
@@ -1,91 +1,70 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getRawMappedPaths } from '../utils/mapped-paths.js';
|
|
2
2
|
import { shareAll, findRootTsConfigJson } from './share-utils.js';
|
|
3
3
|
import { isInSkipList, prepareSkipList } from './default-skip-list.js';
|
|
4
4
|
import { logger } from '../utils/logger.js';
|
|
5
|
-
import { DEFAULT_SERVER_DEPS_LIST } from '../core/default-server-deps-list.js';
|
|
6
5
|
export function withNativeFederation(config) {
|
|
7
6
|
const skip = prepareSkipList(config.skip ?? []);
|
|
7
|
+
const chunks = config.chunks ?? true;
|
|
8
8
|
const normalized = {
|
|
9
|
+
$type: 'classic',
|
|
9
10
|
name: config.name ?? '',
|
|
10
11
|
exposes: config.exposes ?? {},
|
|
11
|
-
shared: normalizeShared(config, skip),
|
|
12
|
-
sharedMappings:
|
|
12
|
+
shared: normalizeShared(config, skip, chunks),
|
|
13
|
+
sharedMappings: removeSkippedMappings(config, skip),
|
|
14
|
+
chunks,
|
|
13
15
|
skip,
|
|
14
16
|
externals: config.externals ?? [],
|
|
15
17
|
features: {
|
|
16
18
|
mappingVersion: config.features?.mappingVersion ?? false,
|
|
17
|
-
ignoreUnusedDeps: config.features?.ignoreUnusedDeps ??
|
|
19
|
+
ignoreUnusedDeps: config.features?.ignoreUnusedDeps ?? true,
|
|
20
|
+
denseChunking: config.features?.denseChunking ?? false,
|
|
18
21
|
},
|
|
19
22
|
...(config.shareScope && { shareScope: config.shareScope }),
|
|
20
23
|
};
|
|
21
|
-
// This is for being backwards compatible
|
|
22
|
-
if (!normalized.features.ignoreUnusedDeps) {
|
|
23
|
-
normalized.shared = filterShared(normalized.shared);
|
|
24
|
-
}
|
|
25
24
|
return normalized;
|
|
26
25
|
}
|
|
27
|
-
function
|
|
28
|
-
const keys = Object.keys(shared).filter(k => !k.startsWith('@angular/common/locales'));
|
|
29
|
-
const filtered = keys.reduce((acc, curr) => ({
|
|
30
|
-
...acc,
|
|
31
|
-
[curr]: shared[curr],
|
|
32
|
-
}), {});
|
|
33
|
-
return filtered;
|
|
34
|
-
}
|
|
35
|
-
function normalizeShared(config, skip) {
|
|
26
|
+
function normalizeShared(config, skip, chunks) {
|
|
36
27
|
let result = {};
|
|
37
|
-
const shared = config.shared
|
|
38
|
-
|
|
39
|
-
result = shareAll({
|
|
28
|
+
const shared = config.shared ??
|
|
29
|
+
shareAll({
|
|
40
30
|
singleton: true,
|
|
41
31
|
strictVersion: true,
|
|
42
32
|
requiredVersion: 'auto',
|
|
43
33
|
platform: 'browser',
|
|
44
34
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
35
|
+
result = Object.keys(shared).reduce((acc, cur) => {
|
|
36
|
+
const key = cur.replace(/\\/g, '/');
|
|
37
|
+
const sharedConfig = shared[cur];
|
|
38
|
+
if (!!sharedConfig.chunks && !sharedConfig.build && sharedConfig.chunks !== chunks) {
|
|
39
|
+
logger.warn(`External '${cur}' has explicit chunk settings, consider switching build type to { build: 'package' }.`);
|
|
40
|
+
sharedConfig.chunks = chunks;
|
|
41
|
+
}
|
|
42
|
+
const normalizedConfig = {
|
|
43
|
+
requiredVersion: sharedConfig.requiredVersion ?? 'auto',
|
|
44
|
+
singleton: sharedConfig.singleton ?? false,
|
|
45
|
+
strictVersion: sharedConfig.strictVersion ?? false,
|
|
46
|
+
version: sharedConfig.version,
|
|
47
|
+
chunks: sharedConfig.chunks ?? chunks,
|
|
48
|
+
includeSecondaries: sharedConfig.includeSecondaries,
|
|
49
|
+
packageInfo: sharedConfig.packageInfo,
|
|
50
|
+
platform: sharedConfig.platform ?? config.platform ?? 'browser',
|
|
51
|
+
build: sharedConfig.build ?? 'default',
|
|
52
|
+
...(sharedConfig.shareScope && { shareScope: sharedConfig.shareScope }),
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
...acc,
|
|
56
|
+
[key]: normalizedConfig,
|
|
57
|
+
};
|
|
58
|
+
}, {});
|
|
67
59
|
result = Object.keys(result)
|
|
68
60
|
.filter(key => !isInSkipList(key, skip))
|
|
69
61
|
.reduce((acc, cur) => ({ ...acc, [cur]: result[cur] }), {});
|
|
70
62
|
return result;
|
|
71
63
|
}
|
|
72
|
-
function
|
|
64
|
+
function removeSkippedMappings(config, skipList) {
|
|
73
65
|
const rootTsConfigPath = findRootTsConfigJson();
|
|
74
|
-
const paths =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const result = paths.filter(p => !isInSkipList(p.key, skip) && !p.key.includes('*'));
|
|
79
|
-
if (paths.find(p => p.key.includes('*'))) {
|
|
80
|
-
logger.warn('Sharing mapped paths with wildcards (*) not supported');
|
|
81
|
-
}
|
|
82
|
-
return result;
|
|
83
|
-
}
|
|
84
|
-
function getDefaultPlatform(cur) {
|
|
85
|
-
if (DEFAULT_SERVER_DEPS_LIST.find(e => cur.startsWith(e))) {
|
|
86
|
-
return 'node';
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
return 'browser';
|
|
90
|
-
}
|
|
66
|
+
const paths = getRawMappedPaths(rootTsConfigPath, config.sharedMappings);
|
|
67
|
+
return Object.entries(paths)
|
|
68
|
+
.filter(([, _import]) => !isInSkipList(_import, skipList))
|
|
69
|
+
.reduce((acc, [_path, _import]) => ({ ...acc, [_path]: _import }), {});
|
|
91
70
|
}
|
|
@@ -5,62 +5,63 @@ import { writeImportMap } from './write-import-map.js';
|
|
|
5
5
|
import { logger } from '../utils/logger.js';
|
|
6
6
|
import { normalizePackageName } from '../utils/normalize.js';
|
|
7
7
|
import { AbortedError } from '../utils/errors.js';
|
|
8
|
-
import { resolveProjectName } from '../utils/config-utils.js';
|
|
9
8
|
import { addExternalsToCache } from './federation-cache.js';
|
|
10
9
|
import path from 'path';
|
|
11
10
|
export async function buildForFederation(config, fedOptions, externals, signal) {
|
|
12
|
-
// 1.
|
|
13
|
-
fedOptions.federationCache.cachePath = path.join(fedOptions.federationCache.cachePath,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
logger.measure(start, '[build artifacts] - To bundle all mappings and exposed.');
|
|
18
|
-
if (signal?.aborted)
|
|
19
|
-
throw new AbortedError('[buildForFederation] After exposed-and-mappings bundle');
|
|
20
|
-
const exposedInfo = !artifactInfo ? describeExposed(config, fedOptions) : artifactInfo.exposes;
|
|
21
|
-
// 3. Externals
|
|
11
|
+
// 1. Setup
|
|
12
|
+
fedOptions.federationCache.cachePath = path.join(fedOptions.federationCache.cachePath, fedOptions.projectName);
|
|
13
|
+
logger.info('Building federation artifacts');
|
|
14
|
+
logger.notice("Skip packages you don't want to share in your federation config");
|
|
15
|
+
// 2. Externals
|
|
22
16
|
if (fedOptions.federationCache.externals.length > 0) {
|
|
23
17
|
logger.info('Checksum matched, re-using cached externals.');
|
|
24
18
|
}
|
|
25
19
|
if (fedOptions.federationCache.externals.length === 0) {
|
|
26
20
|
const { sharedBrowser, sharedServer, separateBrowser, separateServer } = splitShared(config.shared);
|
|
27
21
|
if (Object.keys(sharedBrowser).length > 0) {
|
|
28
|
-
|
|
22
|
+
logger.info(`Bundling external npm packages with bundle type 'browser-shared'`);
|
|
29
23
|
const start = process.hrtime();
|
|
30
|
-
const sharedPackageInfoBrowser = await bundleShared(sharedBrowser, config, fedOptions, externals, { platform: 'browser', bundleName: 'browser-shared' });
|
|
31
|
-
logger.measure(start, '
|
|
24
|
+
const sharedPackageInfoBrowser = await bundleShared(sharedBrowser, config, fedOptions, externals, { platform: 'browser', bundleName: 'browser-shared', chunks: config.chunks });
|
|
25
|
+
logger.measure(start, 'Step 2.1) Bundling all shared browser externals');
|
|
32
26
|
addExternalsToCache(fedOptions.federationCache, sharedPackageInfoBrowser);
|
|
33
27
|
if (signal?.aborted)
|
|
34
28
|
throw new AbortedError('[buildForFederation] After shared-browser bundle');
|
|
35
29
|
}
|
|
36
30
|
if (Object.keys(sharedServer).length > 0) {
|
|
37
|
-
|
|
31
|
+
logger.info(`Bundling external npm packages with bundle type 'server-shared'`);
|
|
38
32
|
const start = process.hrtime();
|
|
39
|
-
const sharedPackageInfoServer = await bundleShared(sharedServer, config, fedOptions, externals, { platform: 'node', bundleName: 'node-shared' });
|
|
40
|
-
logger.measure(start, '
|
|
33
|
+
const sharedPackageInfoServer = await bundleShared(sharedServer, config, fedOptions, externals, { platform: 'node', bundleName: 'node-shared', chunks: config.chunks });
|
|
34
|
+
logger.measure(start, 'Step 2.1) Bundling all shared node externals');
|
|
41
35
|
addExternalsToCache(fedOptions.federationCache, sharedPackageInfoServer);
|
|
42
36
|
if (signal?.aborted)
|
|
43
37
|
throw new AbortedError('[buildForFederation] After shared-node bundle');
|
|
44
38
|
}
|
|
45
39
|
if (Object.keys(separateBrowser).length > 0) {
|
|
46
|
-
|
|
40
|
+
logger.info(`Bundling external npm packages with bundle type 'browser-separate'`);
|
|
47
41
|
const start = process.hrtime();
|
|
48
42
|
const separatePackageInfoBrowser = await bundleSeparatePackages(separateBrowser, externals, config, fedOptions, { platform: 'browser' });
|
|
49
|
-
logger.measure(start, '
|
|
43
|
+
logger.measure(start, 'Step 2.2) Bundling all separate browser external packages');
|
|
50
44
|
addExternalsToCache(fedOptions.federationCache, separatePackageInfoBrowser);
|
|
51
45
|
if (signal?.aborted)
|
|
52
46
|
throw new AbortedError('[buildForFederation] After separate-browser bundle');
|
|
53
47
|
}
|
|
54
48
|
if (Object.keys(separateServer).length > 0) {
|
|
55
|
-
|
|
49
|
+
logger.info(`Bundling external npm packages with bundle type 'node-separate'`);
|
|
56
50
|
const start = process.hrtime();
|
|
57
51
|
const separatePackageInfoServer = await bundleSeparatePackages(separateServer, externals, config, fedOptions, { platform: 'node' });
|
|
58
|
-
logger.measure(start, '
|
|
52
|
+
logger.measure(start, 'Step 2.2) Bundling all separate node external packages');
|
|
59
53
|
addExternalsToCache(fedOptions.federationCache, separatePackageInfoServer);
|
|
60
54
|
}
|
|
61
55
|
if (signal?.aborted)
|
|
62
56
|
throw new AbortedError('[buildForFederation] After separate-node bundle');
|
|
63
57
|
}
|
|
58
|
+
// 2. Shared mappings and exposed modules
|
|
59
|
+
const start = process.hrtime();
|
|
60
|
+
const artifactInfo = await bundleExposedAndMappings(config, fedOptions, externals, undefined, signal);
|
|
61
|
+
logger.measure(start, 'Step 3) Bundling all internal libraries and exposed modules.');
|
|
62
|
+
if (signal?.aborted)
|
|
63
|
+
throw new AbortedError('[buildForFederation] After exposed-and-mappings bundle');
|
|
64
|
+
const exposedInfo = !artifactInfo ? describeExposed(config, fedOptions) : artifactInfo.exposes;
|
|
64
65
|
const sharedMappingInfo = !artifactInfo
|
|
65
66
|
? describeSharedMappings(config, fedOptions)
|
|
66
67
|
: artifactInfo.mappings;
|
|
@@ -102,13 +103,17 @@ async function bundleSeparatePackages(separateBrowser, externals, config, fedOpt
|
|
|
102
103
|
for (const [key, shared] of Object.entries(separateBrowser)) {
|
|
103
104
|
const packageName = shared.build === 'separate' ? key : inferPackageFromSecondary(key);
|
|
104
105
|
if (!groupedByPackage[packageName]) {
|
|
105
|
-
groupedByPackage[packageName] = {
|
|
106
|
+
groupedByPackage[packageName] = {
|
|
107
|
+
chunks: shared.chunks,
|
|
108
|
+
entries: {},
|
|
109
|
+
};
|
|
106
110
|
}
|
|
107
|
-
groupedByPackage[packageName][key] = shared;
|
|
111
|
+
groupedByPackage[packageName].entries[key] = shared;
|
|
108
112
|
}
|
|
109
|
-
const bundlePromises = Object.entries(groupedByPackage).map(async ([packageName,
|
|
110
|
-
return bundleShared(
|
|
113
|
+
const bundlePromises = Object.entries(groupedByPackage).map(async ([packageName, packageConfig]) => {
|
|
114
|
+
return bundleShared(packageConfig.entries, config, fedOptions, externals.filter(e => !e.startsWith(packageName)), {
|
|
111
115
|
platform: buildOptions.platform,
|
|
116
|
+
chunks: packageConfig.chunks,
|
|
112
117
|
bundleName: `${buildOptions.platform}-${normalizePackageName(packageName)}`,
|
|
113
118
|
});
|
|
114
119
|
});
|
|
@@ -121,11 +126,6 @@ async function bundleSeparatePackages(separateBrowser, externals, config, fedOpt
|
|
|
121
126
|
return { externals: [...acc.externals, ...r.externals], chunks };
|
|
122
127
|
}, { externals: [] });
|
|
123
128
|
}
|
|
124
|
-
function notifyBundling(platform) {
|
|
125
|
-
logger.info('Preparing shared npm packages for the platform ' + platform);
|
|
126
|
-
logger.notice('This only needs to be done once, as results are cached');
|
|
127
|
-
logger.notice("Skip packages you don't want to share in your federation config");
|
|
128
|
-
}
|
|
129
129
|
function splitShared(shared) {
|
|
130
130
|
const sharedServer = {};
|
|
131
131
|
const sharedBrowser = {};
|
|
@@ -10,11 +10,12 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, mo
|
|
|
10
10
|
if (signal?.aborted) {
|
|
11
11
|
throw new AbortedError('[bundle-exposed-and-mappings] Aborted before bundling');
|
|
12
12
|
}
|
|
13
|
-
const shared = config.sharedMappings.map(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
const shared = Object.entries(config.sharedMappings).map(([entryPoint, mappedImport]) => {
|
|
14
|
+
return {
|
|
15
|
+
fileName: entryPoint,
|
|
16
|
+
outName: mappedImport.replace(/[^A-Za-z0-9]/g, '_') + '.js',
|
|
17
|
+
key: mappedImport,
|
|
18
|
+
};
|
|
18
19
|
});
|
|
19
20
|
const exposes = Object.entries(config.exposes).map(([key, entry]) => {
|
|
20
21
|
const outFilePath = key + '.js';
|
|
@@ -22,11 +23,10 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, mo
|
|
|
22
23
|
});
|
|
23
24
|
const entryPoints = [...shared, ...exposes];
|
|
24
25
|
const hash = !fedOptions.dev;
|
|
25
|
-
logger.info('Building federation artifacts');
|
|
26
26
|
let result;
|
|
27
27
|
try {
|
|
28
28
|
if (!modifiedFiles) {
|
|
29
|
-
await getBuildAdapter().setup({
|
|
29
|
+
await getBuildAdapter().setup('mapping-or-exposed', {
|
|
30
30
|
entryPoints,
|
|
31
31
|
outdir: fedOptions.outputPath,
|
|
32
32
|
tsConfigPath: fedOptions.tsConfig,
|
|
@@ -34,18 +34,16 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, mo
|
|
|
34
34
|
dev: !!fedOptions.dev,
|
|
35
35
|
watch: fedOptions.watch,
|
|
36
36
|
mappedPaths: config.sharedMappings,
|
|
37
|
-
|
|
38
|
-
chunks: (typeof fedOptions.chunks === 'boolean' && fedOptions.chunks) ||
|
|
39
|
-
(typeof fedOptions.chunks === 'object' && !!fedOptions.chunks.enable),
|
|
37
|
+
chunks: config.chunks,
|
|
40
38
|
hash,
|
|
41
39
|
optimizedMappings: config.features.ignoreUnusedDeps,
|
|
42
|
-
|
|
40
|
+
isMappingOrExposed: true,
|
|
43
41
|
cache: fedOptions.federationCache,
|
|
44
42
|
});
|
|
45
43
|
}
|
|
46
44
|
result = await getBuildAdapter().build('mapping-or-exposed', {
|
|
47
45
|
signal,
|
|
48
|
-
|
|
46
|
+
modifiedFiles,
|
|
49
47
|
});
|
|
50
48
|
if (signal?.aborted) {
|
|
51
49
|
throw new AbortedError('[bundle-exposed-and-mappings] Aborted after bundle');
|
|
@@ -99,7 +97,7 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, mo
|
|
|
99
97
|
.forEach(f => popFromResultMap(resultMap, f));
|
|
100
98
|
// Process remaining chunks and lazy loaded internal modules
|
|
101
99
|
let exportedChunks = undefined;
|
|
102
|
-
if (
|
|
100
|
+
if (config.chunks && config.features.denseChunking) {
|
|
103
101
|
for (const entryFile of entryFiles)
|
|
104
102
|
rewriteChunkImports(entryFile);
|
|
105
103
|
exportedChunks = {
|
|
@@ -126,18 +124,18 @@ export function describeExposed(config, options) {
|
|
|
126
124
|
}
|
|
127
125
|
export function describeSharedMappings(config, fedOptions) {
|
|
128
126
|
const result = [];
|
|
129
|
-
for (const
|
|
127
|
+
for (const [mappedPath, mappedImport] of Object.entries(config.sharedMappings)) {
|
|
130
128
|
result.push({
|
|
131
|
-
packageName:
|
|
129
|
+
packageName: mappedImport,
|
|
132
130
|
outFileName: '',
|
|
133
131
|
requiredVersion: '',
|
|
134
132
|
singleton: true,
|
|
135
133
|
strictVersion: false,
|
|
136
|
-
version: config.features.mappingVersion ? getMappingVersion(
|
|
134
|
+
version: config.features.mappingVersion ? getMappingVersion(mappedPath) : '',
|
|
137
135
|
dev: !fedOptions.dev
|
|
138
136
|
? undefined
|
|
139
137
|
: {
|
|
140
|
-
entryPoint: normalize(path.normalize(
|
|
138
|
+
entryPoint: normalize(path.normalize(mappedPath)),
|
|
141
139
|
},
|
|
142
140
|
});
|
|
143
141
|
}
|
|
@@ -5,6 +5,7 @@ import type { NormalizedExternalConfig } from '../domain/config/external-config.
|
|
|
5
5
|
export declare function bundleShared(sharedBundles: Record<string, NormalizedExternalConfig>, config: NormalizedFederationConfig, fedOptions: NormalizedFederationOptions, externals: string[], buildOptions: {
|
|
6
6
|
platform: 'browser' | 'node';
|
|
7
7
|
bundleName: string;
|
|
8
|
+
chunks: boolean;
|
|
8
9
|
}): Promise<{
|
|
9
10
|
externals: SharedInfo[];
|
|
10
11
|
chunks?: Record<string, string[]>;
|
|
@@ -53,18 +53,16 @@ export async function bundleShared(sharedBundles, config, fedOptions, externals,
|
|
|
53
53
|
const additionalExternals = useDefaultExternalList ? DEFAULT_EXTERNAL_LIST : [];
|
|
54
54
|
let bundleResult = null;
|
|
55
55
|
try {
|
|
56
|
-
await getBuildAdapter().setup({
|
|
56
|
+
await getBuildAdapter().setup(buildOptions.bundleName, {
|
|
57
57
|
entryPoints,
|
|
58
58
|
tsConfigPath: fedOptions.tsConfig,
|
|
59
59
|
external: [...additionalExternals, ...externals],
|
|
60
60
|
outdir: fedOptions.federationCache.cachePath,
|
|
61
61
|
mappedPaths: config.sharedMappings,
|
|
62
62
|
dev: fedOptions.dev,
|
|
63
|
-
|
|
64
|
-
isNodeModules: true,
|
|
63
|
+
isMappingOrExposed: false,
|
|
65
64
|
hash: false,
|
|
66
|
-
chunks:
|
|
67
|
-
(typeof fedOptions.chunks === 'object' && !!fedOptions.chunks.enable),
|
|
65
|
+
chunks: buildOptions.chunks,
|
|
68
66
|
platform: buildOptions.platform,
|
|
69
67
|
optimizedMappings: config.features.ignoreUnusedDeps,
|
|
70
68
|
cache: fedOptions.federationCache,
|
|
@@ -102,11 +100,13 @@ export async function bundleShared(sharedBundles, config, fedOptions, externals,
|
|
|
102
100
|
* Chunking
|
|
103
101
|
*/
|
|
104
102
|
let exportedChunks = undefined;
|
|
105
|
-
if (
|
|
103
|
+
if (buildOptions.chunks && config.features.denseChunking) {
|
|
106
104
|
result.forEach(external => {
|
|
107
105
|
external.bundle = buildOptions.bundleName;
|
|
108
106
|
});
|
|
109
|
-
|
|
107
|
+
if (chunks.length > 0) {
|
|
108
|
+
exportedChunks = { [buildOptions.bundleName]: getChunkFileNames(chunks) };
|
|
109
|
+
}
|
|
110
110
|
}
|
|
111
111
|
else {
|
|
112
112
|
addChunksToResult(chunks, result);
|
|
@@ -115,6 +115,7 @@ export async function bundleShared(sharedBundles, config, fedOptions, externals,
|
|
|
115
115
|
checksum,
|
|
116
116
|
externals: result,
|
|
117
117
|
files: bundleResult.map(r => r.fileName.split(path.sep).pop() ?? r.fileName),
|
|
118
|
+
chunks: exportedChunks,
|
|
118
119
|
});
|
|
119
120
|
bundleCache.copyFiles(path.join(fedOptions.workspaceRoot, fedOptions.outputPath));
|
|
120
121
|
return { externals: result, chunks: exportedChunks };
|
|
@@ -7,10 +7,15 @@ export interface BuildHelperParams {
|
|
|
7
7
|
adapter: NFBuildAdapter;
|
|
8
8
|
}
|
|
9
9
|
declare function init(params: BuildHelperParams): Promise<void>;
|
|
10
|
-
declare function build(
|
|
10
|
+
declare function build(opts?: {
|
|
11
|
+
modifiedFiles?: string[];
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
declare function close(): Promise<void>;
|
|
11
15
|
export declare const federationBuilder: {
|
|
12
16
|
init: typeof init;
|
|
13
17
|
build: typeof build;
|
|
18
|
+
close: typeof close;
|
|
14
19
|
readonly federationInfo: FederationInfo;
|
|
15
20
|
readonly externals: string[];
|
|
16
21
|
readonly config: NormalizedFederationConfig;
|
|
@@ -1,28 +1,38 @@
|
|
|
1
1
|
import { getConfigContext, usePackageJson, useWorkspace } from '../config/configuration-context.js';
|
|
2
|
-
import { setBuildAdapter } from './build-adapter.js';
|
|
2
|
+
import { getBuildAdapter, setBuildAdapter } from './build-adapter.js';
|
|
3
3
|
import { buildForFederation } from './build-for-federation.js';
|
|
4
4
|
import { getExternals } from './get-externals.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { normalizeFederationOptions } from './normalize-options.js';
|
|
6
|
+
import { rebuildForFederation } from './rebuild-for-federation.js';
|
|
7
7
|
let externals = [];
|
|
8
8
|
let config;
|
|
9
|
-
let
|
|
9
|
+
let options;
|
|
10
10
|
let fedInfo;
|
|
11
11
|
async function init(params) {
|
|
12
12
|
setBuildAdapter(params.adapter);
|
|
13
|
-
fedOptions = normalizeFederationOptions(params.options);
|
|
14
13
|
useWorkspace(params.options.workspaceRoot);
|
|
15
14
|
usePackageJson(params.options.packageJson);
|
|
16
|
-
config = await loadFederationConfig(fedOptions);
|
|
17
15
|
params.options.workspaceRoot = getConfigContext().workspaceRoot ?? params.options.workspaceRoot;
|
|
16
|
+
const normalized = await normalizeFederationOptions(params.options);
|
|
17
|
+
options = normalized.options;
|
|
18
|
+
config = normalized.config;
|
|
18
19
|
externals = getExternals(config);
|
|
19
20
|
}
|
|
20
|
-
async function build(
|
|
21
|
-
|
|
21
|
+
async function build(opts = {}) {
|
|
22
|
+
if (!fedInfo) {
|
|
23
|
+
fedInfo = await buildForFederation(config, options, externals, opts.signal);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
fedInfo = await rebuildForFederation(config, options, externals, opts.modifiedFiles ?? [], opts.signal);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function close() {
|
|
30
|
+
return getBuildAdapter().dispose();
|
|
22
31
|
}
|
|
23
32
|
export const federationBuilder = {
|
|
24
33
|
init,
|
|
25
34
|
build,
|
|
35
|
+
close,
|
|
26
36
|
get federationInfo() {
|
|
27
37
|
return fedInfo;
|
|
28
38
|
},
|