@mf-toolkit/shared-inspector 0.1.1 → 0.3.0
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/README.md +63 -9
- package/dist/analyzer/analyze-federation.d.ts +9 -0
- package/dist/analyzer/analyze-federation.d.ts.map +1 -0
- package/dist/analyzer/analyze-federation.js +157 -0
- package/dist/analyzer/analyze-federation.js.map +1 -0
- package/dist/collector/extract-mfp-shared.d.ts +14 -0
- package/dist/collector/extract-mfp-shared.d.ts.map +1 -0
- package/dist/collector/extract-mfp-shared.js +40 -0
- package/dist/collector/extract-mfp-shared.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/webpack.d.ts.map +1 -1
- package/dist/plugins/webpack.js +16 -3
- package/dist/plugins/webpack.js.map +1 -1
- package/dist/reporter/format-federation-report.d.ts +13 -0
- package/dist/reporter/format-federation-report.d.ts.map +1 -0
- package/dist/reporter/format-federation-report.js +77 -0
- package/dist/reporter/format-federation-report.js.map +1 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/zvitaly7/mf-toolkit/blob/main/LICENSE)
|
|
6
6
|
[](https://nodejs.org)
|
|
7
7
|
|
|
8
|
-
> ⚠️ **Work in progress.** This package is fully tested (
|
|
8
|
+
> ⚠️ **Work in progress.** This package is fully tested (252 tests) and published to npm. The API is stable but may receive minor changes before the official stable release.
|
|
9
9
|
|
|
10
10
|
Build-time analyser for Module Federation `shared` dependencies. Two-phase architecture: **collect facts → analyse facts**.
|
|
11
11
|
|
|
@@ -78,6 +78,8 @@ const report = await inspect({
|
|
|
78
78
|
|
|
79
79
|
### Webpack plugin
|
|
80
80
|
|
|
81
|
+
`sharedConfig` is optional — the plugin auto-extracts it from `ModuleFederationPlugin` when not provided:
|
|
82
|
+
|
|
81
83
|
```typescript
|
|
82
84
|
import { MfSharedInspectorPlugin } from '@mf-toolkit/shared-inspector/webpack';
|
|
83
85
|
|
|
@@ -88,20 +90,25 @@ module.exports = {
|
|
|
88
90
|
shared: { react: { singleton: true }, mobx: { singleton: true } },
|
|
89
91
|
}),
|
|
90
92
|
|
|
93
|
+
// sharedConfig not needed — auto-extracted from ModuleFederationPlugin above
|
|
91
94
|
new MfSharedInspectorPlugin({
|
|
92
95
|
sourceDirs: ['./src'],
|
|
93
|
-
sharedConfig: {
|
|
94
|
-
react: { singleton: true, requiredVersion: '^19.0.0' },
|
|
95
|
-
mobx: { singleton: true },
|
|
96
|
-
},
|
|
97
|
-
tsconfigPath: './tsconfig.json', // resolve @alias/* imports
|
|
98
96
|
warn: true,
|
|
99
|
-
writeManifest: true,
|
|
97
|
+
writeManifest: true, // writes project-manifest.json for CI aggregation
|
|
100
98
|
}),
|
|
101
99
|
],
|
|
102
100
|
};
|
|
103
101
|
```
|
|
104
102
|
|
|
103
|
+
Pass `sharedConfig` explicitly to override auto-extraction:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
new MfSharedInspectorPlugin({
|
|
107
|
+
sourceDirs: ['./src'],
|
|
108
|
+
sharedConfig: { react: { singleton: true, requiredVersion: '^18.0.0' } },
|
|
109
|
+
})
|
|
110
|
+
```
|
|
111
|
+
|
|
105
112
|
## Analysis depth
|
|
106
113
|
|
|
107
114
|
| Depth | What it finds | Speed |
|
|
@@ -197,7 +204,32 @@ jobs:
|
|
|
197
204
|
path: project-manifest.json
|
|
198
205
|
```
|
|
199
206
|
|
|
200
|
-
|
|
207
|
+
Each MF manifest can then be aggregated for cross-team analysis:
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
import { analyzeFederation, formatFederationReport } from '@mf-toolkit/shared-inspector';
|
|
211
|
+
|
|
212
|
+
const report = analyzeFederation([checkoutManifest, catalogManifest, cartManifest]);
|
|
213
|
+
console.log(formatFederationReport(report));
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
[MfSharedInspector] federation analysis (3 MFs)
|
|
218
|
+
|
|
219
|
+
Version conflicts (singleton negotiation will fail):
|
|
220
|
+
⚠ react — checkout: ^17.0.0, catalog: ^18.0.0
|
|
221
|
+
|
|
222
|
+
Singleton mismatches (add singleton: true to all MFs):
|
|
223
|
+
⚠ mobx — singleton in [checkout], not singleton in [catalog, cart]
|
|
224
|
+
|
|
225
|
+
Host gaps (add to shared — each MF bundles its own copy):
|
|
226
|
+
→ axios — used by [checkout, catalog], not in shared
|
|
227
|
+
|
|
228
|
+
Ghost shares (remove from shared — no other MF benefits):
|
|
229
|
+
✗ lodash — shared only by cart, unused by all other MFs
|
|
230
|
+
|
|
231
|
+
Total: 3 MFs, 1 version conflicts, 1 singleton mismatches, 1 host gaps, 1 ghost shares
|
|
232
|
+
```
|
|
201
233
|
|
|
202
234
|
## API reference
|
|
203
235
|
|
|
@@ -224,8 +256,22 @@ jobs:
|
|
|
224
256
|
| `additionalCandidates` | `string[]` | `[]` | Extend built-in candidates list |
|
|
225
257
|
| `additionalSingletonRisks` | `string[]` | `[]` | Extend built-in singleton-risk list |
|
|
226
258
|
|
|
259
|
+
### `analyzeFederation(manifests, options?)`
|
|
260
|
+
|
|
261
|
+
Accepts N `ProjectManifest` objects (one per microfrontend) and returns a `FederationReport`.
|
|
262
|
+
|
|
263
|
+
| Option | Type | Default | Description |
|
|
264
|
+
|--------|------|---------|-------------|
|
|
265
|
+
| `alwaysShared` | `string[]` | `['react','react-dom']` | Exclude from ghost/gap detection |
|
|
266
|
+
|
|
267
|
+
### `formatFederationReport(report)`
|
|
268
|
+
|
|
269
|
+
Formats a `FederationReport` as a human-readable terminal string.
|
|
270
|
+
|
|
227
271
|
## Detection categories
|
|
228
272
|
|
|
273
|
+
### Per-project (`analyzeProject`)
|
|
274
|
+
|
|
229
275
|
| Category | Type | Description |
|
|
230
276
|
|----------|------|-------------|
|
|
231
277
|
| `mismatched` | Deterministic | `requiredVersion` doesn't satisfy installed version |
|
|
@@ -236,12 +282,20 @@ jobs:
|
|
|
236
282
|
|
|
237
283
|
*Within the visibility of the chosen depth.*
|
|
238
284
|
|
|
285
|
+
### Cross-MF (`analyzeFederation`)
|
|
286
|
+
|
|
287
|
+
| Category | Type | Description |
|
|
288
|
+
|----------|------|-------------|
|
|
289
|
+
| `versionConflicts` | Deterministic | `requiredVersion` ranges across MFs have no overlap |
|
|
290
|
+
| `singletonMismatches` | Deterministic | `singleton: true` in some MFs, absent in others |
|
|
291
|
+
| `hostGaps` | Heuristic | Package used by 2+ MFs but not declared in `shared` by anyone |
|
|
292
|
+
| `ghostShares` | Heuristic | Package in `shared` of one MF, unused/unshared by all others |
|
|
293
|
+
|
|
239
294
|
## Known limitations
|
|
240
295
|
|
|
241
296
|
- **TypeScript path aliases without `tsconfigPath`**: aliased imports are treated as external package names. Pass `tsconfigPath` to resolve them correctly.
|
|
242
297
|
- **Dynamic imports with variables** (`import(moduleName)`): not analysed — requires runtime information.
|
|
243
298
|
- **Exact tsconfig alias patterns** (non-wildcard, e.g. `"@root": ["."]`): not supported, only `"@alias/*"` wildcard form.
|
|
244
|
-
- **`analyzeFederation()`** (cross-MF analysis): v0.2.
|
|
245
299
|
|
|
246
300
|
## Demo
|
|
247
301
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ProjectManifest, FederationAnalysisOptions, FederationReport } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cross-MF analysis: accepts N project manifests and detects federation-level issues
|
|
4
|
+
* that are invisible when analysing each MF in isolation.
|
|
5
|
+
*
|
|
6
|
+
* Pure function — no I/O, no side effects.
|
|
7
|
+
*/
|
|
8
|
+
export declare function analyzeFederation(manifests: ProjectManifest[], options?: FederationAnalysisOptions): FederationReport;
|
|
9
|
+
//# sourceMappingURL=analyze-federation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-federation.d.ts","sourceRoot":"","sources":["../../src/analyzer/analyze-federation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,yBAAyB,EACzB,gBAAgB,EAKjB,MAAM,aAAa,CAAC;AAmBrB;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,eAAe,EAAE,EAC5B,OAAO,CAAC,EAAE,yBAAyB,GAClC,gBAAgB,CAwJlB"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import semver from 'semver';
|
|
2
|
+
const DEFAULT_ALWAYS_SHARED = ['react', 'react-dom'];
|
|
3
|
+
/**
|
|
4
|
+
* Returns true when two semver ranges have at least one version in common.
|
|
5
|
+
* Strategy: the max of the two minimums must satisfy both ranges.
|
|
6
|
+
* e.g. ^18.0.0 and ^18.2.0 → max(18.0.0, 18.2.0) = 18.2.0 → satisfies both → compatible.
|
|
7
|
+
* e.g. ^17.0.0 and ^18.0.0 → max(17.0.0, 18.0.0) = 18.0.0 → fails ^17 → conflict.
|
|
8
|
+
*/
|
|
9
|
+
function rangesOverlap(a, b) {
|
|
10
|
+
if (!semver.validRange(a) || !semver.validRange(b))
|
|
11
|
+
return true; // unknown → assume ok
|
|
12
|
+
const minA = semver.minVersion(a);
|
|
13
|
+
const minB = semver.minVersion(b);
|
|
14
|
+
if (!minA || !minB)
|
|
15
|
+
return true;
|
|
16
|
+
const candidate = semver.gt(minA, minB) ? minA : minB;
|
|
17
|
+
return semver.satisfies(candidate, a) && semver.satisfies(candidate, b);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Cross-MF analysis: accepts N project manifests and detects federation-level issues
|
|
21
|
+
* that are invisible when analysing each MF in isolation.
|
|
22
|
+
*
|
|
23
|
+
* Pure function — no I/O, no side effects.
|
|
24
|
+
*/
|
|
25
|
+
export function analyzeFederation(manifests, options) {
|
|
26
|
+
if (manifests.length === 0) {
|
|
27
|
+
return {
|
|
28
|
+
ghostShares: [], hostGaps: [], versionConflicts: [], singletonMismatches: [],
|
|
29
|
+
summary: { totalManifests: 0, ghostSharesCount: 0, hostGapsCount: 0, versionConflictsCount: 0, singletonMismatchesCount: 0 },
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const alwaysShared = new Set(options?.alwaysShared ?? DEFAULT_ALWAYS_SHARED);
|
|
33
|
+
// ── Index manifests ────────────────────────────────────────────────────────
|
|
34
|
+
/** All packages declared in shared config per MF: pkg → Set<mfName> */
|
|
35
|
+
const sharedByPkg = new Map();
|
|
36
|
+
/** All packages observed in source per MF: pkg → Set<mfName> */
|
|
37
|
+
const usedByPkg = new Map();
|
|
38
|
+
/** requiredVersion per MF per pkg: pkg → Map<mfName, version> */
|
|
39
|
+
const versionsByPkg = new Map();
|
|
40
|
+
/**
|
|
41
|
+
* singleton flag per MF per pkg — only for MFs that explicitly set singleton.
|
|
42
|
+
* pkg → Map<mfName, boolean>
|
|
43
|
+
*/
|
|
44
|
+
const explicitSingletonByPkg = new Map();
|
|
45
|
+
for (const manifest of manifests) {
|
|
46
|
+
const mfName = manifest.project.name;
|
|
47
|
+
for (const [pkg, cfg] of Object.entries(manifest.shared.declared)) {
|
|
48
|
+
if (!sharedByPkg.has(pkg))
|
|
49
|
+
sharedByPkg.set(pkg, new Set());
|
|
50
|
+
sharedByPkg.get(pkg).add(mfName);
|
|
51
|
+
if (cfg.requiredVersion) {
|
|
52
|
+
if (!versionsByPkg.has(pkg))
|
|
53
|
+
versionsByPkg.set(pkg, new Map());
|
|
54
|
+
versionsByPkg.get(pkg).set(mfName, cfg.requiredVersion);
|
|
55
|
+
}
|
|
56
|
+
if (cfg.singleton !== undefined) {
|
|
57
|
+
if (!explicitSingletonByPkg.has(pkg))
|
|
58
|
+
explicitSingletonByPkg.set(pkg, new Map());
|
|
59
|
+
explicitSingletonByPkg.get(pkg).set(mfName, cfg.singleton);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const pkg of manifest.usage.resolvedPackages) {
|
|
63
|
+
if (!usedByPkg.has(pkg))
|
|
64
|
+
usedByPkg.set(pkg, new Set());
|
|
65
|
+
usedByPkg.get(pkg).add(mfName);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// ── Ghost shares ───────────────────────────────────────────────────────────
|
|
69
|
+
// Package shared by exactly one MF with no other MF sharing or benefiting from it.
|
|
70
|
+
// Requires at least 2 manifests — with one MF there's nothing to compare.
|
|
71
|
+
const ghostShares = [];
|
|
72
|
+
if (manifests.length > 1) {
|
|
73
|
+
for (const [pkg, sharedByMfs] of sharedByPkg) {
|
|
74
|
+
if (alwaysShared.has(pkg))
|
|
75
|
+
continue;
|
|
76
|
+
if (sharedByMfs.size !== 1)
|
|
77
|
+
continue; // shared by multiple → not a ghost
|
|
78
|
+
const soloMf = [...sharedByMfs][0];
|
|
79
|
+
const usedByMfs = usedByPkg.get(pkg) ?? new Set();
|
|
80
|
+
// Other MFs that use the pkg but don't declare it in shared
|
|
81
|
+
const usedUnsharedBy = [...usedByMfs].filter((mf) => mf !== soloMf && !sharedByPkg.get(pkg)?.has(mf));
|
|
82
|
+
const otherMfsUseIt = [...usedByMfs].some((mf) => mf !== soloMf);
|
|
83
|
+
if (!otherMfsUseIt) {
|
|
84
|
+
// No other MF uses it at all — pure ghost share
|
|
85
|
+
ghostShares.push({ package: pkg, sharedBy: soloMf, usedUnsharedBy: [] });
|
|
86
|
+
}
|
|
87
|
+
else if (usedUnsharedBy.length > 0) {
|
|
88
|
+
// Other MFs use it but haven't declared it in shared
|
|
89
|
+
ghostShares.push({ package: pkg, sharedBy: soloMf, usedUnsharedBy });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// ── Host gaps ──────────────────────────────────────────────────────────────
|
|
94
|
+
// Package used by 2+ MFs but not declared in shared by anyone.
|
|
95
|
+
const hostGaps = [];
|
|
96
|
+
for (const [pkg, usedByMfs] of usedByPkg) {
|
|
97
|
+
if (usedByMfs.size < 2)
|
|
98
|
+
continue;
|
|
99
|
+
if (alwaysShared.has(pkg))
|
|
100
|
+
continue;
|
|
101
|
+
const sharedByMfs = sharedByPkg.get(pkg);
|
|
102
|
+
if (sharedByMfs && sharedByMfs.size > 0)
|
|
103
|
+
continue;
|
|
104
|
+
hostGaps.push({ package: pkg, missingIn: [...usedByMfs] });
|
|
105
|
+
}
|
|
106
|
+
// ── Version conflicts ──────────────────────────────────────────────────────
|
|
107
|
+
// Package where requiredVersion ranges across MFs have no overlap.
|
|
108
|
+
const versionConflicts = [];
|
|
109
|
+
for (const [pkg, mfVersions] of versionsByPkg) {
|
|
110
|
+
if (mfVersions.size < 2)
|
|
111
|
+
continue;
|
|
112
|
+
const ranges = [...mfVersions.values()];
|
|
113
|
+
const validRanges = ranges.filter((r) => semver.validRange(r));
|
|
114
|
+
if (validRanges.length < 2)
|
|
115
|
+
continue;
|
|
116
|
+
// Check all pairs of ranges for overlap — any non-overlapping pair is a conflict
|
|
117
|
+
let hasConflict = false;
|
|
118
|
+
outer: for (let i = 0; i < validRanges.length; i++) {
|
|
119
|
+
for (let j = i + 1; j < validRanges.length; j++) {
|
|
120
|
+
if (!rangesOverlap(validRanges[i], validRanges[j])) {
|
|
121
|
+
hasConflict = true;
|
|
122
|
+
break outer;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (hasConflict) {
|
|
127
|
+
versionConflicts.push({ package: pkg, versions: Object.fromEntries(mfVersions) });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// ── Singleton mismatches ───────────────────────────────────────────────────
|
|
131
|
+
// Package where some MFs declare singleton: true and others don't (false or absent).
|
|
132
|
+
const singletonMismatches = [];
|
|
133
|
+
for (const [pkg, sharedByMfs] of sharedByPkg) {
|
|
134
|
+
if (sharedByMfs.size < 2)
|
|
135
|
+
continue;
|
|
136
|
+
const explicitMap = explicitSingletonByPkg.get(pkg) ?? new Map();
|
|
137
|
+
const singletonIn = [...sharedByMfs].filter((mf) => explicitMap.get(mf) === true);
|
|
138
|
+
const nonSingletonIn = [...sharedByMfs].filter((mf) => explicitMap.get(mf) !== true);
|
|
139
|
+
if (singletonIn.length > 0 && nonSingletonIn.length > 0) {
|
|
140
|
+
singletonMismatches.push({ package: pkg, singletonIn, nonSingletonIn });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
ghostShares,
|
|
145
|
+
hostGaps,
|
|
146
|
+
versionConflicts,
|
|
147
|
+
singletonMismatches,
|
|
148
|
+
summary: {
|
|
149
|
+
totalManifests: manifests.length,
|
|
150
|
+
ghostSharesCount: ghostShares.length,
|
|
151
|
+
hostGapsCount: hostGaps.length,
|
|
152
|
+
versionConflictsCount: versionConflicts.length,
|
|
153
|
+
singletonMismatchesCount: singletonMismatches.length,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=analyze-federation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-federation.js","sourceRoot":"","sources":["../../src/analyzer/analyze-federation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SharedDepConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Tries to extract the `shared` config from a ModuleFederationPlugin instance
|
|
4
|
+
* found in `compiler.options.plugins`.
|
|
5
|
+
*
|
|
6
|
+
* Returns `null` when:
|
|
7
|
+
* - No ModuleFederationPlugin is found
|
|
8
|
+
* - The plugin exists but has no `shared` option
|
|
9
|
+
* - The plugin uses an unknown internal storage format
|
|
10
|
+
*
|
|
11
|
+
* This intentionally uses `any` to remain independent of webpack/rspack types.
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractSharedFromCompiler(compiler: any): Record<string, SharedDepConfig> | null;
|
|
14
|
+
//# sourceMappingURL=extract-mfp-shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-mfp-shared.d.ts","sourceRoot":"","sources":["../../src/collector/extract-mfp-shared.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAWnD;;;;;;;;;;GAUG;AAEH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,IAAI,CAoB/F"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { parseSharedConfig } from './parse-shared-config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Known constructor names for Module Federation plugins across bundlers.
|
|
4
|
+
* Checked by name to avoid a hard runtime dependency on webpack/rspack.
|
|
5
|
+
*/
|
|
6
|
+
const MFP_CONSTRUCTOR_NAMES = new Set([
|
|
7
|
+
'ModuleFederationPlugin', // webpack 5
|
|
8
|
+
'ModuleFederationPluginV2', // some community forks
|
|
9
|
+
]);
|
|
10
|
+
/**
|
|
11
|
+
* Tries to extract the `shared` config from a ModuleFederationPlugin instance
|
|
12
|
+
* found in `compiler.options.plugins`.
|
|
13
|
+
*
|
|
14
|
+
* Returns `null` when:
|
|
15
|
+
* - No ModuleFederationPlugin is found
|
|
16
|
+
* - The plugin exists but has no `shared` option
|
|
17
|
+
* - The plugin uses an unknown internal storage format
|
|
18
|
+
*
|
|
19
|
+
* This intentionally uses `any` to remain independent of webpack/rspack types.
|
|
20
|
+
*/
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
+
export function extractSharedFromCompiler(compiler) {
|
|
23
|
+
const plugins = compiler?.options?.plugins;
|
|
24
|
+
if (!Array.isArray(plugins))
|
|
25
|
+
return null;
|
|
26
|
+
const mfPlugin = plugins.find(
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
(p) => p != null && MFP_CONSTRUCTOR_NAMES.has(p.constructor?.name));
|
|
29
|
+
if (!mfPlugin)
|
|
30
|
+
return null;
|
|
31
|
+
// webpack 5 stores options as `this._options` (private but stable across 5.x)
|
|
32
|
+
// Fall back to `this.options` used by some community variants
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
const raw = mfPlugin._options?.shared ?? mfPlugin.options?.shared;
|
|
35
|
+
if (raw == null)
|
|
36
|
+
return null;
|
|
37
|
+
const parsed = parseSharedConfig(raw);
|
|
38
|
+
return Object.keys(parsed).length > 0 ? parsed : null;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=extract-mfp-shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-mfp-shared.js","sourceRoot":"","sources":["../../src/collector/extract-mfp-shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D;;;GAGG;AACH,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,wBAAwB,EAAQ,YAAY;IAC5C,0BAA0B,EAAM,uBAAuB;CACxD,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,8DAA8D;AAC9D,MAAM,UAAU,yBAAyB,CAAC,QAAa;IACrD,MAAM,OAAO,GAAc,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC;IACtD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI;IAC3B,8DAA8D;IAC9D,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CACxE,CAAC;IAEF,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,8EAA8E;IAC9E,8DAA8D;IAC9D,8DAA8D;IAC9D,MAAM,GAAG,GAAI,QAAgB,CAAC,QAAQ,EAAE,MAAM,IAAK,QAAgB,CAAC,OAAO,EAAE,MAAM,CAAC;IAEpF,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAE7B,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { buildProjectManifest } from './collector/build-project-manifest.js';
|
|
2
2
|
export { analyzeProject } from './analyzer/analyze-project.js';
|
|
3
|
+
export { analyzeFederation } from './analyzer/analyze-federation.js';
|
|
3
4
|
export { inspect } from './inspect.js';
|
|
4
5
|
export { formatReport } from './reporter/format-report.js';
|
|
6
|
+
export { formatFederationReport } from './reporter/format-federation-report.js';
|
|
5
7
|
export { writeReport, writeManifest } from './reporter/write-report.js';
|
|
6
|
-
export type { ProjectManifest, ProjectReport, CollectorOptions, AnalysisOptions, SharedDepConfig, PackageOccurrence, UnusedEntry, CandidateEntry, MismatchedEntry, SingletonRiskEntry, } from './types.js';
|
|
8
|
+
export type { ProjectManifest, ProjectReport, CollectorOptions, AnalysisOptions, SharedDepConfig, PackageOccurrence, UnusedEntry, CandidateEntry, MismatchedEntry, SingletonRiskEntry, EagerRiskEntry, FederationAnalysisOptions, FederationReport, GhostShareEntry, HostGapEntry, VersionConflictEntry, SingletonMismatchEntry, } from './types.js';
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAGxE,YAAY,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// ─── Two-phase API ────────────────────────────────────────────────────────────
|
|
2
2
|
export { buildProjectManifest } from './collector/build-project-manifest.js';
|
|
3
3
|
export { analyzeProject } from './analyzer/analyze-project.js';
|
|
4
|
+
export { analyzeFederation } from './analyzer/analyze-federation.js';
|
|
4
5
|
// ─── Shortcut API ─────────────────────────────────────────────────────────────
|
|
5
6
|
export { inspect } from './inspect.js';
|
|
6
7
|
// ─── Reporter ─────────────────────────────────────────────────────────────────
|
|
7
8
|
export { formatReport } from './reporter/format-report.js';
|
|
9
|
+
export { formatFederationReport } from './reporter/format-federation-report.js';
|
|
8
10
|
export { writeReport, writeManifest } from './reporter/write-report.js';
|
|
9
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,iFAAiF;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,iFAAiF;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webpack.d.ts","sourceRoot":"","sources":["../../src/plugins/webpack.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"webpack.d.ts","sourceRoot":"","sources":["../../src/plugins/webpack.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAUxD,UAAU,kBAAkB;IAC1B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,KAAK,EAAE,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,EAAE;QACL,YAAY,EAAE;YACZ,UAAU,CACR,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,WAAW,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,GACrD,IAAI,CAAC;SACT,CAAC;KACH,CAAC;CACH;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,OAAO,CAAuB;gBAE1B,OAAO,EAAE,oBAAoB;IAIzC,KAAK,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;CA2GvC"}
|
package/dist/plugins/webpack.js
CHANGED
|
@@ -3,6 +3,7 @@ import { buildProjectManifest } from '../collector/build-project-manifest.js';
|
|
|
3
3
|
import { analyzeProject } from '../analyzer/analyze-project.js';
|
|
4
4
|
import { formatReport } from '../reporter/format-report.js';
|
|
5
5
|
import { writeManifest } from '../reporter/write-report.js';
|
|
6
|
+
import { extractSharedFromCompiler } from '../collector/extract-mfp-shared.js';
|
|
6
7
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
7
8
|
const PLUGIN_NAME = 'MfSharedInspectorPlugin';
|
|
8
9
|
/**
|
|
@@ -29,7 +30,7 @@ export class MfSharedInspectorPlugin {
|
|
|
29
30
|
}
|
|
30
31
|
apply(compiler) {
|
|
31
32
|
compiler.hooks.afterCompile.tapPromise(PLUGIN_NAME, async (compilation) => {
|
|
32
|
-
const { sourceDirs, depth = 'local-graph', sharedConfig, kind, packageJsonPath, extensions, ignore, parser, analysis, warn = true, failOn, writeManifest: shouldWriteManifest = false, outputDir = '.', } = this.options;
|
|
33
|
+
const { sourceDirs, depth = 'local-graph', sharedConfig: explicitSharedConfig, kind, packageJsonPath, extensions, ignore, tsconfigPath, workspacePackages, parser, analysis, warn = true, failOn, writeManifest: shouldWriteManifest = false, outputDir = '.', } = this.options;
|
|
33
34
|
// Resolve name from webpack compiler, fallback to context dir name
|
|
34
35
|
const name = compiler.options.name ?? basename(compiler.context);
|
|
35
36
|
// Resolve paths relative to compiler.context when not absolute
|
|
@@ -41,6 +42,14 @@ export class MfSharedInspectorPlugin {
|
|
|
41
42
|
? outputDir
|
|
42
43
|
: join(compiler.context, outputDir);
|
|
43
44
|
try {
|
|
45
|
+
// Use explicit sharedConfig if provided, otherwise auto-extract from
|
|
46
|
+
// ModuleFederationPlugin found in compiler.options.plugins
|
|
47
|
+
const sharedConfig = explicitSharedConfig ?? extractSharedFromCompiler(compiler) ?? {};
|
|
48
|
+
const autoExtracted = !explicitSharedConfig && Object.keys(sharedConfig).length > 0;
|
|
49
|
+
if (autoExtracted && warn) {
|
|
50
|
+
console.log(`[${PLUGIN_NAME}] sharedConfig auto-extracted from ModuleFederationPlugin ` +
|
|
51
|
+
`(${Object.keys(sharedConfig).length} packages)`);
|
|
52
|
+
}
|
|
44
53
|
const manifest = await buildProjectManifest({
|
|
45
54
|
name,
|
|
46
55
|
sourceDirs: resolvedSourceDirs,
|
|
@@ -50,13 +59,16 @@ export class MfSharedInspectorPlugin {
|
|
|
50
59
|
packageJsonPath: resolvedPkgJson,
|
|
51
60
|
extensions,
|
|
52
61
|
ignore,
|
|
62
|
+
tsconfigPath,
|
|
63
|
+
workspacePackages,
|
|
53
64
|
parser,
|
|
54
65
|
});
|
|
55
66
|
const report = analyzeProject(manifest, analysis);
|
|
56
67
|
const hasFindings = report.mismatched.length > 0 ||
|
|
57
68
|
report.unused.length > 0 ||
|
|
58
69
|
report.candidates.length > 0 ||
|
|
59
|
-
report.singletonRisks.length > 0
|
|
70
|
+
report.singletonRisks.length > 0 ||
|
|
71
|
+
report.eagerRisks.length > 0;
|
|
60
72
|
if (warn && hasFindings) {
|
|
61
73
|
console.warn(formatReport(report, {
|
|
62
74
|
name: manifest.project.name,
|
|
@@ -89,7 +101,8 @@ function shouldFailBuild(failOn, report) {
|
|
|
89
101
|
case 'any': return (report.mismatched.length > 0 ||
|
|
90
102
|
report.unused.length > 0 ||
|
|
91
103
|
report.candidates.length > 0 ||
|
|
92
|
-
report.singletonRisks.length > 0
|
|
104
|
+
report.singletonRisks.length > 0 ||
|
|
105
|
+
report.eagerRisks.length > 0);
|
|
93
106
|
}
|
|
94
107
|
}
|
|
95
108
|
//# sourceMappingURL=webpack.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webpack.js","sourceRoot":"","sources":["../../src/plugins/webpack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"webpack.js","sourceRoot":"","sources":["../../src/plugins/webpack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FederationReport } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Formats a FederationReport as a human-readable terminal string.
|
|
4
|
+
*
|
|
5
|
+
* Section order (by severity):
|
|
6
|
+
* 1. Version conflicts — deterministic, most dangerous (silent broken singleton)
|
|
7
|
+
* 2. Singleton mismatches — deterministic, runtime risk
|
|
8
|
+
* 3. Host gaps — heuristic, bundle duplication
|
|
9
|
+
* 4. Ghost shares — heuristic, dead coupling
|
|
10
|
+
* 5. Summary line
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatFederationReport(report: FederationReport): string;
|
|
13
|
+
//# sourceMappingURL=format-federation-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-federation-report.d.ts","sourceRoot":"","sources":["../../src/reporter/format-federation-report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAgFvE"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a FederationReport as a human-readable terminal string.
|
|
3
|
+
*
|
|
4
|
+
* Section order (by severity):
|
|
5
|
+
* 1. Version conflicts — deterministic, most dangerous (silent broken singleton)
|
|
6
|
+
* 2. Singleton mismatches — deterministic, runtime risk
|
|
7
|
+
* 3. Host gaps — heuristic, bundle duplication
|
|
8
|
+
* 4. Ghost shares — heuristic, dead coupling
|
|
9
|
+
* 5. Summary line
|
|
10
|
+
*/
|
|
11
|
+
export function formatFederationReport(report) {
|
|
12
|
+
const lines = [];
|
|
13
|
+
const { ghostShares, hostGaps, versionConflicts, singletonMismatches, summary } = report;
|
|
14
|
+
// ── Header ─────────────────────────────────────────────────────────────────
|
|
15
|
+
lines.push('', `[MfSharedInspector] federation analysis (${summary.totalManifests} MFs)`, '');
|
|
16
|
+
const hasFindings = versionConflicts.length > 0 ||
|
|
17
|
+
singletonMismatches.length > 0 ||
|
|
18
|
+
hostGaps.length > 0 ||
|
|
19
|
+
ghostShares.length > 0;
|
|
20
|
+
if (!hasFindings) {
|
|
21
|
+
lines.push(' No federation-level issues found.');
|
|
22
|
+
lines.push('');
|
|
23
|
+
lines.push(` Total: ${summary.totalManifests} MFs analysed, everything looks consistent.`);
|
|
24
|
+
lines.push('');
|
|
25
|
+
return lines.join('\n');
|
|
26
|
+
}
|
|
27
|
+
// ── 1. Version conflicts ───────────────────────────────────────────────────
|
|
28
|
+
if (versionConflicts.length > 0) {
|
|
29
|
+
lines.push(' Version conflicts (singleton negotiation will fail):');
|
|
30
|
+
for (const c of versionConflicts) {
|
|
31
|
+
const versions = Object.entries(c.versions)
|
|
32
|
+
.map(([mf, v]) => `${mf}: ${v}`)
|
|
33
|
+
.join(', ');
|
|
34
|
+
lines.push(` ⚠ ${c.package} — ${versions}`);
|
|
35
|
+
}
|
|
36
|
+
lines.push('');
|
|
37
|
+
}
|
|
38
|
+
// ── 2. Singleton mismatches ────────────────────────────────────────────────
|
|
39
|
+
if (singletonMismatches.length > 0) {
|
|
40
|
+
lines.push(' Singleton mismatches (add singleton: true to all MFs):');
|
|
41
|
+
for (const s of singletonMismatches) {
|
|
42
|
+
lines.push(` ⚠ ${s.package} — singleton in [${s.singletonIn.join(', ')}], not singleton in [${s.nonSingletonIn.join(', ')}]`);
|
|
43
|
+
}
|
|
44
|
+
lines.push('');
|
|
45
|
+
}
|
|
46
|
+
// ── 3. Host gaps ───────────────────────────────────────────────────────────
|
|
47
|
+
if (hostGaps.length > 0) {
|
|
48
|
+
lines.push(' Host gaps (add to shared — each MF bundles its own copy):');
|
|
49
|
+
for (const g of hostGaps) {
|
|
50
|
+
lines.push(` → ${g.package} — used by [${g.missingIn.join(', ')}], not in shared`);
|
|
51
|
+
}
|
|
52
|
+
lines.push('');
|
|
53
|
+
}
|
|
54
|
+
// ── 4. Ghost shares ────────────────────────────────────────────────────────
|
|
55
|
+
if (ghostShares.length > 0) {
|
|
56
|
+
lines.push(' Ghost shares (remove from shared — no other MF benefits):');
|
|
57
|
+
for (const g of ghostShares) {
|
|
58
|
+
if (g.usedUnsharedBy.length > 0) {
|
|
59
|
+
lines.push(` ✗ ${g.package} — shared only by ${g.sharedBy}, ` +
|
|
60
|
+
`used unshared by [${g.usedUnsharedBy.join(', ')}]`);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
lines.push(` ✗ ${g.package} — shared only by ${g.sharedBy}, unused by all other MFs`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
lines.push('');
|
|
67
|
+
}
|
|
68
|
+
// ── 5. Summary ─────────────────────────────────────────────────────────────
|
|
69
|
+
lines.push(` Total: ${summary.totalManifests} MFs, ` +
|
|
70
|
+
`${summary.versionConflictsCount} version conflicts, ` +
|
|
71
|
+
`${summary.singletonMismatchesCount} singleton mismatches, ` +
|
|
72
|
+
`${summary.hostGapsCount} host gaps, ` +
|
|
73
|
+
`${summary.ghostSharesCount} ghost shares`);
|
|
74
|
+
lines.push('');
|
|
75
|
+
return lines.join('\n');
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=format-federation-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-federation-report.js","sourceRoot":"","sources":["../../src/reporter/format-federation-report.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -164,6 +164,83 @@ export interface ProjectReport {
|
|
|
164
164
|
eagerRisksCount: number;
|
|
165
165
|
};
|
|
166
166
|
}
|
|
167
|
+
export interface FederationAnalysisOptions {
|
|
168
|
+
/**
|
|
169
|
+
* Packages that are always expected to be shared across all MFs.
|
|
170
|
+
* Used to strengthen ghost-sharing detection.
|
|
171
|
+
* @default ['react', 'react-dom']
|
|
172
|
+
*/
|
|
173
|
+
alwaysShared?: string[];
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Package shared by one MF but absent from shared config in all other MFs.
|
|
177
|
+
* Creates one-sided coupling with no federation benefit.
|
|
178
|
+
*/
|
|
179
|
+
export interface GhostShareEntry {
|
|
180
|
+
package: string;
|
|
181
|
+
/** MF that declares this package in shared config */
|
|
182
|
+
sharedBy: string;
|
|
183
|
+
/** MFs that also use the package but don't declare it in shared */
|
|
184
|
+
usedUnsharedBy: string[];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Package used by one or more remotes but not declared in shared by any MF.
|
|
188
|
+
* Each MF bundles its own copy — potential duplication.
|
|
189
|
+
*/
|
|
190
|
+
export interface HostGapEntry {
|
|
191
|
+
package: string;
|
|
192
|
+
/** MFs that use the package without any shared declaration */
|
|
193
|
+
missingIn: string[];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Package where different MFs declare incompatible requiredVersion ranges.
|
|
197
|
+
* Module Federation singleton resolution will fail silently.
|
|
198
|
+
*/
|
|
199
|
+
export interface VersionConflictEntry {
|
|
200
|
+
package: string;
|
|
201
|
+
/** Map of MF name → requiredVersion declared in that MF's shared config */
|
|
202
|
+
versions: Record<string, string>;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Package where some MFs declare singleton: true and others don't.
|
|
206
|
+
* Inconsistent singleton flags cause unpredictable MF negotiation.
|
|
207
|
+
*/
|
|
208
|
+
export interface SingletonMismatchEntry {
|
|
209
|
+
package: string;
|
|
210
|
+
/** MFs that declare singleton: true */
|
|
211
|
+
singletonIn: string[];
|
|
212
|
+
/** MFs that declare the package in shared but without singleton: true */
|
|
213
|
+
nonSingletonIn: string[];
|
|
214
|
+
}
|
|
215
|
+
export interface FederationReport {
|
|
216
|
+
/**
|
|
217
|
+
* Packages in shared config of one MF that no other MF shares or uses.
|
|
218
|
+
* Safe to remove from shared — only creates artificial coupling.
|
|
219
|
+
*/
|
|
220
|
+
ghostShares: GhostShareEntry[];
|
|
221
|
+
/**
|
|
222
|
+
* Packages used across MFs but not declared in shared by anyone.
|
|
223
|
+
* Each MF pays the full bundle cost independently.
|
|
224
|
+
*/
|
|
225
|
+
hostGaps: HostGapEntry[];
|
|
226
|
+
/**
|
|
227
|
+
* Packages with conflicting requiredVersion across MFs.
|
|
228
|
+
* MF singleton negotiation will pick one version and silently break others.
|
|
229
|
+
*/
|
|
230
|
+
versionConflicts: VersionConflictEntry[];
|
|
231
|
+
/**
|
|
232
|
+
* Packages where singleton flag is inconsistent across MFs.
|
|
233
|
+
* Risk of duplicate instances in production.
|
|
234
|
+
*/
|
|
235
|
+
singletonMismatches: SingletonMismatchEntry[];
|
|
236
|
+
summary: {
|
|
237
|
+
totalManifests: number;
|
|
238
|
+
ghostSharesCount: number;
|
|
239
|
+
hostGapsCount: number;
|
|
240
|
+
versionConflictsCount: number;
|
|
241
|
+
singletonMismatchesCount: number;
|
|
242
|
+
};
|
|
243
|
+
}
|
|
167
244
|
export interface WebpackPluginOptions extends Omit<CollectorOptions, 'name'> {
|
|
168
245
|
/** Policy options for the analyzer */
|
|
169
246
|
analysis?: AnalysisOptions;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|