@softarc/native-federation 4.0.0-RC1 → 4.0.0-RC10
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 +2 -2
- package/src/config.d.ts +0 -1
- package/src/domain.d.ts +0 -1
- package/src/index.d.ts +3 -2
- package/src/index.js +3 -1
- package/src/internal.d.ts +5 -4
- package/src/internal.js +3 -1
- package/src/lib/config/configuration-context.d.ts +0 -1
- package/src/lib/config/default-skip-list.d.ts +0 -1
- 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 -2
- package/src/lib/config/share-utils.js +7 -13
- package/src/lib/config/with-native-federation.d.ts +0 -1
- package/src/lib/config/with-native-federation.js +41 -59
- package/src/lib/core/build-adapter.d.ts +0 -1
- package/src/lib/core/build-adapter.js +5 -5
- package/src/lib/core/build-for-federation.d.ts +2 -5
- package/src/lib/core/build-for-federation.js +68 -59
- package/src/lib/core/bundle-exposed-and-mappings.d.ts +5 -6
- package/src/lib/core/bundle-exposed-and-mappings.js +56 -28
- package/src/lib/core/bundle-shared.d.ts +8 -5
- package/src/lib/core/bundle-shared.js +41 -18
- package/src/lib/core/default-external-list.d.ts +0 -1
- package/src/lib/core/default-external-list.js +1 -4
- package/src/lib/core/federation-builder.d.ts +6 -2
- package/src/lib/core/federation-builder.js +19 -8
- package/src/lib/core/federation-cache.d.ts +8 -0
- package/src/lib/core/federation-cache.js +11 -0
- package/src/lib/core/get-externals.d.ts +0 -1
- 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 +57 -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/core/write-federation-info.d.ts +0 -1
- package/src/lib/core/write-import-map.d.ts +5 -3
- package/src/lib/core/write-import-map.js +10 -1
- package/src/lib/domain/config/external-config.contract.d.ts +5 -2
- package/src/lib/domain/config/federation-config.contract.d.ts +10 -3
- package/src/lib/domain/config/index.d.ts +0 -1
- package/src/lib/domain/config/skip-list.contract.d.ts +0 -1
- package/src/lib/domain/config/with-native-federation.contract.d.ts +2 -0
- package/src/lib/domain/core/build-adapter.contract.d.ts +23 -11
- package/src/lib/domain/core/build-notification-options.contract.d.ts +0 -1
- package/src/lib/domain/core/chunk.d.ts +2 -0
- package/src/lib/domain/core/chunk.js +8 -0
- package/src/lib/domain/core/federation-cache.contract.d.ts +7 -0
- package/src/lib/domain/core/federation-cache.contract.js +1 -0
- package/src/lib/domain/core/federation-info.contract.d.ts +6 -2
- package/src/lib/domain/core/federation-options.contract.d.ts +8 -2
- package/src/lib/domain/core/index.d.ts +5 -5
- package/src/lib/domain/core/index.js +1 -0
- package/src/lib/domain/utils/index.d.ts +1 -2
- package/src/lib/domain/utils/keyvaluepair.contract.d.ts +0 -1
- package/src/lib/domain/utils/mapped-path.contract.d.ts +1 -5
- 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/build-result-map.d.ts +1 -1
- package/src/lib/utils/build-result-map.js +9 -2
- package/src/lib/utils/{bundle-caching.d.ts → cache-persistence.d.ts} +4 -3
- package/src/lib/utils/{bundle-caching.js → cache-persistence.js} +2 -2
- package/src/lib/utils/errors.d.ts +0 -1
- package/src/lib/utils/get-external-imports.d.ts +0 -1
- 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/hash-file.d.ts +0 -1
- package/src/lib/utils/logger.d.ts +0 -1
- package/src/lib/utils/mapped-paths.d.ts +7 -8
- package/src/lib/utils/mapped-paths.js +14 -12
- package/src/lib/utils/normalize.d.ts +0 -1
- package/src/lib/utils/package-info.d.ts +0 -1
- package/src/lib/utils/rebuild-queue.d.ts +14 -2
- package/src/lib/utils/rebuild-queue.js +32 -12
- package/src/lib/utils/resolve-glob.d.ts +0 -1
- package/src/lib/utils/resolve-glob.js +4 -4
- package/src/lib/utils/resolve-wildcard-keys.d.ts +29 -3
- package/src/lib/utils/resolve-wildcard-keys.js +105 -38
- package/src/lib/utils/rewrite-chunk-imports.d.ts +0 -3
- package/src/lib/utils/rewrite-chunk-imports.js +3 -10
- package/src/config.d.ts.map +0 -1
- package/src/domain.d.ts.map +0 -1
- package/src/index.d.ts.map +0 -1
- package/src/internal.d.ts.map +0 -1
- package/src/lib/config/configuration-context.d.ts.map +0 -1
- package/src/lib/config/default-skip-list.d.ts.map +0 -1
- package/src/lib/config/share-utils.d.ts.map +0 -1
- package/src/lib/config/with-native-federation.d.ts.map +0 -1
- package/src/lib/core/build-adapter.d.ts.map +0 -1
- package/src/lib/core/build-for-federation.d.ts.map +0 -1
- package/src/lib/core/bundle-exposed-and-mappings.d.ts.map +0 -1
- package/src/lib/core/bundle-shared.d.ts.map +0 -1
- package/src/lib/core/default-external-list.d.ts.map +0 -1
- package/src/lib/core/default-server-deps-list.d.ts +0 -3
- package/src/lib/core/default-server-deps-list.d.ts.map +0 -1
- package/src/lib/core/default-server-deps-list.js +0 -6
- package/src/lib/core/federation-builder.d.ts.map +0 -1
- package/src/lib/core/get-externals.d.ts.map +0 -1
- package/src/lib/core/load-federation-config.d.ts +0 -4
- package/src/lib/core/load-federation-config.d.ts.map +0 -1
- package/src/lib/core/load-federation-config.js +0 -18
- package/src/lib/core/remove-unused-deps.d.ts +0 -3
- package/src/lib/core/remove-unused-deps.d.ts.map +0 -1
- package/src/lib/core/remove-unused-deps.js +0 -88
- package/src/lib/core/write-federation-info.d.ts.map +0 -1
- package/src/lib/core/write-import-map.d.ts.map +0 -1
- package/src/lib/domain/config/external-config.contract.d.ts.map +0 -1
- package/src/lib/domain/config/federation-config.contract.d.ts.map +0 -1
- package/src/lib/domain/config/index.d.ts.map +0 -1
- package/src/lib/domain/config/skip-list.contract.d.ts.map +0 -1
- package/src/lib/domain/core/build-adapter.contract.d.ts.map +0 -1
- package/src/lib/domain/core/build-notification-options.contract.d.ts.map +0 -1
- package/src/lib/domain/core/build-params.contract.d.ts +0 -6
- package/src/lib/domain/core/build-params.contract.d.ts.map +0 -1
- package/src/lib/domain/core/federation-info.contract.d.ts.map +0 -1
- package/src/lib/domain/core/federation-options.contract.d.ts.map +0 -1
- package/src/lib/domain/core/index.d.ts.map +0 -1
- package/src/lib/domain/utils/index.d.ts.map +0 -1
- package/src/lib/domain/utils/keyvaluepair.contract.d.ts.map +0 -1
- package/src/lib/domain/utils/mapped-path.contract.d.ts.map +0 -1
- package/src/lib/utils/build-result-map.d.ts.map +0 -1
- package/src/lib/utils/build-utils.d.ts +0 -3
- package/src/lib/utils/build-utils.d.ts.map +0 -1
- package/src/lib/utils/build-utils.js +0 -5
- package/src/lib/utils/bundle-caching.d.ts.map +0 -1
- package/src/lib/utils/errors.d.ts.map +0 -1
- package/src/lib/utils/get-external-imports.d.ts.map +0 -1
- package/src/lib/utils/hash-file.d.ts.map +0 -1
- package/src/lib/utils/logger.d.ts.map +0 -1
- package/src/lib/utils/mapped-paths.d.ts.map +0 -1
- package/src/lib/utils/normalize.d.ts.map +0 -1
- package/src/lib/utils/package-info.d.ts.map +0 -1
- package/src/lib/utils/rebuild-queue.d.ts.map +0 -1
- package/src/lib/utils/resolve-glob.d.ts.map +0 -1
- package/src/lib/utils/resolve-wildcard-keys.d.ts.map +0 -1
- package/src/lib/utils/rewrite-chunk-imports.d.ts.map +0 -1
- /package/src/lib/domain/{core/build-params.contract.js → config/with-native-federation.contract.js} +0 -0
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { createBuildResultMap,
|
|
4
|
-
import { bundle } from '../utils/build-utils.js';
|
|
3
|
+
import { createBuildResultMap, popFromResultMap } from '../utils/build-result-map.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';
|
|
8
|
+
import { getBuildAdapter } from './build-adapter.js';
|
|
9
|
+
export async function bundleExposedAndMappings(config, fedOptions, externals, modifiedFiles, signal) {
|
|
9
10
|
if (signal?.aborted) {
|
|
10
11
|
throw new AbortedError('[bundle-exposed-and-mappings] Aborted before bundling');
|
|
11
12
|
}
|
|
12
|
-
const shared = config.sharedMappings.map(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
+
};
|
|
17
19
|
});
|
|
18
20
|
const exposes = Object.entries(config.exposes).map(([key, entry]) => {
|
|
19
21
|
const outFilePath = key + '.js';
|
|
@@ -21,21 +23,27 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, si
|
|
|
21
23
|
});
|
|
22
24
|
const entryPoints = [...shared, ...exposes];
|
|
23
25
|
const hash = !fedOptions.dev;
|
|
24
|
-
logger.info('Building federation artefacts');
|
|
25
26
|
let result;
|
|
26
27
|
try {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
if (!modifiedFiles) {
|
|
29
|
+
await getBuildAdapter().setup('mapping-or-exposed', {
|
|
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
|
+
chunks: config.chunks,
|
|
38
|
+
hash,
|
|
39
|
+
optimizedMappings: config.features.ignoreUnusedDeps,
|
|
40
|
+
isMappingOrExposed: true,
|
|
41
|
+
cache: fedOptions.federationCache,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
result = await getBuildAdapter().build('mapping-or-exposed', {
|
|
38
45
|
signal,
|
|
46
|
+
modifiedFiles,
|
|
39
47
|
});
|
|
40
48
|
if (signal?.aborted) {
|
|
41
49
|
throw new AbortedError('[bundle-exposed-and-mappings] Aborted after bundle');
|
|
@@ -43,16 +51,19 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, si
|
|
|
43
51
|
}
|
|
44
52
|
catch (error) {
|
|
45
53
|
if (!(error instanceof AbortedError)) {
|
|
46
|
-
logger.error('Error building federation
|
|
54
|
+
logger.error('Error building federation artifacts');
|
|
47
55
|
}
|
|
48
56
|
throw error;
|
|
49
57
|
}
|
|
50
58
|
const resultMap = createBuildResultMap(result, hash);
|
|
51
59
|
const sharedResult = [];
|
|
60
|
+
const entryFiles = [];
|
|
61
|
+
// Pick shared-mappings
|
|
52
62
|
for (const item of shared) {
|
|
63
|
+
const distEntryFile = popFromResultMap(resultMap, item.outName);
|
|
53
64
|
sharedResult.push({
|
|
54
65
|
packageName: item.key,
|
|
55
|
-
outFileName:
|
|
66
|
+
outFileName: path.basename(distEntryFile),
|
|
56
67
|
requiredVersion: '',
|
|
57
68
|
singleton: true,
|
|
58
69
|
strictVersion: false,
|
|
@@ -63,20 +74,37 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, si
|
|
|
63
74
|
entryPoint: normalize(path.normalize(item.fileName)),
|
|
64
75
|
},
|
|
65
76
|
});
|
|
77
|
+
entryFiles.push(distEntryFile);
|
|
66
78
|
}
|
|
67
79
|
const exposedResult = [];
|
|
80
|
+
// Pick exposed-modules
|
|
68
81
|
for (const item of exposes) {
|
|
82
|
+
const distEntryFile = popFromResultMap(resultMap, item.outName);
|
|
69
83
|
exposedResult.push({
|
|
70
84
|
key: item.key,
|
|
71
|
-
outFileName:
|
|
85
|
+
outFileName: path.basename(distEntryFile),
|
|
72
86
|
dev: !fedOptions.dev
|
|
73
87
|
? undefined
|
|
74
88
|
: {
|
|
75
89
|
entryPoint: normalize(path.join(fedOptions.workspaceRoot, item.fileName)),
|
|
76
90
|
},
|
|
77
91
|
});
|
|
92
|
+
entryFiles.push(distEntryFile);
|
|
93
|
+
}
|
|
94
|
+
// Remove .map files
|
|
95
|
+
Object.keys(resultMap)
|
|
96
|
+
.filter(f => f.endsWith('.map'))
|
|
97
|
+
.forEach(f => popFromResultMap(resultMap, f));
|
|
98
|
+
// Process remaining chunks and lazy loaded internal modules
|
|
99
|
+
let exportedChunks = undefined;
|
|
100
|
+
if (config.chunks && config.features.denseChunking) {
|
|
101
|
+
for (const entryFile of entryFiles)
|
|
102
|
+
rewriteChunkImports(entryFile);
|
|
103
|
+
exportedChunks = {
|
|
104
|
+
['mapping-or-exposed']: Object.values(resultMap).map(chunk => path.basename(chunk)),
|
|
105
|
+
};
|
|
78
106
|
}
|
|
79
|
-
return { mappings: sharedResult, exposes: exposedResult };
|
|
107
|
+
return { mappings: sharedResult, exposes: exposedResult, chunks: exportedChunks };
|
|
80
108
|
}
|
|
81
109
|
export function describeExposed(config, options) {
|
|
82
110
|
const result = [];
|
|
@@ -96,18 +124,18 @@ export function describeExposed(config, options) {
|
|
|
96
124
|
}
|
|
97
125
|
export function describeSharedMappings(config, fedOptions) {
|
|
98
126
|
const result = [];
|
|
99
|
-
for (const
|
|
127
|
+
for (const [mappedPath, mappedImport] of Object.entries(config.sharedMappings)) {
|
|
100
128
|
result.push({
|
|
101
|
-
packageName:
|
|
129
|
+
packageName: mappedImport,
|
|
102
130
|
outFileName: '',
|
|
103
131
|
requiredVersion: '',
|
|
104
132
|
singleton: true,
|
|
105
133
|
strictVersion: false,
|
|
106
|
-
version: config.features.mappingVersion ? getMappingVersion(
|
|
134
|
+
version: config.features.mappingVersion ? getMappingVersion(mappedPath) : '',
|
|
107
135
|
dev: !fedOptions.dev
|
|
108
136
|
? undefined
|
|
109
137
|
: {
|
|
110
|
-
entryPoint: normalize(path.normalize(
|
|
138
|
+
entryPoint: normalize(path.normalize(mappedPath)),
|
|
111
139
|
},
|
|
112
140
|
});
|
|
113
141
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
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
|
-
|
|
9
|
-
|
|
8
|
+
chunks: boolean;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
externals: SharedInfo[];
|
|
11
|
+
chunks?: Record<string, string[]>;
|
|
12
|
+
}>;
|
|
@@ -1,25 +1,26 @@
|
|
|
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
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { isSourceFile, rewriteChunkImports } from '../utils/rewrite-chunk-imports.js';
|
|
8
|
+
import { toChunkImport } from '../domain/core/chunk.js';
|
|
9
|
+
import { cacheEntry, getChecksum, getFilename } from '../utils/cache-persistence.js';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
|
-
|
|
11
|
+
import { getBuildAdapter } from './build-adapter.js';
|
|
12
|
+
export async function bundleShared(sharedBundles, config, fedOptions, externals, buildOptions) {
|
|
12
13
|
const checksum = getChecksum(sharedBundles, fedOptions.dev ? '1' : '0');
|
|
13
14
|
const folder = fedOptions.packageJson
|
|
14
15
|
? path.dirname(fedOptions.packageJson)
|
|
15
16
|
: fedOptions.workspaceRoot;
|
|
16
|
-
const bundleCache = cacheEntry(
|
|
17
|
+
const bundleCache = cacheEntry(fedOptions.federationCache.cachePath, getFilename(buildOptions.bundleName, fedOptions.dev));
|
|
17
18
|
if (fedOptions?.cacheExternalArtifacts) {
|
|
18
19
|
const cacheMetadata = bundleCache.getMetadata(checksum);
|
|
19
20
|
if (cacheMetadata) {
|
|
20
|
-
logger.debug(`Checksum of ${
|
|
21
|
+
logger.debug(`Checksum of ${buildOptions.bundleName} matched, Skipped artifact bundling`);
|
|
21
22
|
bundleCache.copyFiles(path.join(fedOptions.workspaceRoot, fedOptions.outputPath));
|
|
22
|
-
return cacheMetadata.externals;
|
|
23
|
+
return { externals: cacheMetadata.externals, chunks: cacheMetadata.chunks };
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
bundleCache.clear();
|
|
@@ -45,27 +46,31 @@ export async function bundleShared(sharedBundles, config, fedOptions, externals,
|
|
|
45
46
|
});
|
|
46
47
|
const fullOutputPath = path.join(fedOptions.workspaceRoot, fedOptions.outputPath);
|
|
47
48
|
const expectedResults = allEntryPoints.map(ep => path.join(fullOutputPath, ep.outName));
|
|
48
|
-
const entryPoints = allEntryPoints.filter(ep => !fs.existsSync(path.join(
|
|
49
|
+
const entryPoints = allEntryPoints.filter(ep => !fs.existsSync(path.join(fedOptions.federationCache.cachePath, ep.outName)));
|
|
49
50
|
// If we build for the browser and don't remote unused deps from the shared config,
|
|
50
51
|
// we need to exclude typical node libs to avoid compilation issues
|
|
51
|
-
const useDefaultExternalList = platform === 'browser' && !config.features.ignoreUnusedDeps;
|
|
52
|
+
const useDefaultExternalList = buildOptions.platform === 'browser' && !config.features.ignoreUnusedDeps;
|
|
52
53
|
const additionalExternals = useDefaultExternalList ? DEFAULT_EXTERNAL_LIST : [];
|
|
53
54
|
let bundleResult = null;
|
|
54
55
|
try {
|
|
55
|
-
|
|
56
|
+
await getBuildAdapter().setup(buildOptions.bundleName, {
|
|
56
57
|
entryPoints,
|
|
57
58
|
tsConfigPath: fedOptions.tsConfig,
|
|
58
59
|
external: [...additionalExternals, ...externals],
|
|
59
|
-
outdir:
|
|
60
|
+
outdir: fedOptions.federationCache.cachePath,
|
|
60
61
|
mappedPaths: config.sharedMappings,
|
|
61
62
|
dev: fedOptions.dev,
|
|
62
|
-
|
|
63
|
+
isMappingOrExposed: false,
|
|
63
64
|
hash: false,
|
|
64
|
-
|
|
65
|
+
chunks: buildOptions.chunks,
|
|
66
|
+
platform: buildOptions.platform,
|
|
65
67
|
optimizedMappings: config.features.ignoreUnusedDeps,
|
|
68
|
+
cache: fedOptions.federationCache,
|
|
66
69
|
});
|
|
70
|
+
bundleResult = await getBuildAdapter().build(buildOptions.bundleName);
|
|
71
|
+
await getBuildAdapter().dispose(buildOptions.bundleName);
|
|
67
72
|
const cachedFiles = bundleResult.map(br => path.basename(br.fileName));
|
|
68
|
-
rewriteImports(cachedFiles,
|
|
73
|
+
rewriteImports(cachedFiles, fedOptions.federationCache.cachePath);
|
|
69
74
|
}
|
|
70
75
|
catch (e) {
|
|
71
76
|
logger.error('Error bundling shared npm package ');
|
|
@@ -89,17 +94,31 @@ export async function bundleShared(sharedBundles, config, fedOptions, externals,
|
|
|
89
94
|
}
|
|
90
95
|
const outFileNames = [...expectedResults];
|
|
91
96
|
const result = buildResult(packageInfos, sharedBundles, outFileNames);
|
|
92
|
-
// TODO: Decide whether/when to add .map files
|
|
93
97
|
const chunks = bundleResult.filter(br => !br.fileName.endsWith('.map') &&
|
|
94
98
|
!result.find(r => r.outFileName === path.basename(br.fileName)));
|
|
95
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Chunking
|
|
101
|
+
*/
|
|
102
|
+
let exportedChunks = undefined;
|
|
103
|
+
if (buildOptions.chunks && config.features.denseChunking) {
|
|
104
|
+
result.forEach(external => {
|
|
105
|
+
external.bundle = buildOptions.bundleName;
|
|
106
|
+
});
|
|
107
|
+
if (chunks.length > 0) {
|
|
108
|
+
exportedChunks = { [buildOptions.bundleName]: getChunkFileNames(chunks) };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
addChunksToResult(chunks, result);
|
|
113
|
+
}
|
|
96
114
|
bundleCache.persist({
|
|
97
115
|
checksum,
|
|
98
116
|
externals: result,
|
|
99
117
|
files: bundleResult.map(r => r.fileName.split(path.sep).pop() ?? r.fileName),
|
|
118
|
+
chunks: exportedChunks,
|
|
100
119
|
});
|
|
101
120
|
bundleCache.copyFiles(path.join(fedOptions.workspaceRoot, fedOptions.outputPath));
|
|
102
|
-
return result;
|
|
121
|
+
return { externals: result, chunks: exportedChunks };
|
|
103
122
|
}
|
|
104
123
|
function rewriteImports(cachedFiles, cachePath) {
|
|
105
124
|
const newSourceFiles = cachedFiles.filter(cf => isSourceFile(cf));
|
|
@@ -124,6 +143,7 @@ function buildResult(packageInfos, sharedBundles, outFileNames) {
|
|
|
124
143
|
singleton: shared?.singleton,
|
|
125
144
|
strictVersion: shared?.strictVersion,
|
|
126
145
|
version: pi.version,
|
|
146
|
+
...(shared?.shareScope && { shareScope: shared.shareScope }),
|
|
127
147
|
// TODO: Decide whether/when we need debug infos
|
|
128
148
|
// dev: !fedOptions.dev
|
|
129
149
|
// ? undefined
|
|
@@ -133,6 +153,9 @@ function buildResult(packageInfos, sharedBundles, outFileNames) {
|
|
|
133
153
|
};
|
|
134
154
|
});
|
|
135
155
|
}
|
|
156
|
+
function getChunkFileNames(chunks) {
|
|
157
|
+
return chunks.map(chunk => path.basename(chunk.fileName));
|
|
158
|
+
}
|
|
136
159
|
function addChunksToResult(chunks, result) {
|
|
137
160
|
for (const item of chunks) {
|
|
138
161
|
const fileName = path.basename(item.fileName);
|
|
@@ -149,7 +172,7 @@ function addChunksToResult(chunks, result) {
|
|
|
149
172
|
// take care of singleton and strictVersion.
|
|
150
173
|
version: '0.0.0',
|
|
151
174
|
requiredVersion: '0.0.0',
|
|
152
|
-
packageName:
|
|
175
|
+
packageName: toChunkImport(fileName),
|
|
153
176
|
outFileName: fileName,
|
|
154
177
|
// dev: dev
|
|
155
178
|
// ? undefined
|
|
@@ -7,13 +7,17 @@ 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;
|
|
17
22
|
};
|
|
18
23
|
export {};
|
|
19
|
-
//# sourceMappingURL=federation-builder.d.ts.map
|
|
@@ -1,27 +1,38 @@
|
|
|
1
1
|
import { getConfigContext, usePackageJson, useWorkspace } from '../config/configuration-context.js';
|
|
2
|
-
import { setBuildAdapter } from './build-adapter.js';
|
|
3
|
-
import { buildForFederation
|
|
2
|
+
import { getBuildAdapter, setBuildAdapter } from './build-adapter.js';
|
|
3
|
+
import { buildForFederation } from './build-for-federation.js';
|
|
4
4
|
import { getExternals } from './get-externals.js';
|
|
5
|
-
import {
|
|
5
|
+
import { normalizeFederationOptions } from './normalize-options.js';
|
|
6
|
+
import { rebuildForFederation } from './rebuild-for-federation.js';
|
|
6
7
|
let externals = [];
|
|
7
8
|
let config;
|
|
8
|
-
let
|
|
9
|
+
let options;
|
|
9
10
|
let fedInfo;
|
|
10
11
|
async function init(params) {
|
|
11
12
|
setBuildAdapter(params.adapter);
|
|
12
|
-
fedOptions = params.options;
|
|
13
13
|
useWorkspace(params.options.workspaceRoot);
|
|
14
14
|
usePackageJson(params.options.packageJson);
|
|
15
|
-
config = await loadFederationConfig(fedOptions);
|
|
16
15
|
params.options.workspaceRoot = getConfigContext().workspaceRoot ?? params.options.workspaceRoot;
|
|
16
|
+
const normalized = await normalizeFederationOptions(params.options);
|
|
17
|
+
options = normalized.options;
|
|
18
|
+
config = normalized.config;
|
|
17
19
|
externals = getExternals(config);
|
|
18
20
|
}
|
|
19
|
-
async function build(
|
|
20
|
-
|
|
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();
|
|
21
31
|
}
|
|
22
32
|
export const federationBuilder = {
|
|
23
33
|
init,
|
|
24
34
|
build,
|
|
35
|
+
close,
|
|
25
36
|
get federationInfo() {
|
|
26
37
|
return fedInfo;
|
|
27
38
|
},
|
|
@@ -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
|
+
}
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { NormalizedFederationConfig } from '../domain/config/federation-config.contract.js';
|
|
2
|
+
import type { FederationOptions, NormalizedFederationOptions } from '../domain/core/federation-options.contract.js';
|
|
3
|
+
import { type FederationCache } from '../../domain.js';
|
|
4
|
+
export declare function normalizeFederationOptions(options: FederationOptions): Promise<{
|
|
5
|
+
config: NormalizedFederationConfig;
|
|
6
|
+
options: NormalizedFederationOptions<undefined>;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function normalizeFederationOptions<TBundlerCache>(options: FederationOptions, cache: FederationCache<TBundlerCache>): Promise<{
|
|
9
|
+
config: NormalizedFederationConfig;
|
|
10
|
+
options: NormalizedFederationOptions<TBundlerCache>;
|
|
11
|
+
}>;
|
|
12
|
+
export declare function resolveProjectName(name?: string): string;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { pathToFileURL } from 'url';
|
|
4
|
+
import { removeUnusedDeps } from '../config/remove-unused-deps.js';
|
|
5
|
+
import { createFederationCache } from './federation-cache.js';
|
|
6
|
+
import { getDefaultCachePath } from '../utils/cache-persistence.js';
|
|
7
|
+
import { getUsedDependenciesFactory } from '../utils/get-used-dependencies.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
import { normalizePackageName } from '../utils/normalize.js';
|
|
10
|
+
export async function normalizeFederationOptions(options, cache) {
|
|
11
|
+
/**
|
|
12
|
+
* Step 1: normalizing config
|
|
13
|
+
*/
|
|
14
|
+
const fullConfigPath = path.join(options.workspaceRoot, options.federationConfig);
|
|
15
|
+
const getUsedDeps = getUsedDependenciesFactory(options.workspaceRoot, options.entryPoints);
|
|
16
|
+
if (!fs.existsSync(fullConfigPath)) {
|
|
17
|
+
throw new Error('Expected ' + fullConfigPath);
|
|
18
|
+
}
|
|
19
|
+
let config = (await import(pathToFileURL(fullConfigPath).href))
|
|
20
|
+
?.default;
|
|
21
|
+
/**
|
|
22
|
+
* Step 2: normalizing options
|
|
23
|
+
*/
|
|
24
|
+
const federationCache = cache ??
|
|
25
|
+
createFederationCache(getDefaultCachePath(options.workspaceRoot));
|
|
26
|
+
const normalizedOptions = {
|
|
27
|
+
...options,
|
|
28
|
+
entryPoints: options.entryPoints ?? Object.values(config.exposes ?? {}),
|
|
29
|
+
projectName: resolveProjectName(options.projectName ?? config.name),
|
|
30
|
+
federationCache,
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Step 3: Remove unused deps
|
|
34
|
+
*/
|
|
35
|
+
if (config.features.ignoreUnusedDeps) {
|
|
36
|
+
config = removeUnusedDeps(getUsedDeps(config), config);
|
|
37
|
+
logger.info('Removed unused dependencies.');
|
|
38
|
+
logger.debug('This can be disabled per dependency/external using the "includeSecondaries: {keepAll: true}" property. Or in general by disabling the "ignoreUnusedDeps" feature. ');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const withWildcard = Object.keys(config.sharedMappings).some(m => m.includes('*'));
|
|
42
|
+
if (withWildcard) {
|
|
43
|
+
logger.warn('Sharing mapped paths with wildcards (*) is only supported with ignoreUnusedDeps feature.');
|
|
44
|
+
config.sharedMappings = Object.entries(config.sharedMappings)
|
|
45
|
+
.filter(([_path]) => !_path.includes('*'))
|
|
46
|
+
.reduce((acc, [_path, _import]) => ({ ...acc, [_path]: _import }), {});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { config, options: normalizedOptions };
|
|
50
|
+
}
|
|
51
|
+
export function resolveProjectName(name) {
|
|
52
|
+
if (!name || name.length < 1) {
|
|
53
|
+
logger.warn("Project name in 'federation.config.js' is empty, defaulting to 'shell' cache folder (could collide with other projects in the workspace).");
|
|
54
|
+
return 'shell';
|
|
55
|
+
}
|
|
56
|
+
return normalizePackageName(name);
|
|
57
|
+
}
|
|
@@ -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
|
+
logger.info(`Re-bundling all internal libraries and exposed modules..'`);
|
|
9
|
+
const start = process.hrtime();
|
|
10
|
+
const artifactInfo = await bundleExposedAndMappings(config, fedOptions, externals, modifiedFiles, signal);
|
|
11
|
+
logger.measure(start, 'To re-bundle all internal libraries and exposed modules.');
|
|
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,4 +1,3 @@
|
|
|
1
1
|
import type { FederationInfo } from '../domain/core/federation-info.contract.js';
|
|
2
2
|
import type { FederationOptions } from '../domain/core/federation-options.contract.js';
|
|
3
3
|
export declare function writeFederationInfo(federationInfo: FederationInfo, fedOptions: FederationOptions): void;
|
|
4
|
-
//# sourceMappingURL=write-federation-info.d.ts.map
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { SharedInfo } from '../domain/core/federation-info.contract.js';
|
|
1
|
+
import type { ChunkInfo, SharedInfo } from '../domain/core/federation-info.contract.js';
|
|
2
2
|
import type { FederationOptions } from '../domain/core/federation-options.contract.js';
|
|
3
|
-
export declare function writeImportMap(sharedInfo:
|
|
4
|
-
|
|
3
|
+
export declare function writeImportMap(sharedInfo: {
|
|
4
|
+
externals: SharedInfo[];
|
|
5
|
+
chunks?: ChunkInfo;
|
|
6
|
+
}, fedOption: FederationOptions): void;
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
|
+
import { toChunkImport } from '../domain/core/chunk.js';
|
|
3
4
|
export function writeImportMap(sharedInfo, fedOption) {
|
|
4
|
-
const imports = sharedInfo.reduce((acc, cur) => {
|
|
5
|
+
const imports = sharedInfo.externals.reduce((acc, cur) => {
|
|
5
6
|
return {
|
|
6
7
|
...acc,
|
|
7
8
|
[cur.packageName]: cur.outFileName,
|
|
8
9
|
};
|
|
9
10
|
}, {});
|
|
11
|
+
if (sharedInfo.chunks) {
|
|
12
|
+
Object.values(sharedInfo.chunks).forEach(c => {
|
|
13
|
+
c.forEach(e => {
|
|
14
|
+
const key = toChunkImport(e);
|
|
15
|
+
imports[key] = e;
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
10
19
|
const importMap = { imports };
|
|
11
20
|
const importMapPath = path.join(fedOption.workspaceRoot, fedOption.outputPath, 'importmap.json');
|
|
12
21
|
fs.writeFileSync(importMapPath, JSON.stringify(importMap, null, 2));
|
|
@@ -5,7 +5,9 @@ export interface ExternalConfig {
|
|
|
5
5
|
version?: string;
|
|
6
6
|
includeSecondaries?: boolean;
|
|
7
7
|
platform?: 'browser' | 'node';
|
|
8
|
-
build?: '
|
|
8
|
+
build?: 'separate' | 'package';
|
|
9
|
+
chunks?: boolean;
|
|
10
|
+
shareScope?: string;
|
|
9
11
|
packageInfo?: {
|
|
10
12
|
entryPoint: string;
|
|
11
13
|
version?: string;
|
|
@@ -18,6 +20,8 @@ export interface NormalizedExternalConfig {
|
|
|
18
20
|
requiredVersion: string;
|
|
19
21
|
version?: string;
|
|
20
22
|
includeSecondaries?: boolean;
|
|
23
|
+
shareScope?: string;
|
|
24
|
+
chunks: boolean;
|
|
21
25
|
platform: 'browser' | 'node';
|
|
22
26
|
build: 'default' | 'separate' | 'package';
|
|
23
27
|
packageInfo?: {
|
|
@@ -37,4 +41,3 @@ export type ShareAllExternalsOptions = ExternalConfig & {
|
|
|
37
41
|
includeSecondaries?: IncludeSecondariesOptions;
|
|
38
42
|
};
|
|
39
43
|
export type ShareExternalsOptions = Record<string, ShareAllExternalsOptions>;
|
|
40
|
-
//# sourceMappingURL=external-config.contract.d.ts.map
|
|
@@ -1,28 +1,35 @@
|
|
|
1
1
|
import type { PreparedSkipList, SkipList } from './skip-list.contract.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PathToImport } from '../utils/mapped-path.contract.js';
|
|
3
3
|
import type { NormalizedSharedExternalsConfig, SharedExternalsConfig } from './external-config.contract.js';
|
|
4
4
|
export interface FederationConfig {
|
|
5
5
|
name?: string;
|
|
6
6
|
exposes?: Record<string, string>;
|
|
7
7
|
shared?: SharedExternalsConfig;
|
|
8
|
+
platform?: 'browser' | 'node';
|
|
8
9
|
sharedMappings?: Array<string>;
|
|
10
|
+
chunks?: boolean;
|
|
9
11
|
skip?: SkipList;
|
|
10
12
|
externals?: string[];
|
|
13
|
+
shareScope?: string;
|
|
11
14
|
features?: {
|
|
12
15
|
mappingVersion?: boolean;
|
|
13
16
|
ignoreUnusedDeps?: boolean;
|
|
17
|
+
denseChunking?: boolean;
|
|
14
18
|
};
|
|
15
19
|
}
|
|
16
20
|
export interface NormalizedFederationConfig {
|
|
21
|
+
$type: 'classic';
|
|
17
22
|
name: string;
|
|
18
23
|
exposes: Record<string, string>;
|
|
19
24
|
shared: NormalizedSharedExternalsConfig;
|
|
20
|
-
sharedMappings:
|
|
25
|
+
sharedMappings: PathToImport;
|
|
21
26
|
skip: PreparedSkipList;
|
|
27
|
+
chunks: boolean;
|
|
22
28
|
externals: string[];
|
|
29
|
+
shareScope?: string;
|
|
23
30
|
features: {
|
|
24
31
|
mappingVersion: boolean;
|
|
25
32
|
ignoreUnusedDeps: boolean;
|
|
33
|
+
denseChunking: boolean;
|
|
26
34
|
};
|
|
27
35
|
}
|
|
28
|
-
//# sourceMappingURL=federation-config.contract.d.ts.map
|