@softarc/native-federation 4.0.0-RC8 → 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 +2 -1
- 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 +21 -22
- package/src/lib/core/bundle-exposed-and-mappings.js +15 -16
- 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/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,7 +2,7 @@ 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 {
|
|
5
|
+
export type { PathToImport } from './lib/domain/utils/mapped-path.contract.js';
|
|
6
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';
|
|
@@ -10,3 +10,4 @@ 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,13 +5,13 @@ 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
11
|
// 1. Setup
|
|
13
|
-
fedOptions.federationCache.cachePath = path.join(fedOptions.federationCache.cachePath,
|
|
12
|
+
fedOptions.federationCache.cachePath = path.join(fedOptions.federationCache.cachePath, fedOptions.projectName);
|
|
14
13
|
logger.info('Building federation artifacts');
|
|
14
|
+
logger.notice("Skip packages you don't want to share in your federation config");
|
|
15
15
|
// 2. Externals
|
|
16
16
|
if (fedOptions.federationCache.externals.length > 0) {
|
|
17
17
|
logger.info('Checksum matched, re-using cached externals.');
|
|
@@ -19,37 +19,37 @@ export async function buildForFederation(config, fedOptions, externals, signal)
|
|
|
19
19
|
if (fedOptions.federationCache.externals.length === 0) {
|
|
20
20
|
const { sharedBrowser, sharedServer, separateBrowser, separateServer } = splitShared(config.shared);
|
|
21
21
|
if (Object.keys(sharedBrowser).length > 0) {
|
|
22
|
-
|
|
22
|
+
logger.info(`Bundling external npm packages with bundle type 'browser-shared'`);
|
|
23
23
|
const start = process.hrtime();
|
|
24
|
-
const sharedPackageInfoBrowser = await bundleShared(sharedBrowser, config, fedOptions, externals, { platform: 'browser', bundleName: 'browser-shared' });
|
|
25
|
-
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');
|
|
26
26
|
addExternalsToCache(fedOptions.federationCache, sharedPackageInfoBrowser);
|
|
27
27
|
if (signal?.aborted)
|
|
28
28
|
throw new AbortedError('[buildForFederation] After shared-browser bundle');
|
|
29
29
|
}
|
|
30
30
|
if (Object.keys(sharedServer).length > 0) {
|
|
31
|
-
|
|
31
|
+
logger.info(`Bundling external npm packages with bundle type 'server-shared'`);
|
|
32
32
|
const start = process.hrtime();
|
|
33
|
-
const sharedPackageInfoServer = await bundleShared(sharedServer, config, fedOptions, externals, { platform: 'node', bundleName: 'node-shared' });
|
|
34
|
-
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');
|
|
35
35
|
addExternalsToCache(fedOptions.federationCache, sharedPackageInfoServer);
|
|
36
36
|
if (signal?.aborted)
|
|
37
37
|
throw new AbortedError('[buildForFederation] After shared-node bundle');
|
|
38
38
|
}
|
|
39
39
|
if (Object.keys(separateBrowser).length > 0) {
|
|
40
|
-
|
|
40
|
+
logger.info(`Bundling external npm packages with bundle type 'browser-separate'`);
|
|
41
41
|
const start = process.hrtime();
|
|
42
42
|
const separatePackageInfoBrowser = await bundleSeparatePackages(separateBrowser, externals, config, fedOptions, { platform: 'browser' });
|
|
43
|
-
logger.measure(start, '
|
|
43
|
+
logger.measure(start, 'Step 2.2) Bundling all separate browser external packages');
|
|
44
44
|
addExternalsToCache(fedOptions.federationCache, separatePackageInfoBrowser);
|
|
45
45
|
if (signal?.aborted)
|
|
46
46
|
throw new AbortedError('[buildForFederation] After separate-browser bundle');
|
|
47
47
|
}
|
|
48
48
|
if (Object.keys(separateServer).length > 0) {
|
|
49
|
-
|
|
49
|
+
logger.info(`Bundling external npm packages with bundle type 'node-separate'`);
|
|
50
50
|
const start = process.hrtime();
|
|
51
51
|
const separatePackageInfoServer = await bundleSeparatePackages(separateServer, externals, config, fedOptions, { platform: 'node' });
|
|
52
|
-
logger.measure(start, '
|
|
52
|
+
logger.measure(start, 'Step 2.2) Bundling all separate node external packages');
|
|
53
53
|
addExternalsToCache(fedOptions.federationCache, separatePackageInfoServer);
|
|
54
54
|
}
|
|
55
55
|
if (signal?.aborted)
|
|
@@ -58,7 +58,7 @@ export async function buildForFederation(config, fedOptions, externals, signal)
|
|
|
58
58
|
// 2. Shared mappings and exposed modules
|
|
59
59
|
const start = process.hrtime();
|
|
60
60
|
const artifactInfo = await bundleExposedAndMappings(config, fedOptions, externals, undefined, signal);
|
|
61
|
-
logger.measure(start, '
|
|
61
|
+
logger.measure(start, 'Step 3) Bundling all internal libraries and exposed modules.');
|
|
62
62
|
if (signal?.aborted)
|
|
63
63
|
throw new AbortedError('[buildForFederation] After exposed-and-mappings bundle');
|
|
64
64
|
const exposedInfo = !artifactInfo ? describeExposed(config, fedOptions) : artifactInfo.exposes;
|
|
@@ -103,13 +103,17 @@ async function bundleSeparatePackages(separateBrowser, externals, config, fedOpt
|
|
|
103
103
|
for (const [key, shared] of Object.entries(separateBrowser)) {
|
|
104
104
|
const packageName = shared.build === 'separate' ? key : inferPackageFromSecondary(key);
|
|
105
105
|
if (!groupedByPackage[packageName]) {
|
|
106
|
-
groupedByPackage[packageName] = {
|
|
106
|
+
groupedByPackage[packageName] = {
|
|
107
|
+
chunks: shared.chunks,
|
|
108
|
+
entries: {},
|
|
109
|
+
};
|
|
107
110
|
}
|
|
108
|
-
groupedByPackage[packageName][key] = shared;
|
|
111
|
+
groupedByPackage[packageName].entries[key] = shared;
|
|
109
112
|
}
|
|
110
|
-
const bundlePromises = Object.entries(groupedByPackage).map(async ([packageName,
|
|
111
|
-
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)), {
|
|
112
115
|
platform: buildOptions.platform,
|
|
116
|
+
chunks: packageConfig.chunks,
|
|
113
117
|
bundleName: `${buildOptions.platform}-${normalizePackageName(packageName)}`,
|
|
114
118
|
});
|
|
115
119
|
});
|
|
@@ -122,11 +126,6 @@ async function bundleSeparatePackages(separateBrowser, externals, config, fedOpt
|
|
|
122
126
|
return { externals: [...acc.externals, ...r.externals], chunks };
|
|
123
127
|
}, { externals: [] });
|
|
124
128
|
}
|
|
125
|
-
function notifyBundling(platform) {
|
|
126
|
-
logger.info('Preparing shared npm packages for the platform ' + platform);
|
|
127
|
-
logger.notice('This only needs to be done once, as results are cached');
|
|
128
|
-
logger.notice("Skip packages you don't want to share in your federation config");
|
|
129
|
-
}
|
|
130
129
|
function splitShared(shared) {
|
|
131
130
|
const sharedServer = {};
|
|
132
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';
|
|
@@ -25,7 +26,7 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, mo
|
|
|
25
26
|
let result;
|
|
26
27
|
try {
|
|
27
28
|
if (!modifiedFiles) {
|
|
28
|
-
await getBuildAdapter().setup({
|
|
29
|
+
await getBuildAdapter().setup('mapping-or-exposed', {
|
|
29
30
|
entryPoints,
|
|
30
31
|
outdir: fedOptions.outputPath,
|
|
31
32
|
tsConfigPath: fedOptions.tsConfig,
|
|
@@ -33,18 +34,16 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, mo
|
|
|
33
34
|
dev: !!fedOptions.dev,
|
|
34
35
|
watch: fedOptions.watch,
|
|
35
36
|
mappedPaths: config.sharedMappings,
|
|
36
|
-
|
|
37
|
-
chunks: (typeof fedOptions.chunks === 'boolean' && fedOptions.chunks) ||
|
|
38
|
-
(typeof fedOptions.chunks === 'object' && !!fedOptions.chunks.enable),
|
|
37
|
+
chunks: config.chunks,
|
|
39
38
|
hash,
|
|
40
39
|
optimizedMappings: config.features.ignoreUnusedDeps,
|
|
41
|
-
|
|
40
|
+
isMappingOrExposed: true,
|
|
42
41
|
cache: fedOptions.federationCache,
|
|
43
42
|
});
|
|
44
43
|
}
|
|
45
44
|
result = await getBuildAdapter().build('mapping-or-exposed', {
|
|
46
45
|
signal,
|
|
47
|
-
|
|
46
|
+
modifiedFiles,
|
|
48
47
|
});
|
|
49
48
|
if (signal?.aborted) {
|
|
50
49
|
throw new AbortedError('[bundle-exposed-and-mappings] Aborted after bundle');
|
|
@@ -98,7 +97,7 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, mo
|
|
|
98
97
|
.forEach(f => popFromResultMap(resultMap, f));
|
|
99
98
|
// Process remaining chunks and lazy loaded internal modules
|
|
100
99
|
let exportedChunks = undefined;
|
|
101
|
-
if (
|
|
100
|
+
if (config.chunks && config.features.denseChunking) {
|
|
102
101
|
for (const entryFile of entryFiles)
|
|
103
102
|
rewriteChunkImports(entryFile);
|
|
104
103
|
exportedChunks = {
|
|
@@ -125,18 +124,18 @@ export function describeExposed(config, options) {
|
|
|
125
124
|
}
|
|
126
125
|
export function describeSharedMappings(config, fedOptions) {
|
|
127
126
|
const result = [];
|
|
128
|
-
for (const
|
|
127
|
+
for (const [mappedPath, mappedImport] of Object.entries(config.sharedMappings)) {
|
|
129
128
|
result.push({
|
|
130
|
-
packageName:
|
|
129
|
+
packageName: mappedImport,
|
|
131
130
|
outFileName: '',
|
|
132
131
|
requiredVersion: '',
|
|
133
132
|
singleton: true,
|
|
134
133
|
strictVersion: false,
|
|
135
|
-
version: config.features.mappingVersion ? getMappingVersion(
|
|
134
|
+
version: config.features.mappingVersion ? getMappingVersion(mappedPath) : '',
|
|
136
135
|
dev: !fedOptions.dev
|
|
137
136
|
? undefined
|
|
138
137
|
: {
|
|
139
|
-
entryPoint: normalize(path.normalize(
|
|
138
|
+
entryPoint: normalize(path.normalize(mappedPath)),
|
|
140
139
|
},
|
|
141
140
|
});
|
|
142
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
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export function getExternals(config) {
|
|
2
2
|
const shared = Object.keys(config.shared);
|
|
3
|
-
const sharedMappings = config.sharedMappings
|
|
3
|
+
const sharedMappings = Object.values(config.sharedMappings);
|
|
4
4
|
const externals = [...shared, ...sharedMappings, ...config.externals];
|
|
5
5
|
return externals;
|
|
6
6
|
}
|