@softarc/native-federation 4.0.0-RC2 → 4.0.0-RC4
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/internal.d.ts +1 -1
- package/src/internal.js +1 -1
- package/src/lib/core/build-for-federation.js +5 -5
- package/src/lib/core/bundle-exposed-and-mappings.js +27 -4
- package/src/lib/core/bundle-shared.js +0 -1
- package/src/lib/core/remove-unused-deps.js +7 -5
- package/src/lib/domain/core/federation-info.contract.d.ts +1 -0
- package/src/lib/utils/build-result-map.d.ts +1 -0
- package/src/lib/utils/build-result-map.js +9 -2
- package/src/lib/utils/config-utils.d.ts +2 -0
- package/src/lib/utils/config-utils.js +9 -0
package/package.json
CHANGED
package/src/internal.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { logger, setLogLevel } from './lib/utils/logger.js';
|
|
|
5
5
|
export type { MappedPath } from './lib/domain/utils/mapped-path.contract.js';
|
|
6
6
|
export { RebuildQueue } from './lib/utils/rebuild-queue.js';
|
|
7
7
|
export { AbortedError } from './lib/utils/errors.js';
|
|
8
|
-
export { createBuildResultMap, lookupInResultMap } from './lib/utils/build-result-map.js';
|
|
8
|
+
export { createBuildResultMap, lookupInResultMap, popFromResultMap, } from './lib/utils/build-result-map.js';
|
|
9
9
|
export { writeImportMap } from './lib/core/write-import-map.js';
|
|
10
10
|
export type { NormalizedExternalConfig, NormalizedSharedExternalsConfig, } from './lib/domain/config/external-config.contract.js';
|
|
11
11
|
export type { NormalizedFederationConfig } from './lib/domain/config/federation-config.contract.js';
|
package/src/internal.js
CHANGED
|
@@ -4,5 +4,5 @@ export * from './lib/utils/errors.js';
|
|
|
4
4
|
export { logger, setLogLevel } from './lib/utils/logger.js';
|
|
5
5
|
export { RebuildQueue } from './lib/utils/rebuild-queue.js';
|
|
6
6
|
export { AbortedError } from './lib/utils/errors.js';
|
|
7
|
-
export { createBuildResultMap, lookupInResultMap } from './lib/utils/build-result-map.js';
|
|
7
|
+
export { createBuildResultMap, lookupInResultMap, popFromResultMap, } from './lib/utils/build-result-map.js';
|
|
8
8
|
export { writeImportMap } from './lib/core/write-import-map.js';
|
|
@@ -6,6 +6,7 @@ import { logger } from '../utils/logger.js';
|
|
|
6
6
|
import { getCachePath } from './../utils/bundle-caching.js';
|
|
7
7
|
import { normalizePackageName } from '../utils/normalize.js';
|
|
8
8
|
import { AbortedError } from '../utils/errors.js';
|
|
9
|
+
import { resolveProjectName } from '../utils/config-utils.js';
|
|
9
10
|
export const defaultBuildParams = {
|
|
10
11
|
skipMappingsAndExposed: false,
|
|
11
12
|
skipShared: false,
|
|
@@ -22,11 +23,7 @@ export async function buildForFederation(config, fedOptions, externals, buildPar
|
|
|
22
23
|
throw new AbortedError('[buildForFederation] After exposed-and-mappings bundle');
|
|
23
24
|
}
|
|
24
25
|
const exposedInfo = !artifactInfo ? describeExposed(config, fedOptions) : artifactInfo.exposes;
|
|
25
|
-
const
|
|
26
|
-
if (normalizedCacheFolder.length < 1) {
|
|
27
|
-
logger.warn("Project name in 'federation.config.js' is empty, defaulting to 'shell' cache folder (could collide with other projects in the workspace).");
|
|
28
|
-
}
|
|
29
|
-
const cacheProjectFolder = normalizedCacheFolder.length < 1 ? 'shell' : normalizedCacheFolder;
|
|
26
|
+
const cacheProjectFolder = resolveProjectName(config);
|
|
30
27
|
const pathToCache = getCachePath(fedOptions.workspaceRoot, cacheProjectFolder);
|
|
31
28
|
if (!buildParams.skipShared && sharedCache.externals.length > 0) {
|
|
32
29
|
logger.info('Checksum matched, re-using cached externals.');
|
|
@@ -92,6 +89,9 @@ export async function buildForFederation(config, fedOptions, externals, buildPar
|
|
|
92
89
|
if (sharedCache.chunks) {
|
|
93
90
|
federationInfo.chunks = sharedCache.chunks;
|
|
94
91
|
}
|
|
92
|
+
if (artifactInfo?.chunks) {
|
|
93
|
+
federationInfo.chunks = { ...(federationInfo.chunks ?? {}), ...artifactInfo?.chunks };
|
|
94
|
+
}
|
|
95
95
|
writeFederationInfo(federationInfo, fedOptions);
|
|
96
96
|
writeImportMap(sharedCache, fedOptions);
|
|
97
97
|
return federationInfo;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { createBuildResultMap,
|
|
3
|
+
import { createBuildResultMap, popFromResultMap } from '../utils/build-result-map.js';
|
|
4
4
|
import { bundle } from '../utils/build-utils.js';
|
|
5
5
|
import { logger } from '../utils/logger.js';
|
|
6
6
|
import { normalize } from '../utils/normalize.js';
|
|
7
7
|
import { AbortedError } from '../utils/errors.js';
|
|
8
|
+
import { rewriteChunkImports } from '../utils/rewrite-chunk-imports.js';
|
|
8
9
|
export async function bundleExposedAndMappings(config, fedOptions, externals, signal) {
|
|
9
10
|
if (signal?.aborted) {
|
|
10
11
|
throw new AbortedError('[bundle-exposed-and-mappings] Aborted before bundling');
|
|
@@ -33,6 +34,8 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, si
|
|
|
33
34
|
watch: fedOptions.watch,
|
|
34
35
|
mappedPaths: config.sharedMappings,
|
|
35
36
|
kind: 'mapping-or-exposed',
|
|
37
|
+
chunks: (typeof fedOptions.chunks === 'boolean' && fedOptions.chunks) ||
|
|
38
|
+
(typeof fedOptions.chunks === 'object' && !!fedOptions.chunks.enable),
|
|
36
39
|
hash,
|
|
37
40
|
optimizedMappings: config.features.ignoreUnusedDeps,
|
|
38
41
|
signal,
|
|
@@ -49,10 +52,13 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, si
|
|
|
49
52
|
}
|
|
50
53
|
const resultMap = createBuildResultMap(result, hash);
|
|
51
54
|
const sharedResult = [];
|
|
55
|
+
const entryFiles = [];
|
|
56
|
+
// Pick shared-mappings
|
|
52
57
|
for (const item of shared) {
|
|
58
|
+
const distEntryFile = popFromResultMap(resultMap, item.outName);
|
|
53
59
|
sharedResult.push({
|
|
54
60
|
packageName: item.key,
|
|
55
|
-
outFileName:
|
|
61
|
+
outFileName: path.basename(distEntryFile),
|
|
56
62
|
requiredVersion: '',
|
|
57
63
|
singleton: true,
|
|
58
64
|
strictVersion: false,
|
|
@@ -63,20 +69,37 @@ export async function bundleExposedAndMappings(config, fedOptions, externals, si
|
|
|
63
69
|
entryPoint: normalize(path.normalize(item.fileName)),
|
|
64
70
|
},
|
|
65
71
|
});
|
|
72
|
+
entryFiles.push(distEntryFile);
|
|
66
73
|
}
|
|
67
74
|
const exposedResult = [];
|
|
75
|
+
// Pick exposed-modules
|
|
68
76
|
for (const item of exposes) {
|
|
77
|
+
const distEntryFile = popFromResultMap(resultMap, item.outName);
|
|
69
78
|
exposedResult.push({
|
|
70
79
|
key: item.key,
|
|
71
|
-
outFileName:
|
|
80
|
+
outFileName: path.basename(distEntryFile),
|
|
72
81
|
dev: !fedOptions.dev
|
|
73
82
|
? undefined
|
|
74
83
|
: {
|
|
75
84
|
entryPoint: normalize(path.join(fedOptions.workspaceRoot, item.fileName)),
|
|
76
85
|
},
|
|
77
86
|
});
|
|
87
|
+
entryFiles.push(distEntryFile);
|
|
78
88
|
}
|
|
79
|
-
|
|
89
|
+
// Remove .map files
|
|
90
|
+
Object.keys(resultMap)
|
|
91
|
+
.filter(f => f.endsWith('.map'))
|
|
92
|
+
.forEach(f => popFromResultMap(resultMap, f));
|
|
93
|
+
// Process remaining chunks and lazy loaded internal modules
|
|
94
|
+
let exportedChunks = undefined;
|
|
95
|
+
if (typeof fedOptions.chunks === 'object' && fedOptions.chunks.dense === true) {
|
|
96
|
+
for (const entryFile of entryFiles)
|
|
97
|
+
rewriteChunkImports(entryFile);
|
|
98
|
+
exportedChunks = {
|
|
99
|
+
['mapping-or-exposed']: Object.values(resultMap).map(chunk => path.basename(chunk)),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return { mappings: sharedResult, exposes: exposedResult, chunks: exportedChunks };
|
|
80
103
|
}
|
|
81
104
|
export function describeExposed(config, options) {
|
|
82
105
|
const result = [];
|
|
@@ -92,7 +92,6 @@ export async function bundleShared(sharedBundles, config, fedOptions, externals,
|
|
|
92
92
|
}
|
|
93
93
|
const outFileNames = [...expectedResults];
|
|
94
94
|
const result = buildResult(packageInfos, sharedBundles, outFileNames);
|
|
95
|
-
// TODO: Decide whether/when to add .map files
|
|
96
95
|
const chunks = bundleResult.filter(br => !br.fileName.endsWith('.map') &&
|
|
97
96
|
!result.find(r => r.outFileName === path.basename(br.fileName)));
|
|
98
97
|
/**
|
|
@@ -5,6 +5,7 @@ import { cwd } from 'process';
|
|
|
5
5
|
import { getPackageInfo } from '../utils/package-info.js';
|
|
6
6
|
import { getExternalImports as extractExternalImports } from '../utils/get-external-imports.js';
|
|
7
7
|
import { normalizePackageName } from '../utils/normalize.js';
|
|
8
|
+
import { resolveProjectName } from '../utils/config-utils.js';
|
|
8
9
|
export function removeUnusedDeps(config, main, workspaceRoot) {
|
|
9
10
|
const fileInfos = getProjectData(main, cwd(), {
|
|
10
11
|
includeExternalLibraries: true,
|
|
@@ -12,7 +13,8 @@ export function removeUnusedDeps(config, main, workspaceRoot) {
|
|
|
12
13
|
const usedDeps = findUsedDeps(fileInfos, workspaceRoot, config);
|
|
13
14
|
const usedPackageNames = usedDeps.usedPackageNames;
|
|
14
15
|
const usedMappings = usedDeps.usedMappings;
|
|
15
|
-
const
|
|
16
|
+
const projectName = resolveProjectName(config);
|
|
17
|
+
const usedPackageNamesWithTransient = addTransientDeps(usedPackageNames, workspaceRoot, projectName);
|
|
16
18
|
const filteredShared = filterShared(config, usedPackageNamesWithTransient);
|
|
17
19
|
return {
|
|
18
20
|
...config,
|
|
@@ -45,7 +47,7 @@ function findUsedDeps(fileInfos, workspaceRoot, config) {
|
|
|
45
47
|
}
|
|
46
48
|
return { usedPackageNames, usedMappings };
|
|
47
49
|
}
|
|
48
|
-
function addTransientDeps(packages, workspaceRoot) {
|
|
50
|
+
function addTransientDeps(packages, workspaceRoot, projectName) {
|
|
49
51
|
const packagesAndPeers = new Set([...packages]);
|
|
50
52
|
const discovered = new Set(packagesAndPeers);
|
|
51
53
|
const stack = [...packagesAndPeers];
|
|
@@ -58,7 +60,7 @@ function addTransientDeps(packages, workspaceRoot) {
|
|
|
58
60
|
if (!pInfo) {
|
|
59
61
|
continue;
|
|
60
62
|
}
|
|
61
|
-
const peerDeps = getExternalImports(pInfo, workspaceRoot);
|
|
63
|
+
const peerDeps = getExternalImports(pInfo, workspaceRoot, projectName);
|
|
62
64
|
for (const peerDep of peerDeps) {
|
|
63
65
|
if (!discovered.has(peerDep)) {
|
|
64
66
|
discovered.add(peerDep);
|
|
@@ -69,10 +71,10 @@ function addTransientDeps(packages, workspaceRoot) {
|
|
|
69
71
|
}
|
|
70
72
|
return packagesAndPeers;
|
|
71
73
|
}
|
|
72
|
-
function getExternalImports(pInfo, workspaceRoot) {
|
|
74
|
+
function getExternalImports(pInfo, workspaceRoot, projectName) {
|
|
73
75
|
const encodedPackageName = normalizePackageName(pInfo.packageName);
|
|
74
76
|
const cacheFileName = `${encodedPackageName}-${pInfo.version}.deps.json`;
|
|
75
|
-
const cachePath = path.join(workspaceRoot, 'node_modules/.cache/native-federation/_externals-metadata');
|
|
77
|
+
const cachePath = path.join(workspaceRoot, 'node_modules/.cache/native-federation/_externals-metadata', projectName);
|
|
76
78
|
const cacheFilePath = path.join(cachePath, cacheFileName);
|
|
77
79
|
const cacheHit = fs.existsSync(cacheFilePath);
|
|
78
80
|
let peerDeps;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { NFBuildAdapterResult } from '../domain/core/build-adapter.contract.js';
|
|
2
2
|
export declare function createBuildResultMap(buildResult: NFBuildAdapterResult[], isHashed: boolean): Record<string, string>;
|
|
3
3
|
export declare function lookupInResultMap(map: Record<string, string>, requestName: string): string;
|
|
4
|
+
export declare function popFromResultMap(map: Record<string, string>, requestName: string): string;
|
|
@@ -11,11 +11,18 @@ export function createBuildResultMap(buildResult, isHashed) {
|
|
|
11
11
|
const part2 = resultName.substring(end);
|
|
12
12
|
requestName = part1 + part2;
|
|
13
13
|
}
|
|
14
|
-
map[requestName] =
|
|
14
|
+
map[requestName] = item.fileName;
|
|
15
15
|
}
|
|
16
16
|
return map;
|
|
17
17
|
}
|
|
18
18
|
export function lookupInResultMap(map, requestName) {
|
|
19
19
|
const key = path.basename(requestName);
|
|
20
|
-
|
|
20
|
+
// path.basename is to maintain backwards compatible
|
|
21
|
+
return path.basename(map[key]);
|
|
22
|
+
}
|
|
23
|
+
export function popFromResultMap(map, requestName) {
|
|
24
|
+
const key = path.basename(requestName);
|
|
25
|
+
const out = map[key];
|
|
26
|
+
delete map[key];
|
|
27
|
+
return out;
|
|
21
28
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { logger } from './logger.js';
|
|
2
|
+
import { normalizePackageName } from './normalize.js';
|
|
3
|
+
export function resolveProjectName(config) {
|
|
4
|
+
const normalizedProjectName = normalizePackageName(config.name);
|
|
5
|
+
if (normalizedProjectName.length < 1) {
|
|
6
|
+
logger.warn("Project name in 'federation.config.js' is empty, defaulting to 'shell' cache folder (could collide with other projects in the workspace).");
|
|
7
|
+
}
|
|
8
|
+
return normalizedProjectName.length < 1 ? 'shell' : normalizedProjectName;
|
|
9
|
+
}
|