@softarc/native-federation 4.0.0-RC5 → 4.0.0-RC6
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 +3 -0
- package/src/index.js +3 -0
- package/src/internal.d.ts +1 -0
- package/src/internal.js +1 -0
- package/src/lib/core/build-adapter.js +5 -5
- package/src/lib/core/build-for-federation.d.ts +2 -4
- package/src/lib/core/build-for-federation.js +31 -42
- package/src/lib/core/bundle-exposed-and-mappings.d.ts +4 -4
- package/src/lib/core/bundle-exposed-and-mappings.js +22 -15
- package/src/lib/core/bundle-shared.d.ts +3 -3
- package/src/lib/core/bundle-shared.js +15 -11
- package/src/lib/core/default-external-list.js +1 -4
- package/src/lib/core/federation-builder.d.ts +1 -1
- package/src/lib/core/federation-builder.js +5 -4
- package/src/lib/core/federation-cache.d.ts +8 -0
- package/src/lib/core/federation-cache.js +11 -0
- package/src/lib/core/normalize-federation-options.d.ts +4 -0
- package/src/lib/core/normalize-federation-options.js +10 -0
- package/src/lib/core/rebuild-for-federation.d.ts +4 -0
- package/src/lib/core/rebuild-for-federation.js +37 -0
- package/src/lib/domain/core/build-adapter.contract.d.ts +14 -8
- package/src/lib/domain/core/federation-cache.contract.d.ts +7 -0
- package/src/lib/domain/core/federation-options.contract.d.ts +4 -0
- package/src/lib/domain/core/index.d.ts +3 -3
- package/src/lib/utils/{bundle-caching.d.ts → cache-persistence.d.ts} +1 -1
- package/src/lib/utils/{bundle-caching.js → cache-persistence.js} +2 -2
- package/src/lib/utils/resolve-glob.js +4 -4
- package/src/lib/domain/core/build-params.contract.d.ts +0 -5
- package/src/lib/utils/build-utils.d.ts +0 -2
- package/src/lib/utils/build-utils.js +0 -5
- /package/src/lib/domain/core/{build-params.contract.js → federation-cache.contract.js} +0 -0
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { setBuildAdapter } from './lib/core/build-adapter.js';
|
|
2
2
|
export { buildForFederation } from './lib/core/build-for-federation.js';
|
|
3
|
+
export { rebuildForFederation } from './lib/core/rebuild-for-federation.js';
|
|
4
|
+
export { normalizeFederationOptions } from './lib/core/normalize-federation-options.js';
|
|
5
|
+
export { createFederationCache } from './lib/core/federation-cache.js';
|
|
3
6
|
export { bundleExposedAndMappings } from './lib/core/bundle-exposed-and-mappings.js';
|
|
4
7
|
export { getExternals } from './lib/core/get-externals.js';
|
|
5
8
|
export { loadFederationConfig } from './lib/core/load-federation-config.js';
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { setBuildAdapter } from './lib/core/build-adapter.js';
|
|
2
2
|
export { buildForFederation } from './lib/core/build-for-federation.js';
|
|
3
|
+
export { rebuildForFederation } from './lib/core/rebuild-for-federation.js';
|
|
4
|
+
export { normalizeFederationOptions } from './lib/core/normalize-federation-options.js';
|
|
5
|
+
export { createFederationCache } from './lib/core/federation-cache.js';
|
|
3
6
|
export { bundleExposedAndMappings } from './lib/core/bundle-exposed-and-mappings.js';
|
|
4
7
|
export { getExternals } from './lib/core/get-externals.js';
|
|
5
8
|
export { loadFederationConfig } from './lib/core/load-federation-config.js';
|
package/src/internal.d.ts
CHANGED
|
@@ -9,3 +9,4 @@ export { createBuildResultMap, lookupInResultMap, popFromResultMap, } from './li
|
|
|
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
|
+
export { getDefaultCachePath, getChecksum } from './lib/utils/cache-persistence.js';
|
package/src/internal.js
CHANGED
|
@@ -6,3 +6,4 @@ export { RebuildQueue } from './lib/utils/rebuild-queue.js';
|
|
|
6
6
|
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
|
+
export { getDefaultCachePath, getChecksum } from './lib/utils/cache-persistence.js';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { logger } from '../utils/logger.js';
|
|
2
|
-
let _buildAdapter =
|
|
3
|
-
// TODO: add logger
|
|
4
|
-
logger.error('NF is missing a build adapter!');
|
|
5
|
-
return [];
|
|
6
|
-
};
|
|
2
|
+
let _buildAdapter = null;
|
|
7
3
|
export function setBuildAdapter(buildAdapter) {
|
|
8
4
|
_buildAdapter = buildAdapter;
|
|
9
5
|
}
|
|
10
6
|
export function getBuildAdapter() {
|
|
7
|
+
if (!_buildAdapter) {
|
|
8
|
+
logger.error('Please set a BuildAdapter!');
|
|
9
|
+
throw new Error('BuildAdapter not set');
|
|
10
|
+
}
|
|
11
11
|
return _buildAdapter;
|
|
12
12
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { FederationInfo } from '../domain/core/federation-info.contract.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { NormalizedFederationOptions } from '../domain/core/federation-options.contract.js';
|
|
3
3
|
import type { NormalizedFederationConfig } from '../domain/config/federation-config.contract.js';
|
|
4
|
-
|
|
5
|
-
export declare const defaultBuildParams: BuildParams;
|
|
6
|
-
export declare function buildForFederation(config: NormalizedFederationConfig, fedOptions: FederationOptions, externals: string[], buildParams?: BuildParams): Promise<FederationInfo>;
|
|
4
|
+
export declare function buildForFederation(config: NormalizedFederationConfig, fedOptions: NormalizedFederationOptions, externals: string[], signal?: AbortSignal): Promise<FederationInfo>;
|
|
@@ -3,66 +3,60 @@ import { bundleShared } from './bundle-shared.js';
|
|
|
3
3
|
import { writeFederationInfo } from './write-federation-info.js';
|
|
4
4
|
import { writeImportMap } from './write-import-map.js';
|
|
5
5
|
import { logger } from '../utils/logger.js';
|
|
6
|
-
import { getCachePath } from './../utils/bundle-caching.js';
|
|
7
6
|
import { normalizePackageName } from '../utils/normalize.js';
|
|
8
7
|
import { AbortedError } from '../utils/errors.js';
|
|
9
8
|
import { resolveProjectName } from '../utils/config-utils.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
logger.measure(start, '[build artifacts] - To bundle all mappings and exposed.');
|
|
22
|
-
if (signal?.aborted)
|
|
23
|
-
throw new AbortedError('[buildForFederation] After exposed-and-mappings bundle');
|
|
24
|
-
}
|
|
9
|
+
import { addExternalsToCache } from './federation-cache.js';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
export async function buildForFederation(config, fedOptions, externals, signal) {
|
|
12
|
+
// 1. Caching
|
|
13
|
+
fedOptions.federationCache.cachePath = path.join(fedOptions.federationCache.cachePath, resolveProjectName(config));
|
|
14
|
+
const start = process.hrtime();
|
|
15
|
+
// 2. Shared mappings and exposed modules
|
|
16
|
+
const artifactInfo = await bundleExposedAndMappings(config, fedOptions, externals, undefined, signal);
|
|
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');
|
|
25
20
|
const exposedInfo = !artifactInfo ? describeExposed(config, fedOptions) : artifactInfo.exposes;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (!buildParams.skipShared && sharedCache.externals.length > 0) {
|
|
21
|
+
// 3. Externals
|
|
22
|
+
if (fedOptions.federationCache.externals.length > 0) {
|
|
29
23
|
logger.info('Checksum matched, re-using cached externals.');
|
|
30
24
|
}
|
|
31
|
-
if (
|
|
25
|
+
if (fedOptions.federationCache.externals.length === 0) {
|
|
32
26
|
const { sharedBrowser, sharedServer, separateBrowser, separateServer } = splitShared(config.shared);
|
|
33
27
|
if (Object.keys(sharedBrowser).length > 0) {
|
|
34
28
|
notifyBundling('browser-shared');
|
|
35
29
|
const start = process.hrtime();
|
|
36
|
-
const sharedPackageInfoBrowser = await bundleShared(sharedBrowser, config, fedOptions, externals, 'browser',
|
|
30
|
+
const sharedPackageInfoBrowser = await bundleShared(sharedBrowser, config, fedOptions, externals, { platform: 'browser', bundleName: 'browser-shared' });
|
|
37
31
|
logger.measure(start, '[build artifacts] - To bundle all shared browser externals');
|
|
38
|
-
|
|
32
|
+
addExternalsToCache(fedOptions.federationCache, sharedPackageInfoBrowser);
|
|
39
33
|
if (signal?.aborted)
|
|
40
34
|
throw new AbortedError('[buildForFederation] After shared-browser bundle');
|
|
41
35
|
}
|
|
42
36
|
if (Object.keys(sharedServer).length > 0) {
|
|
43
37
|
notifyBundling('browser-shared');
|
|
44
38
|
const start = process.hrtime();
|
|
45
|
-
const sharedPackageInfoServer = await bundleShared(sharedServer, config, fedOptions, externals, 'node',
|
|
39
|
+
const sharedPackageInfoServer = await bundleShared(sharedServer, config, fedOptions, externals, { platform: 'node', bundleName: 'node-shared' });
|
|
46
40
|
logger.measure(start, '[build artifacts] - To bundle all shared node externals');
|
|
47
|
-
|
|
41
|
+
addExternalsToCache(fedOptions.federationCache, sharedPackageInfoServer);
|
|
48
42
|
if (signal?.aborted)
|
|
49
43
|
throw new AbortedError('[buildForFederation] After shared-node bundle');
|
|
50
44
|
}
|
|
51
45
|
if (Object.keys(separateBrowser).length > 0) {
|
|
52
46
|
notifyBundling('browser-shared');
|
|
53
47
|
const start = process.hrtime();
|
|
54
|
-
const separatePackageInfoBrowser = await bundleSeparatePackages(separateBrowser, externals, config, fedOptions, 'browser'
|
|
48
|
+
const separatePackageInfoBrowser = await bundleSeparatePackages(separateBrowser, externals, config, fedOptions, { platform: 'browser' });
|
|
55
49
|
logger.measure(start, '[build artifacts] - To bundle all separate browser externals');
|
|
56
|
-
|
|
50
|
+
addExternalsToCache(fedOptions.federationCache, separatePackageInfoBrowser);
|
|
57
51
|
if (signal?.aborted)
|
|
58
52
|
throw new AbortedError('[buildForFederation] After separate-browser bundle');
|
|
59
53
|
}
|
|
60
54
|
if (Object.keys(separateServer).length > 0) {
|
|
61
55
|
notifyBundling('browser-shared');
|
|
62
56
|
const start = process.hrtime();
|
|
63
|
-
const separatePackageInfoServer = await bundleSeparatePackages(separateServer, externals, config, fedOptions, 'node'
|
|
57
|
+
const separatePackageInfoServer = await bundleSeparatePackages(separateServer, externals, config, fedOptions, { platform: 'node' });
|
|
64
58
|
logger.measure(start, '[build artifacts] - To bundle all separate node externals');
|
|
65
|
-
|
|
59
|
+
addExternalsToCache(fedOptions.federationCache, separatePackageInfoServer);
|
|
66
60
|
}
|
|
67
61
|
if (signal?.aborted)
|
|
68
62
|
throw new AbortedError('[buildForFederation] After separate-node bundle');
|
|
@@ -70,7 +64,7 @@ export async function buildForFederation(config, fedOptions, externals, buildPar
|
|
|
70
64
|
const sharedMappingInfo = !artifactInfo
|
|
71
65
|
? describeSharedMappings(config, fedOptions)
|
|
72
66
|
: artifactInfo.mappings;
|
|
73
|
-
const sharedExternals = [...
|
|
67
|
+
const sharedExternals = [...fedOptions.federationCache.externals, ...sharedMappingInfo];
|
|
74
68
|
if (config?.shareScope) {
|
|
75
69
|
Object.values(sharedExternals).forEach(external => {
|
|
76
70
|
if (!external.shareScope)
|
|
@@ -86,24 +80,16 @@ export async function buildForFederation(config, fedOptions, externals, buildPar
|
|
|
86
80
|
exposes: exposedInfo,
|
|
87
81
|
buildNotificationsEndpoint,
|
|
88
82
|
};
|
|
89
|
-
if (
|
|
90
|
-
federationInfo.chunks =
|
|
83
|
+
if (fedOptions.federationCache.chunks) {
|
|
84
|
+
federationInfo.chunks = fedOptions.federationCache.chunks;
|
|
91
85
|
}
|
|
92
86
|
if (artifactInfo?.chunks) {
|
|
93
87
|
federationInfo.chunks = { ...(federationInfo.chunks ?? {}), ...artifactInfo?.chunks };
|
|
94
88
|
}
|
|
95
89
|
writeFederationInfo(federationInfo, fedOptions);
|
|
96
|
-
writeImportMap(
|
|
90
|
+
writeImportMap(fedOptions.federationCache, fedOptions);
|
|
97
91
|
return federationInfo;
|
|
98
92
|
}
|
|
99
|
-
function addToCache({ externals, chunks }) {
|
|
100
|
-
sharedCache.externals.push(...externals);
|
|
101
|
-
if (chunks) {
|
|
102
|
-
if (!sharedCache.chunks)
|
|
103
|
-
sharedCache.chunks = {};
|
|
104
|
-
sharedCache.chunks = { ...sharedCache.chunks, ...chunks };
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
93
|
function inferPackageFromSecondary(secondary) {
|
|
108
94
|
const parts = secondary.split('/');
|
|
109
95
|
if (secondary.startsWith('@') && parts.length >= 2) {
|
|
@@ -111,7 +97,7 @@ function inferPackageFromSecondary(secondary) {
|
|
|
111
97
|
}
|
|
112
98
|
return parts[0];
|
|
113
99
|
}
|
|
114
|
-
async function bundleSeparatePackages(separateBrowser, externals, config, fedOptions,
|
|
100
|
+
async function bundleSeparatePackages(separateBrowser, externals, config, fedOptions, buildOptions) {
|
|
115
101
|
const groupedByPackage = {};
|
|
116
102
|
for (const [key, shared] of Object.entries(separateBrowser)) {
|
|
117
103
|
const packageName = shared.build === 'separate' ? key : inferPackageFromSecondary(key);
|
|
@@ -121,7 +107,10 @@ async function bundleSeparatePackages(separateBrowser, externals, config, fedOpt
|
|
|
121
107
|
groupedByPackage[packageName][key] = shared;
|
|
122
108
|
}
|
|
123
109
|
const bundlePromises = Object.entries(groupedByPackage).map(async ([packageName, sharedGroup]) => {
|
|
124
|
-
return bundleShared(sharedGroup, config, fedOptions, externals.filter(e => !e.startsWith(packageName)),
|
|
110
|
+
return bundleShared(sharedGroup, config, fedOptions, externals.filter(e => !e.startsWith(packageName)), {
|
|
111
|
+
platform: buildOptions.platform,
|
|
112
|
+
bundleName: `${buildOptions.platform}-${normalizePackageName(packageName)}`,
|
|
113
|
+
});
|
|
125
114
|
});
|
|
126
115
|
const buildResults = await Promise.all(bundlePromises);
|
|
127
116
|
return buildResults.reduce((acc, r) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ArtifactInfo, ExposesInfo, SharedInfo } from '../domain/core/federation-info.contract.js';
|
|
2
2
|
import type { NormalizedFederationConfig } from '../domain/config/federation-config.contract.js';
|
|
3
|
-
import { type
|
|
4
|
-
export declare function bundleExposedAndMappings(config: NormalizedFederationConfig, fedOptions:
|
|
5
|
-
export declare function describeExposed(config: NormalizedFederationConfig, options:
|
|
6
|
-
export declare function describeSharedMappings(config: NormalizedFederationConfig, fedOptions:
|
|
3
|
+
import { type NormalizedFederationOptions } from '../domain/core/federation-options.contract.js';
|
|
4
|
+
export declare function bundleExposedAndMappings(config: NormalizedFederationConfig, fedOptions: NormalizedFederationOptions, externals: string[], modifiedFiles?: string[], signal?: AbortSignal): Promise<ArtifactInfo>;
|
|
5
|
+
export declare function describeExposed(config: NormalizedFederationConfig, options: NormalizedFederationOptions): Array<ExposesInfo>;
|
|
6
|
+
export declare function describeSharedMappings(config: NormalizedFederationConfig, fedOptions: NormalizedFederationOptions): Array<SharedInfo>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { createBuildResultMap, popFromResultMap } from '../utils/build-result-map.js';
|
|
4
|
-
import { bundle } from '../utils/build-utils.js';
|
|
5
4
|
import { logger } from '../utils/logger.js';
|
|
6
5
|
import { normalize } from '../utils/normalize.js';
|
|
7
6
|
import { AbortedError } from '../utils/errors.js';
|
|
8
7
|
import { rewriteChunkImports } from '../utils/rewrite-chunk-imports.js';
|
|
9
|
-
|
|
8
|
+
import { getBuildAdapter } from './build-adapter.js';
|
|
9
|
+
export async function bundleExposedAndMappings(config, fedOptions, externals, modifiedFiles, signal) {
|
|
10
10
|
if (signal?.aborted) {
|
|
11
11
|
throw new AbortedError('[bundle-exposed-and-mappings] Aborted before bundling');
|
|
12
12
|
}
|
|
@@ -25,20 +25,27 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, si
|
|
|
25
25
|
logger.info('Building federation artifacts');
|
|
26
26
|
let result;
|
|
27
27
|
try {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
(typeof fedOptions.chunks === '
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
if (!modifiedFiles) {
|
|
29
|
+
await getBuildAdapter().setup({
|
|
30
|
+
entryPoints,
|
|
31
|
+
outdir: fedOptions.outputPath,
|
|
32
|
+
tsConfigPath: fedOptions.tsConfig,
|
|
33
|
+
external: externals,
|
|
34
|
+
dev: !!fedOptions.dev,
|
|
35
|
+
watch: fedOptions.watch,
|
|
36
|
+
mappedPaths: config.sharedMappings,
|
|
37
|
+
bundleName: 'mapping-or-exposed',
|
|
38
|
+
chunks: (typeof fedOptions.chunks === 'boolean' && fedOptions.chunks) ||
|
|
39
|
+
(typeof fedOptions.chunks === 'object' && !!fedOptions.chunks.enable),
|
|
40
|
+
hash,
|
|
41
|
+
optimizedMappings: config.features.ignoreUnusedDeps,
|
|
42
|
+
isNodeModules: false,
|
|
43
|
+
cache: fedOptions.federationCache,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
result = await getBuildAdapter().build('mapping-or-exposed', {
|
|
41
47
|
signal,
|
|
48
|
+
files: modifiedFiles,
|
|
42
49
|
});
|
|
43
50
|
if (signal?.aborted) {
|
|
44
51
|
throw new AbortedError('[bundle-exposed-and-mappings] Aborted after bundle');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { NormalizedFederationConfig } from '../domain/config/federation-config.contract.js';
|
|
2
2
|
import type { SharedInfo } from '../domain/core/federation-info.contract.js';
|
|
3
|
-
import { type
|
|
3
|
+
import { type NormalizedFederationOptions } from '../domain/core/federation-options.contract.js';
|
|
4
4
|
import type { NormalizedExternalConfig } from '../domain/config/external-config.contract.js';
|
|
5
|
-
export declare function bundleShared(sharedBundles: Record<string, NormalizedExternalConfig>, config: NormalizedFederationConfig, fedOptions:
|
|
6
|
-
|
|
5
|
+
export declare function bundleShared(sharedBundles: Record<string, NormalizedExternalConfig>, config: NormalizedFederationConfig, fedOptions: NormalizedFederationOptions, externals: string[], buildOptions: {
|
|
6
|
+
platform: 'browser' | 'node';
|
|
7
7
|
bundleName: string;
|
|
8
8
|
}): Promise<{
|
|
9
9
|
externals: SharedInfo[];
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
|
-
import { bundle } from '../utils/build-utils.js';
|
|
4
3
|
import { getPackageInfo } from '../utils/package-info.js';
|
|
5
4
|
import { logger } from '../utils/logger.js';
|
|
6
5
|
import crypto from 'crypto';
|
|
7
6
|
import { DEFAULT_EXTERNAL_LIST } from './default-external-list.js';
|
|
8
7
|
import { isSourceFile, rewriteChunkImports } from '../utils/rewrite-chunk-imports.js';
|
|
9
8
|
import { toChunkImport } from '../domain/core/chunk.js';
|
|
10
|
-
import { cacheEntry, getChecksum, getFilename } from '
|
|
9
|
+
import { cacheEntry, getChecksum, getFilename } from '../utils/cache-persistence.js';
|
|
11
10
|
import { fileURLToPath } from 'url';
|
|
12
|
-
|
|
11
|
+
import { getBuildAdapter } from './build-adapter.js';
|
|
12
|
+
export async function bundleShared(sharedBundles, config, fedOptions, externals, buildOptions) {
|
|
13
13
|
const checksum = getChecksum(sharedBundles, fedOptions.dev ? '1' : '0');
|
|
14
14
|
const folder = fedOptions.packageJson
|
|
15
15
|
? path.dirname(fedOptions.packageJson)
|
|
16
16
|
: fedOptions.workspaceRoot;
|
|
17
|
-
const bundleCache = cacheEntry(
|
|
17
|
+
const bundleCache = cacheEntry(fedOptions.federationCache.cachePath, getFilename(buildOptions.bundleName, fedOptions.dev));
|
|
18
18
|
if (fedOptions?.cacheExternalArtifacts) {
|
|
19
19
|
const cacheMetadata = bundleCache.getMetadata(checksum);
|
|
20
20
|
if (cacheMetadata) {
|
|
@@ -46,29 +46,33 @@ export async function bundleShared(sharedBundles, config, fedOptions, externals,
|
|
|
46
46
|
});
|
|
47
47
|
const fullOutputPath = path.join(fedOptions.workspaceRoot, fedOptions.outputPath);
|
|
48
48
|
const expectedResults = allEntryPoints.map(ep => path.join(fullOutputPath, ep.outName));
|
|
49
|
-
const entryPoints = allEntryPoints.filter(ep => !fs.existsSync(path.join(
|
|
49
|
+
const entryPoints = allEntryPoints.filter(ep => !fs.existsSync(path.join(fedOptions.federationCache.cachePath, ep.outName)));
|
|
50
50
|
// If we build for the browser and don't remote unused deps from the shared config,
|
|
51
51
|
// we need to exclude typical node libs to avoid compilation issues
|
|
52
|
-
const useDefaultExternalList = platform === 'browser' && !config.features.ignoreUnusedDeps;
|
|
52
|
+
const useDefaultExternalList = buildOptions.platform === 'browser' && !config.features.ignoreUnusedDeps;
|
|
53
53
|
const additionalExternals = useDefaultExternalList ? DEFAULT_EXTERNAL_LIST : [];
|
|
54
54
|
let bundleResult = null;
|
|
55
55
|
try {
|
|
56
|
-
|
|
56
|
+
await getBuildAdapter().setup({
|
|
57
57
|
entryPoints,
|
|
58
58
|
tsConfigPath: fedOptions.tsConfig,
|
|
59
59
|
external: [...additionalExternals, ...externals],
|
|
60
|
-
outdir:
|
|
60
|
+
outdir: fedOptions.federationCache.cachePath,
|
|
61
61
|
mappedPaths: config.sharedMappings,
|
|
62
62
|
dev: fedOptions.dev,
|
|
63
|
-
|
|
63
|
+
bundleName: buildOptions.bundleName,
|
|
64
|
+
isNodeModules: true,
|
|
64
65
|
hash: false,
|
|
65
66
|
chunks: (typeof fedOptions.chunks === 'boolean' && fedOptions.chunks) ||
|
|
66
67
|
(typeof fedOptions.chunks === 'object' && !!fedOptions.chunks.enable),
|
|
67
|
-
platform,
|
|
68
|
+
platform: buildOptions.platform,
|
|
68
69
|
optimizedMappings: config.features.ignoreUnusedDeps,
|
|
70
|
+
cache: fedOptions.federationCache,
|
|
69
71
|
});
|
|
72
|
+
bundleResult = await getBuildAdapter().build(buildOptions.bundleName);
|
|
73
|
+
await getBuildAdapter().dispose(buildOptions.bundleName);
|
|
70
74
|
const cachedFiles = bundleResult.map(br => path.basename(br.fileName));
|
|
71
|
-
rewriteImports(cachedFiles,
|
|
75
|
+
rewriteImports(cachedFiles, fedOptions.federationCache.cachePath);
|
|
72
76
|
}
|
|
73
77
|
catch (e) {
|
|
74
78
|
logger.error('Error bundling shared npm package ');
|
|
@@ -7,7 +7,7 @@ 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(signal?: AbortSignal): Promise<void>;
|
|
11
11
|
export declare const federationBuilder: {
|
|
12
12
|
init: typeof init;
|
|
13
13
|
build: typeof build;
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import { getConfigContext, usePackageJson, useWorkspace } from '../config/configuration-context.js';
|
|
2
2
|
import { setBuildAdapter } from './build-adapter.js';
|
|
3
|
-
import { buildForFederation
|
|
3
|
+
import { buildForFederation } from './build-for-federation.js';
|
|
4
4
|
import { getExternals } from './get-externals.js';
|
|
5
5
|
import { loadFederationConfig } from './load-federation-config.js';
|
|
6
|
+
import { normalizeFederationOptions } from './normalize-federation-options.js';
|
|
6
7
|
let externals = [];
|
|
7
8
|
let config;
|
|
8
9
|
let fedOptions;
|
|
9
10
|
let fedInfo;
|
|
10
11
|
async function init(params) {
|
|
11
12
|
setBuildAdapter(params.adapter);
|
|
12
|
-
fedOptions = params.options;
|
|
13
|
+
fedOptions = normalizeFederationOptions(params.options);
|
|
13
14
|
useWorkspace(params.options.workspaceRoot);
|
|
14
15
|
usePackageJson(params.options.packageJson);
|
|
15
16
|
config = await loadFederationConfig(fedOptions);
|
|
16
17
|
params.options.workspaceRoot = getConfigContext().workspaceRoot ?? params.options.workspaceRoot;
|
|
17
18
|
externals = getExternals(config);
|
|
18
19
|
}
|
|
19
|
-
async function build(
|
|
20
|
-
fedInfo = await buildForFederation(config, fedOptions, externals,
|
|
20
|
+
async function build(signal) {
|
|
21
|
+
fedInfo = await buildForFederation(config, fedOptions, externals, signal);
|
|
21
22
|
}
|
|
22
23
|
export const federationBuilder = {
|
|
23
24
|
init,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FederationCache } from '../domain/core/federation-cache.contract.js';
|
|
2
|
+
import type { ChunkInfo, SharedInfo } from '../domain/core/federation-info.contract.js';
|
|
3
|
+
export declare function createFederationCache(cachePath: string): FederationCache<undefined>;
|
|
4
|
+
export declare function createFederationCache<TBundlerCache>(cachePath: string, bundlerCache: TBundlerCache): FederationCache<TBundlerCache>;
|
|
5
|
+
export declare function addExternalsToCache(cache: FederationCache, { externals, chunks }: {
|
|
6
|
+
externals: SharedInfo[];
|
|
7
|
+
chunks?: ChunkInfo;
|
|
8
|
+
}): void;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function createFederationCache(cachePath, bundlerCache) {
|
|
2
|
+
return { externals: [], cachePath, bundlerCache };
|
|
3
|
+
}
|
|
4
|
+
export function addExternalsToCache(cache, { externals, chunks }) {
|
|
5
|
+
cache.externals.push(...externals);
|
|
6
|
+
if (chunks) {
|
|
7
|
+
if (!cache.chunks)
|
|
8
|
+
cache.chunks = {};
|
|
9
|
+
cache.chunks = { ...cache.chunks, ...chunks };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FederationCache } from '../../domain.js';
|
|
2
|
+
import type { FederationOptions, NormalizedFederationOptions } from '../domain/core/federation-options.contract.js';
|
|
3
|
+
export declare function normalizeFederationOptions(options: FederationOptions): NormalizedFederationOptions<undefined>;
|
|
4
|
+
export declare function normalizeFederationOptions<TBundlerCache>(options: FederationOptions, cache: FederationCache<TBundlerCache>): NormalizedFederationOptions<TBundlerCache>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getDefaultCachePath } from '../utils/cache-persistence.js';
|
|
2
|
+
import { createFederationCache } from './federation-cache.js';
|
|
3
|
+
export function normalizeFederationOptions(options, cache) {
|
|
4
|
+
const federationCache = cache ??
|
|
5
|
+
createFederationCache(getDefaultCachePath(options.workspaceRoot));
|
|
6
|
+
return {
|
|
7
|
+
...options,
|
|
8
|
+
federationCache,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FederationInfo } from '../domain/core/federation-info.contract.js';
|
|
2
|
+
import type { NormalizedFederationOptions } from '../domain/core/federation-options.contract.js';
|
|
3
|
+
import type { NormalizedFederationConfig } from '../domain/config/federation-config.contract.js';
|
|
4
|
+
export declare function rebuildForFederation(config: NormalizedFederationConfig, fedOptions: NormalizedFederationOptions, externals: string[], modifiedFiles: string[], signal?: AbortSignal): Promise<FederationInfo>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { bundleExposedAndMappings, describeExposed, describeSharedMappings, } from './bundle-exposed-and-mappings.js';
|
|
2
|
+
import { writeFederationInfo } from './write-federation-info.js';
|
|
3
|
+
import { writeImportMap } from './write-import-map.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
import { AbortedError } from '../utils/errors.js';
|
|
6
|
+
export async function rebuildForFederation(config, fedOptions, externals, modifiedFiles, signal) {
|
|
7
|
+
const federationCache = fedOptions.federationCache;
|
|
8
|
+
const start = process.hrtime();
|
|
9
|
+
// Shared mappings and exposed modules
|
|
10
|
+
const artifactInfo = await bundleExposedAndMappings(config, fedOptions, externals, modifiedFiles, signal);
|
|
11
|
+
logger.measure(start, '[build artifacts] - To re-bundle all mappings and exposed.');
|
|
12
|
+
if (signal?.aborted)
|
|
13
|
+
throw new AbortedError('[buildForFederation] After exposed-and-mappings bundle');
|
|
14
|
+
const exposedInfo = !artifactInfo ? describeExposed(config, fedOptions) : artifactInfo.exposes;
|
|
15
|
+
const sharedMappingInfo = !artifactInfo
|
|
16
|
+
? describeSharedMappings(config, fedOptions)
|
|
17
|
+
: artifactInfo.mappings;
|
|
18
|
+
const sharedExternals = [...federationCache.externals, ...sharedMappingInfo];
|
|
19
|
+
const buildNotificationsEndpoint = fedOptions.buildNotifications?.enable && fedOptions.dev
|
|
20
|
+
? fedOptions.buildNotifications?.endpoint
|
|
21
|
+
: undefined;
|
|
22
|
+
const federationInfo = {
|
|
23
|
+
name: config.name,
|
|
24
|
+
shared: sharedExternals,
|
|
25
|
+
exposes: exposedInfo,
|
|
26
|
+
buildNotificationsEndpoint,
|
|
27
|
+
};
|
|
28
|
+
if (federationCache.chunks) {
|
|
29
|
+
federationInfo.chunks = federationCache.chunks;
|
|
30
|
+
}
|
|
31
|
+
if (artifactInfo?.chunks) {
|
|
32
|
+
federationInfo.chunks = { ...(federationInfo.chunks ?? {}), ...artifactInfo?.chunks };
|
|
33
|
+
}
|
|
34
|
+
writeFederationInfo(federationInfo, fedOptions);
|
|
35
|
+
writeImportMap(federationCache, fedOptions);
|
|
36
|
+
return federationInfo;
|
|
37
|
+
}
|
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
import type { MappedPath } from '../utils/mapped-path.contract.js';
|
|
2
|
-
|
|
3
|
-
export
|
|
2
|
+
import type { FederationCache } from './federation-cache.contract.js';
|
|
3
|
+
export interface NFBuildAdapter {
|
|
4
|
+
setup(options: NFBuildAdapterOptions): Promise<void>;
|
|
5
|
+
build(name: string, opts?: {
|
|
6
|
+
files?: string[];
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
}): Promise<NFBuildAdapterResult[]>;
|
|
9
|
+
dispose(name?: string): Promise<void>;
|
|
10
|
+
}
|
|
4
11
|
export interface EntryPoint {
|
|
5
12
|
fileName: string;
|
|
6
13
|
outName: string;
|
|
7
14
|
key?: string;
|
|
8
15
|
}
|
|
9
|
-
export interface NFBuildAdapterOptions {
|
|
16
|
+
export interface NFBuildAdapterOptions<TBundlerCache = unknown> {
|
|
10
17
|
entryPoints: EntryPoint[];
|
|
11
18
|
tsConfigPath?: string;
|
|
12
|
-
external:
|
|
19
|
+
external: string[];
|
|
13
20
|
outdir: string;
|
|
14
21
|
mappedPaths: MappedPath[];
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
bundleName: string;
|
|
23
|
+
isNodeModules: boolean;
|
|
17
24
|
dev?: boolean;
|
|
18
25
|
watch?: boolean;
|
|
19
26
|
chunks?: boolean;
|
|
20
|
-
kind: BuildKind;
|
|
21
27
|
hash: boolean;
|
|
22
28
|
platform?: 'browser' | 'node';
|
|
23
29
|
optimizedMappings?: boolean;
|
|
24
|
-
|
|
30
|
+
cache: FederationCache<TBundlerCache>;
|
|
25
31
|
}
|
|
26
32
|
export interface NFBuildAdapterResult {
|
|
27
33
|
fileName: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BuildNotificationOptions } from './build-notification-options.contract.js';
|
|
2
|
+
import type { FederationCache } from './federation-cache.contract.js';
|
|
2
3
|
export interface FederationOptions {
|
|
3
4
|
workspaceRoot: string;
|
|
4
5
|
outputPath: string;
|
|
@@ -16,3 +17,6 @@ export interface FederationOptions {
|
|
|
16
17
|
entryPoint?: string;
|
|
17
18
|
buildNotifications?: BuildNotificationOptions;
|
|
18
19
|
}
|
|
20
|
+
export interface NormalizedFederationOptions<TBundlerCache = unknown> extends FederationOptions {
|
|
21
|
+
federationCache: FederationCache<TBundlerCache>;
|
|
22
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { SharedInfo, FederationInfo, ExposesInfo, ArtifactInfo, ChunkInfo, } from './federation-info.contract.js';
|
|
2
2
|
export { type BuildNotificationOptions, BuildNotificationType, } from './build-notification-options.contract.js';
|
|
3
|
-
export type { FederationOptions } from './federation-options.contract.js';
|
|
4
|
-
export type {
|
|
5
|
-
export type { BuildParams } from './build-params.contract.js';
|
|
3
|
+
export type { FederationOptions, NormalizedFederationOptions, } from './federation-options.contract.js';
|
|
4
|
+
export type { EntryPoint, NFBuildAdapterOptions, NFBuildAdapter, NFBuildAdapterResult, } from './build-adapter.contract.js';
|
|
6
5
|
export { CHUNK_PREFIX, toChunkImport } from './chunk.js';
|
|
6
|
+
export type { FederationCache } from './federation-cache.contract.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { NormalizedExternalConfig } from '../domain/config/external-config.contract.js';
|
|
2
2
|
import type { ChunkInfo, SharedInfo } from '../domain/core/federation-info.contract.js';
|
|
3
|
-
export declare const
|
|
3
|
+
export declare const getDefaultCachePath: (workspaceRoot: string) => string;
|
|
4
4
|
export declare const getFilename: (title: string, dev?: boolean) => string;
|
|
5
5
|
export declare const getChecksum: (shared: Record<string, NormalizedExternalConfig>, dev: "1" | "0") => string;
|
|
6
6
|
export declare const cacheEntry: (pathToCache: string, fileName: string) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import crypto from 'crypto';
|
|
4
|
-
import { logger } from '
|
|
5
|
-
export const
|
|
4
|
+
import { logger } from './logger.js';
|
|
5
|
+
export const getDefaultCachePath = (workspaceRoot) => path.join(workspaceRoot, 'node_modules/.cache/native-federation');
|
|
6
6
|
export const getFilename = (title, dev) => {
|
|
7
7
|
const devSuffix = dev ? '-dev' : '';
|
|
8
8
|
return `${title}${devSuffix}.meta.json`;
|
|
@@ -15,13 +15,13 @@ export function resolveGlobSync(pattern, baseDir = process.cwd()) {
|
|
|
15
15
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
16
16
|
if (segment === '*') {
|
|
17
17
|
entries
|
|
18
|
-
.filter(
|
|
19
|
-
.forEach(
|
|
18
|
+
.filter(entry => entry.isDirectory())
|
|
19
|
+
.forEach(entry => search(path.join(dir, entry.name), segmentIndex + 1));
|
|
20
20
|
}
|
|
21
21
|
else {
|
|
22
22
|
entries
|
|
23
|
-
.filter(
|
|
24
|
-
.forEach(
|
|
23
|
+
.filter(entry => entry.name === segment)
|
|
24
|
+
.forEach(entry => search(path.join(dir, entry.name), segmentIndex + 1));
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
search(baseDir, 0);
|
|
File without changes
|