create-interview-cockpit 0.10.0 → 0.11.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/package.json
CHANGED
|
@@ -2398,6 +2398,161 @@ export default function CodeRunnerModal() {
|
|
|
2398
2398
|
const mfInspectorIssueCount =
|
|
2399
2399
|
mfInspectorDifferentRemoteCount + mfInspectorErroredRemoteCount;
|
|
2400
2400
|
const mfInspectorViewCopy = MF_INSPECTOR_VIEW_COPY[mfInspectorView];
|
|
2401
|
+
const mfInspectorWorkspacePackageMap = new Map<
|
|
2402
|
+
string,
|
|
2403
|
+
{
|
|
2404
|
+
apps: string[];
|
|
2405
|
+
requiredVersions: Array<{ app: string; version: string | false | null }>;
|
|
2406
|
+
}
|
|
2407
|
+
>();
|
|
2408
|
+
|
|
2409
|
+
for (const [filePath, fileContents] of Object.entries(reactFiles)) {
|
|
2410
|
+
const match = filePath.match(/^apps\/([^/]+)\/package\.json$/);
|
|
2411
|
+
if (!match) continue;
|
|
2412
|
+
|
|
2413
|
+
try {
|
|
2414
|
+
const packageJson = JSON.parse(fileContents);
|
|
2415
|
+
const appName = match[1];
|
|
2416
|
+
const dependencyVersions = asInspectorRecord(packageJson.dependencies);
|
|
2417
|
+
|
|
2418
|
+
for (const [packageName, versionValue] of Object.entries(
|
|
2419
|
+
dependencyVersions,
|
|
2420
|
+
)) {
|
|
2421
|
+
const existing = mfInspectorWorkspacePackageMap.get(packageName) ?? {
|
|
2422
|
+
apps: [],
|
|
2423
|
+
requiredVersions: [],
|
|
2424
|
+
};
|
|
2425
|
+
|
|
2426
|
+
if (!existing.apps.includes(appName)) {
|
|
2427
|
+
existing.apps.push(appName);
|
|
2428
|
+
}
|
|
2429
|
+
existing.requiredVersions.push({
|
|
2430
|
+
app: appName,
|
|
2431
|
+
version: typeof versionValue === "string" ? versionValue : null,
|
|
2432
|
+
});
|
|
2433
|
+
mfInspectorWorkspacePackageMap.set(packageName, existing);
|
|
2434
|
+
}
|
|
2435
|
+
} catch {
|
|
2436
|
+
// Ignore malformed package.json edits while the user is typing.
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
const mfInspectorDeclaredSharedPackageMap = new Map<
|
|
2441
|
+
string,
|
|
2442
|
+
{
|
|
2443
|
+
apps: string[];
|
|
2444
|
+
requiredVersions: Array<{ app: string; version: string | false | null }>;
|
|
2445
|
+
singletonPreferred: boolean;
|
|
2446
|
+
}
|
|
2447
|
+
>();
|
|
2448
|
+
|
|
2449
|
+
for (const [packageName, packageInfo] of mfInspectorWorkspacePackageMap) {
|
|
2450
|
+
mfInspectorDeclaredSharedPackageMap.set(packageName, {
|
|
2451
|
+
apps: [...packageInfo.apps],
|
|
2452
|
+
requiredVersions: [...packageInfo.requiredVersions],
|
|
2453
|
+
singletonPreferred: false,
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2456
|
+
|
|
2457
|
+
for (const { app, declaredConfig } of mfInspectorDeclaredConfigs) {
|
|
2458
|
+
const sharedPackages = asInspectorRecord(declaredConfig.shared);
|
|
2459
|
+
for (const packageName of Object.keys(sharedPackages)) {
|
|
2460
|
+
const packageConfig = asInspectorRecord(sharedPackages[packageName]);
|
|
2461
|
+
const existing = mfInspectorDeclaredSharedPackageMap.get(packageName) ?? {
|
|
2462
|
+
apps: [],
|
|
2463
|
+
requiredVersions: [],
|
|
2464
|
+
singletonPreferred: false,
|
|
2465
|
+
};
|
|
2466
|
+
|
|
2467
|
+
if (!existing.apps.includes(app)) {
|
|
2468
|
+
existing.apps.push(app);
|
|
2469
|
+
}
|
|
2470
|
+
existing.requiredVersions.push({
|
|
2471
|
+
app,
|
|
2472
|
+
version:
|
|
2473
|
+
typeof packageConfig.requiredVersion === "string"
|
|
2474
|
+
? packageConfig.requiredVersion
|
|
2475
|
+
: packageConfig.requiredVersion === false
|
|
2476
|
+
? false
|
|
2477
|
+
: null,
|
|
2478
|
+
});
|
|
2479
|
+
existing.singletonPreferred =
|
|
2480
|
+
existing.singletonPreferred || packageConfig.singleton === true;
|
|
2481
|
+
mfInspectorDeclaredSharedPackageMap.set(packageName, existing);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
const mfInspectorShareScopeNames = Array.from(
|
|
2486
|
+
new Set([
|
|
2487
|
+
...Object.keys(mfShareScopeForMatrix?.shareScopes ?? {}).filter(
|
|
2488
|
+
(scopeName) => scopeName !== "__error",
|
|
2489
|
+
),
|
|
2490
|
+
...(mfInspectorDeclaredSharedPackageMap.size > 0 ? ["default"] : []),
|
|
2491
|
+
]),
|
|
2492
|
+
);
|
|
2493
|
+
const mfInspectorRuntimeSharedPackageMap = new Map<
|
|
2494
|
+
string,
|
|
2495
|
+
{ registeredVersionCount: number; loaded: boolean }
|
|
2496
|
+
>();
|
|
2497
|
+
|
|
2498
|
+
for (const [scopeName, scopeValue] of Object.entries(
|
|
2499
|
+
mfShareScopeForMatrix?.shareScopes ?? {},
|
|
2500
|
+
)) {
|
|
2501
|
+
if (scopeName === "__error") continue;
|
|
2502
|
+
for (const [packageName, versionValue] of Object.entries(
|
|
2503
|
+
asInspectorRecord(scopeValue),
|
|
2504
|
+
)) {
|
|
2505
|
+
const versionEntries = Array.isArray(versionValue) ? versionValue : [];
|
|
2506
|
+
const existing = mfInspectorRuntimeSharedPackageMap.get(packageName) ?? {
|
|
2507
|
+
registeredVersionCount: 0,
|
|
2508
|
+
loaded: false,
|
|
2509
|
+
};
|
|
2510
|
+
existing.registeredVersionCount = Math.max(
|
|
2511
|
+
existing.registeredVersionCount,
|
|
2512
|
+
versionEntries.length,
|
|
2513
|
+
);
|
|
2514
|
+
existing.loaded =
|
|
2515
|
+
existing.loaded ||
|
|
2516
|
+
versionEntries.some(
|
|
2517
|
+
(entry) => asInspectorRecord(entry).loaded === true,
|
|
2518
|
+
);
|
|
2519
|
+
mfInspectorRuntimeSharedPackageMap.set(packageName, existing);
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
const mfInspectorSharedPackagesByApp = new Map<
|
|
2524
|
+
string,
|
|
2525
|
+
Array<{
|
|
2526
|
+
packageName: string;
|
|
2527
|
+
singletonPreferred: boolean;
|
|
2528
|
+
runtimeRegistered: boolean;
|
|
2529
|
+
runtimeLoaded: boolean;
|
|
2530
|
+
}>
|
|
2531
|
+
>();
|
|
2532
|
+
|
|
2533
|
+
for (const [
|
|
2534
|
+
packageName,
|
|
2535
|
+
packageInfo,
|
|
2536
|
+
] of mfInspectorDeclaredSharedPackageMap) {
|
|
2537
|
+
for (const appName of packageInfo.apps) {
|
|
2538
|
+
const appPackages = mfInspectorSharedPackagesByApp.get(appName) ?? [];
|
|
2539
|
+
const runtimePackageInfo =
|
|
2540
|
+
mfInspectorRuntimeSharedPackageMap.get(packageName) ?? null;
|
|
2541
|
+
appPackages.push({
|
|
2542
|
+
packageName,
|
|
2543
|
+
singletonPreferred: packageInfo.singletonPreferred,
|
|
2544
|
+
runtimeRegistered: runtimePackageInfo != null,
|
|
2545
|
+
runtimeLoaded: runtimePackageInfo?.loaded === true,
|
|
2546
|
+
});
|
|
2547
|
+
mfInspectorSharedPackagesByApp.set(appName, appPackages);
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
for (const packages of mfInspectorSharedPackagesByApp.values()) {
|
|
2552
|
+
packages.sort((left, right) =>
|
|
2553
|
+
left.packageName.localeCompare(right.packageName),
|
|
2554
|
+
);
|
|
2555
|
+
}
|
|
2401
2556
|
const mfInspectorSummaryCards = [
|
|
2402
2557
|
{
|
|
2403
2558
|
label: "Host page",
|
|
@@ -2442,6 +2597,64 @@ export default function CodeRunnerModal() {
|
|
|
2442
2597
|
},
|
|
2443
2598
|
];
|
|
2444
2599
|
|
|
2600
|
+
const getMfInspectorAppSharedPackages = (appName: string) =>
|
|
2601
|
+
mfInspectorSharedPackagesByApp.get(appName) ?? [];
|
|
2602
|
+
|
|
2603
|
+
const getMfInspectorAppSharedPackageSummary = (appName: string) => {
|
|
2604
|
+
const packages = getMfInspectorAppSharedPackages(appName);
|
|
2605
|
+
const previewItems = packages.slice(0, 2).map((entry) => entry.packageName);
|
|
2606
|
+
const hiddenCount = packages.length - previewItems.length;
|
|
2607
|
+
|
|
2608
|
+
return {
|
|
2609
|
+
count: packages.length,
|
|
2610
|
+
countLabel:
|
|
2611
|
+
packages.length === 1
|
|
2612
|
+
? "1 shared package"
|
|
2613
|
+
: `${packages.length} shared packages`,
|
|
2614
|
+
previewText:
|
|
2615
|
+
packages.length === 0
|
|
2616
|
+
? "none declared"
|
|
2617
|
+
: previewItems.join(", ") +
|
|
2618
|
+
(hiddenCount > 0 ? ` +${hiddenCount}` : ""),
|
|
2619
|
+
};
|
|
2620
|
+
};
|
|
2621
|
+
|
|
2622
|
+
const renderMfInspectorPackageBadges = (appName: string) => {
|
|
2623
|
+
const packages = getMfInspectorAppSharedPackages(appName);
|
|
2624
|
+
|
|
2625
|
+
if (packages.length === 0) {
|
|
2626
|
+
return <span className="text-slate-600">none declared</span>;
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
return (
|
|
2630
|
+
<div className="flex flex-wrap gap-1">
|
|
2631
|
+
{packages.map((entry) => {
|
|
2632
|
+
const toneClass = entry.runtimeLoaded
|
|
2633
|
+
? "border-emerald-500/30 bg-emerald-500/10 text-emerald-200"
|
|
2634
|
+
: entry.runtimeRegistered
|
|
2635
|
+
? "border-cyan-500/30 bg-cyan-500/10 text-cyan-200"
|
|
2636
|
+
: "border-slate-700 bg-slate-800/50 text-slate-300";
|
|
2637
|
+
return (
|
|
2638
|
+
<span
|
|
2639
|
+
key={`${appName}-${entry.packageName}`}
|
|
2640
|
+
className={`rounded border px-1.5 py-0.5 text-[10px] font-mono ${toneClass}`}
|
|
2641
|
+
title={
|
|
2642
|
+
entry.runtimeLoaded
|
|
2643
|
+
? "Seen and loaded at runtime"
|
|
2644
|
+
: entry.runtimeRegistered
|
|
2645
|
+
? "Seen in webpack runtime registry"
|
|
2646
|
+
: "Declared in package.json but not yet seen at runtime"
|
|
2647
|
+
}
|
|
2648
|
+
>
|
|
2649
|
+
{entry.packageName}
|
|
2650
|
+
{entry.singletonPreferred ? " · one copy" : ""}
|
|
2651
|
+
</span>
|
|
2652
|
+
);
|
|
2653
|
+
})}
|
|
2654
|
+
</div>
|
|
2655
|
+
);
|
|
2656
|
+
};
|
|
2657
|
+
|
|
2445
2658
|
const renderMfInspectorTruthCell = (
|
|
2446
2659
|
sameInstance: boolean | null,
|
|
2447
2660
|
error: string | null,
|
|
@@ -4526,9 +4739,11 @@ export default function CodeRunnerModal() {
|
|
|
4526
4739
|
const remoteY = 156;
|
|
4527
4740
|
const nodeW = 96;
|
|
4528
4741
|
const nodeH = 46;
|
|
4529
|
-
const svgH =
|
|
4742
|
+
const svgH = 250;
|
|
4530
4743
|
const hostBooted = mfInspectorBootMap.has("host");
|
|
4531
4744
|
const hostData = mfInspectorBootMap.get("host");
|
|
4745
|
+
const hostPackageSummary =
|
|
4746
|
+
getMfInspectorAppSharedPackageSummary("host");
|
|
4532
4747
|
|
|
4533
4748
|
const getConnectionStatus = (
|
|
4534
4749
|
remoteName: string,
|
|
@@ -4716,6 +4931,30 @@ export default function CodeRunnerModal() {
|
|
|
4716
4931
|
{"▣ DOM " + hostData.reactDomVersion}
|
|
4717
4932
|
</text>
|
|
4718
4933
|
)}
|
|
4934
|
+
{hostPackageSummary.count > 0 && (
|
|
4935
|
+
<>
|
|
4936
|
+
<text
|
|
4937
|
+
x={W / 2}
|
|
4938
|
+
y={hostY + nodeH / 2 + 16}
|
|
4939
|
+
textAnchor="middle"
|
|
4940
|
+
fill="#cbd5e1"
|
|
4941
|
+
fontSize={8}
|
|
4942
|
+
fontFamily="ui-sans-serif, sans-serif"
|
|
4943
|
+
>
|
|
4944
|
+
{hostPackageSummary.countLabel}
|
|
4945
|
+
</text>
|
|
4946
|
+
<text
|
|
4947
|
+
x={W / 2}
|
|
4948
|
+
y={hostY + nodeH / 2 + 27}
|
|
4949
|
+
textAnchor="middle"
|
|
4950
|
+
fill="#64748b"
|
|
4951
|
+
fontSize={7.5}
|
|
4952
|
+
fontFamily="ui-monospace, monospace"
|
|
4953
|
+
>
|
|
4954
|
+
{hostPackageSummary.previewText}
|
|
4955
|
+
</text>
|
|
4956
|
+
</>
|
|
4957
|
+
)}
|
|
4719
4958
|
|
|
4720
4959
|
{/* REMOTE nodes */}
|
|
4721
4960
|
{displayRemotes.map((remoteName, i) => {
|
|
@@ -4723,6 +4962,10 @@ export default function CodeRunnerModal() {
|
|
|
4723
4962
|
const status = isPlaceholder
|
|
4724
4963
|
? "idle"
|
|
4725
4964
|
: getConnectionStatus(remoteName);
|
|
4965
|
+
const packageSummary =
|
|
4966
|
+
getMfInspectorAppSharedPackageSummary(
|
|
4967
|
+
remoteName,
|
|
4968
|
+
);
|
|
4726
4969
|
const remoteData =
|
|
4727
4970
|
mfInspectorBootMap.get(remoteName);
|
|
4728
4971
|
const keys =
|
|
@@ -4958,6 +5201,30 @@ export default function CodeRunnerModal() {
|
|
|
4958
5201
|
)}
|
|
4959
5202
|
</g>
|
|
4960
5203
|
)}
|
|
5204
|
+
{packageSummary.count > 0 && (
|
|
5205
|
+
<g>
|
|
5206
|
+
<text
|
|
5207
|
+
x={rx}
|
|
5208
|
+
y={remoteY + nodeH / 2 + 26}
|
|
5209
|
+
textAnchor="middle"
|
|
5210
|
+
fill="#cbd5e1"
|
|
5211
|
+
fontSize={8}
|
|
5212
|
+
fontFamily="ui-sans-serif, sans-serif"
|
|
5213
|
+
>
|
|
5214
|
+
{packageSummary.countLabel}
|
|
5215
|
+
</text>
|
|
5216
|
+
<text
|
|
5217
|
+
x={rx}
|
|
5218
|
+
y={remoteY + nodeH / 2 + 37}
|
|
5219
|
+
textAnchor="middle"
|
|
5220
|
+
fill="#64748b"
|
|
5221
|
+
fontSize={7.5}
|
|
5222
|
+
fontFamily="ui-monospace, monospace"
|
|
5223
|
+
>
|
|
5224
|
+
{packageSummary.previewText}
|
|
5225
|
+
</text>
|
|
5226
|
+
</g>
|
|
5227
|
+
)}
|
|
4961
5228
|
</g>
|
|
4962
5229
|
);
|
|
4963
5230
|
})}
|
|
@@ -5036,7 +5303,9 @@ export default function CodeRunnerModal() {
|
|
|
5036
5303
|
<div className="text-[11px] text-slate-500 mb-2 leading-relaxed">
|
|
5037
5304
|
"Same copy" is the healthy result for React and
|
|
5038
5305
|
ReactDOM. "Different copy" often leads to hook,
|
|
5039
|
-
context, or shared-state bugs.
|
|
5306
|
+
context, or shared-state bugs. The package list
|
|
5307
|
+
column reflects the current app package.json
|
|
5308
|
+
files.
|
|
5040
5309
|
</div>
|
|
5041
5310
|
<div className="rounded-lg border border-slate-800 overflow-hidden">
|
|
5042
5311
|
<table className="w-full text-[11px]">
|
|
@@ -5051,6 +5320,9 @@ export default function CodeRunnerModal() {
|
|
|
5051
5320
|
<th className="text-left px-3 py-1.5 text-slate-400 font-medium">
|
|
5052
5321
|
DOM copy
|
|
5053
5322
|
</th>
|
|
5323
|
+
<th className="text-left px-3 py-1.5 text-slate-400 font-medium">
|
|
5324
|
+
Current shared packages
|
|
5325
|
+
</th>
|
|
5054
5326
|
<th className="text-left px-3 py-1.5 text-slate-400 font-medium">
|
|
5055
5327
|
Version seen
|
|
5056
5328
|
</th>
|
|
@@ -5066,6 +5338,10 @@ export default function CodeRunnerModal() {
|
|
|
5066
5338
|
mfInspectorIdentityResultMap.get(
|
|
5067
5339
|
remoteKey,
|
|
5068
5340
|
) ?? null;
|
|
5341
|
+
const remoteAppName =
|
|
5342
|
+
result?.remoteApp ??
|
|
5343
|
+
remoteKey.split("/")[0] ??
|
|
5344
|
+
"unknown";
|
|
5069
5345
|
const loadInfo =
|
|
5070
5346
|
mfInspectorRemoteLoadMap.get(
|
|
5071
5347
|
remoteKey,
|
|
@@ -5092,6 +5368,11 @@ export default function CodeRunnerModal() {
|
|
|
5092
5368
|
loadInfo?.status ?? null,
|
|
5093
5369
|
)}
|
|
5094
5370
|
</td>
|
|
5371
|
+
<td className="px-3 py-2 align-top">
|
|
5372
|
+
{renderMfInspectorPackageBadges(
|
|
5373
|
+
remoteAppName,
|
|
5374
|
+
)}
|
|
5375
|
+
</td>
|
|
5095
5376
|
<td className="px-3 py-2 font-mono text-slate-400 text-[10px]">
|
|
5096
5377
|
{result?.reactVersion ??
|
|
5097
5378
|
(loadInfo?.status ===
|
|
@@ -5257,13 +5538,13 @@ export default function CodeRunnerModal() {
|
|
|
5257
5538
|
<>
|
|
5258
5539
|
<div className="rounded-lg border border-slate-800 bg-slate-900/50 px-3 py-2.5 mb-3">
|
|
5259
5540
|
<div className="text-[12px] font-semibold text-slate-100">
|
|
5260
|
-
|
|
5541
|
+
Shared package picture
|
|
5261
5542
|
</div>
|
|
5262
5543
|
<p className="mt-1 text-[11px] text-slate-400 leading-relaxed">
|
|
5263
|
-
This
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5544
|
+
This tab merges two sources: the packages found in
|
|
5545
|
+
the current app package.json files in the editor,
|
|
5546
|
+
and the packages webpack has actually registered
|
|
5547
|
+
in its live runtime share scope.
|
|
5267
5548
|
</p>
|
|
5268
5549
|
<p className="mt-1 text-[10px] text-slate-500">
|
|
5269
5550
|
Snapshot source:{" "}
|
|
@@ -5276,168 +5557,239 @@ export default function CodeRunnerModal() {
|
|
|
5276
5557
|
)}
|
|
5277
5558
|
</p>
|
|
5278
5559
|
</div>
|
|
5279
|
-
{
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5560
|
+
{mfInspectorShareScopeNames.map((scopeName) => {
|
|
5561
|
+
const scopeValue =
|
|
5562
|
+
scopeName === "default"
|
|
5563
|
+
? asInspectorRecord(
|
|
5564
|
+
mfShareScopeForMatrix.shareScopes.default,
|
|
5565
|
+
)
|
|
5566
|
+
: asInspectorRecord(
|
|
5567
|
+
mfShareScopeForMatrix.shareScopes[
|
|
5568
|
+
scopeName
|
|
5569
|
+
],
|
|
5570
|
+
);
|
|
5571
|
+
const packageNames = Array.from(
|
|
5572
|
+
new Set([
|
|
5573
|
+
...Object.keys(scopeValue),
|
|
5574
|
+
...(scopeName === "default"
|
|
5575
|
+
? Array.from(
|
|
5576
|
+
mfInspectorDeclaredSharedPackageMap.keys(),
|
|
5577
|
+
)
|
|
5578
|
+
: []),
|
|
5579
|
+
]),
|
|
5580
|
+
).sort((left, right) => left.localeCompare(right));
|
|
5581
|
+
|
|
5582
|
+
if (packageNames.length === 0) return null;
|
|
5583
|
+
|
|
5584
|
+
return (
|
|
5585
|
+
<div key={scopeName} className="mb-4">
|
|
5586
|
+
<div className="text-[10px] text-slate-500 uppercase tracking-wider mb-2 font-mono">
|
|
5587
|
+
sharing group: {scopeName}
|
|
5588
|
+
</div>
|
|
5589
|
+
<div className="rounded-lg border border-slate-800 overflow-hidden">
|
|
5590
|
+
<table className="w-full text-[11px]">
|
|
5591
|
+
<thead>
|
|
5592
|
+
<tr className="bg-slate-900/80 border-b border-slate-800">
|
|
5593
|
+
<th className="text-left px-3 py-1.5 text-slate-400 font-medium w-32">
|
|
5594
|
+
Package
|
|
5595
|
+
</th>
|
|
5596
|
+
<th className="text-left px-3 py-1.5 text-slate-400 font-medium w-56">
|
|
5597
|
+
Declared by apps
|
|
5598
|
+
</th>
|
|
5599
|
+
<th className="text-left px-3 py-1.5 text-slate-400 font-medium">
|
|
5600
|
+
Versions webpack can reuse
|
|
5601
|
+
</th>
|
|
5602
|
+
</tr>
|
|
5603
|
+
</thead>
|
|
5604
|
+
<tbody>
|
|
5605
|
+
{packageNames.map((pkgName) => {
|
|
5606
|
+
const versionValue =
|
|
5607
|
+
scopeValue[pkgName];
|
|
5608
|
+
const versionEntries = Array.isArray(
|
|
5609
|
+
versionValue,
|
|
5610
|
+
)
|
|
5611
|
+
? versionValue
|
|
5612
|
+
: [];
|
|
5613
|
+
const declaredInfo =
|
|
5614
|
+
mfInspectorDeclaredSharedPackageMap.get(
|
|
5615
|
+
pkgName,
|
|
5616
|
+
) ?? null;
|
|
5617
|
+
const declaredSingleton =
|
|
5618
|
+
declaredInfo?.singletonPreferred ===
|
|
5619
|
+
true;
|
|
5620
|
+
const declaredVersionSummary =
|
|
5621
|
+
declaredInfo?.requiredVersions
|
|
5622
|
+
.filter(
|
|
5623
|
+
({ version }) => version !== null,
|
|
5624
|
+
)
|
|
5625
|
+
.map(({ app, version }) =>
|
|
5626
|
+
version === false
|
|
5627
|
+
? `${app}: any`
|
|
5628
|
+
: `${app}: ${version}`,
|
|
5629
|
+
) ?? [];
|
|
5630
|
+
const loadedCount =
|
|
5631
|
+
versionEntries.filter(
|
|
5632
|
+
(ve) =>
|
|
5633
|
+
asInspectorRecord(ve).loaded ===
|
|
5634
|
+
true,
|
|
5635
|
+
).length;
|
|
5636
|
+
return (
|
|
5637
|
+
<tr
|
|
5638
|
+
key={pkgName}
|
|
5639
|
+
className="border-b border-slate-800/50 last:border-0"
|
|
5640
|
+
>
|
|
5641
|
+
<td className="px-3 py-2.5 align-top">
|
|
5642
|
+
<div className="font-mono text-slate-100 font-medium">
|
|
5643
|
+
{pkgName}
|
|
5644
|
+
</div>
|
|
5645
|
+
<div className="flex flex-wrap gap-1 mt-1">
|
|
5646
|
+
{declaredSingleton && (
|
|
5647
|
+
<span className="rounded border border-amber-500/30 bg-amber-500/10 px-1 py-0.5 text-[9px] text-amber-300">
|
|
5648
|
+
one copy preferred
|
|
5649
|
+
</span>
|
|
5650
|
+
)}
|
|
5651
|
+
{declaredInfo ? (
|
|
5652
|
+
<span className="rounded border border-cyan-500/30 bg-cyan-500/10 px-1 py-0.5 text-[9px] text-cyan-300">
|
|
5653
|
+
from current package.json
|
|
5654
|
+
</span>
|
|
5655
|
+
) : (
|
|
5656
|
+
<span className="rounded border border-slate-700 bg-slate-800/50 px-1 py-0.5 text-[9px] text-slate-500">
|
|
5657
|
+
runtime only
|
|
5658
|
+
</span>
|
|
5659
|
+
)}
|
|
5660
|
+
<span className="rounded border border-slate-700 bg-slate-800/50 px-1 py-0.5 text-[9px] text-slate-400">
|
|
5661
|
+
{loadedCount}/
|
|
5662
|
+
{versionEntries.length}{" "}
|
|
5663
|
+
already used
|
|
5664
|
+
</span>
|
|
5665
|
+
</div>
|
|
5666
|
+
</td>
|
|
5667
|
+
<td className="px-3 py-2.5 align-top">
|
|
5668
|
+
{declaredInfo ? (
|
|
5669
|
+
<div>
|
|
5670
|
+
<div className="flex flex-wrap gap-1">
|
|
5671
|
+
{declaredInfo.apps.map(
|
|
5672
|
+
(appName) => (
|
|
5673
|
+
<span
|
|
5674
|
+
key={appName}
|
|
5675
|
+
className="rounded border border-slate-700 bg-slate-800/50 px-1.5 py-0.5 text-[9px] text-slate-300 font-mono"
|
|
5676
|
+
>
|
|
5677
|
+
{appName}
|
|
5678
|
+
</span>
|
|
5679
|
+
),
|
|
5344
5680
|
)}
|
|
5345
|
-
<span className="rounded border border-slate-700 bg-slate-800/50 px-1 py-0.5 text-[9px] text-slate-400">
|
|
5346
|
-
{loadedCount}/
|
|
5347
|
-
{versionEntries.length}{" "}
|
|
5348
|
-
already used
|
|
5349
|
-
</span>
|
|
5350
5681
|
</div>
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5682
|
+
{declaredVersionSummary.length >
|
|
5683
|
+
0 && (
|
|
5684
|
+
<div className="mt-1 text-[9px] text-slate-500 leading-relaxed">
|
|
5685
|
+
required versions:{" "}
|
|
5686
|
+
{declaredVersionSummary.join(
|
|
5687
|
+
", ",
|
|
5688
|
+
)}
|
|
5689
|
+
</div>
|
|
5690
|
+
)}
|
|
5691
|
+
</div>
|
|
5692
|
+
) : (
|
|
5693
|
+
<span className="text-slate-600">
|
|
5694
|
+
not declared in current app
|
|
5695
|
+
config
|
|
5696
|
+
</span>
|
|
5697
|
+
)}
|
|
5698
|
+
</td>
|
|
5699
|
+
<td className="px-3 py-2.5">
|
|
5700
|
+
<div className="flex flex-wrap gap-2">
|
|
5701
|
+
{versionEntries.length === 0 ? (
|
|
5702
|
+
declaredInfo ? (
|
|
5703
|
+
<div className="rounded-lg border border-slate-700 bg-slate-800/40 px-2 py-1.5 text-[10px] text-slate-400 leading-relaxed max-w-[22rem]">
|
|
5704
|
+
Declared for sharing, but
|
|
5705
|
+
webpack has not put it in
|
|
5706
|
+
the live runtime registry
|
|
5707
|
+
yet.
|
|
5708
|
+
</div>
|
|
5709
|
+
) : (
|
|
5710
|
+
<span className="text-slate-600">
|
|
5711
|
+
none yet
|
|
5712
|
+
</span>
|
|
5713
|
+
)
|
|
5714
|
+
) : (
|
|
5715
|
+
versionEntries.map(
|
|
5716
|
+
(ve, vi) => {
|
|
5717
|
+
const vr =
|
|
5718
|
+
asInspectorRecord(ve);
|
|
5719
|
+
const version =
|
|
5720
|
+
typeof vr.version ===
|
|
5721
|
+
"string"
|
|
5722
|
+
? vr.version
|
|
5723
|
+
: "?";
|
|
5724
|
+
const from =
|
|
5725
|
+
typeof vr.from ===
|
|
5726
|
+
"string"
|
|
5727
|
+
? vr.from
|
|
5728
|
+
: null;
|
|
5729
|
+
const loaded =
|
|
5730
|
+
vr.loaded === true;
|
|
5731
|
+
const eager =
|
|
5732
|
+
vr.eager === true;
|
|
5733
|
+
return (
|
|
5734
|
+
<div
|
|
5735
|
+
key={vi}
|
|
5736
|
+
className={`rounded-lg border px-2 py-1.5 font-mono text-[10px] ${
|
|
5737
|
+
loaded
|
|
5738
|
+
? "border-emerald-500/30 bg-emerald-500/5"
|
|
5739
|
+
: "border-slate-700 bg-slate-800/40"
|
|
5740
|
+
}`}
|
|
5741
|
+
>
|
|
5742
|
+
<div
|
|
5743
|
+
className={`font-semibold ${loaded ? "text-emerald-200" : "text-slate-400"}`}
|
|
5744
|
+
>
|
|
5745
|
+
{version}
|
|
5746
|
+
</div>
|
|
5747
|
+
{from && (
|
|
5748
|
+
<div className="text-slate-500 mt-0.5 text-[9px]">
|
|
5749
|
+
registered by{" "}
|
|
5750
|
+
{from}
|
|
5751
|
+
</div>
|
|
5752
|
+
)}
|
|
5753
|
+
<div className="flex gap-1 mt-1">
|
|
5754
|
+
<span
|
|
5755
|
+
className={`rounded px-1 py-0.5 text-[8px] ${
|
|
5384
5756
|
loaded
|
|
5385
|
-
? "
|
|
5386
|
-
: "
|
|
5757
|
+
? "bg-emerald-500/20 text-emerald-300"
|
|
5758
|
+
: "bg-slate-700 text-slate-500"
|
|
5387
5759
|
}`}
|
|
5388
5760
|
>
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
{
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
}`}
|
|
5418
|
-
>
|
|
5419
|
-
{eager
|
|
5420
|
-
? "load now"
|
|
5421
|
-
: "load later"}
|
|
5422
|
-
</span>
|
|
5423
|
-
</div>
|
|
5424
|
-
</div>
|
|
5425
|
-
);
|
|
5426
|
-
},
|
|
5427
|
-
)
|
|
5428
|
-
)}
|
|
5429
|
-
</div>
|
|
5430
|
-
</td>
|
|
5431
|
-
</tr>
|
|
5432
|
-
);
|
|
5433
|
-
},
|
|
5434
|
-
)}
|
|
5435
|
-
</tbody>
|
|
5436
|
-
</table>
|
|
5437
|
-
</div>
|
|
5761
|
+
{loaded
|
|
5762
|
+
? "in use"
|
|
5763
|
+
: "registered"}
|
|
5764
|
+
</span>
|
|
5765
|
+
<span
|
|
5766
|
+
className={`rounded px-1 py-0.5 text-[8px] ${
|
|
5767
|
+
eager
|
|
5768
|
+
? "bg-amber-500/20 text-amber-300"
|
|
5769
|
+
: "bg-slate-800 text-slate-600"
|
|
5770
|
+
}`}
|
|
5771
|
+
>
|
|
5772
|
+
{eager
|
|
5773
|
+
? "load now"
|
|
5774
|
+
: "load later"}
|
|
5775
|
+
</span>
|
|
5776
|
+
</div>
|
|
5777
|
+
</div>
|
|
5778
|
+
);
|
|
5779
|
+
},
|
|
5780
|
+
)
|
|
5781
|
+
)}
|
|
5782
|
+
</div>
|
|
5783
|
+
</td>
|
|
5784
|
+
</tr>
|
|
5785
|
+
);
|
|
5786
|
+
})}
|
|
5787
|
+
</tbody>
|
|
5788
|
+
</table>
|
|
5438
5789
|
</div>
|
|
5439
|
-
|
|
5440
|
-
|
|
5790
|
+
</div>
|
|
5791
|
+
);
|
|
5792
|
+
})}
|
|
5441
5793
|
{typeof mfShareScopeForMatrix.shareScopes.__error ===
|
|
5442
5794
|
"string" && (
|
|
5443
5795
|
<div className="rounded border border-red-500/20 bg-red-500/10 px-3 py-2 text-[11px] text-red-200">
|
|
@@ -216,10 +216,12 @@ This lab uses real webpack 5 + webpack-dev-server + Module Federation.
|
|
|
216
216
|
|
|
217
217
|
## What is here
|
|
218
218
|
|
|
219
|
-
- package.json
|
|
219
|
+
- the root package.json orchestrates three npm workspaces: a host plus two remotes
|
|
220
|
+
- each app owns its own dependencies in its local package.json
|
|
220
221
|
- apps/host consumes federated modules from the remotes
|
|
221
222
|
- apps/profile exposes a profile widget
|
|
222
223
|
- apps/checkout exposes a checkout widget
|
|
224
|
+
- react-router-dom is declared in each app package.json so routing experiments work across apps
|
|
223
225
|
|
|
224
226
|
## Good experiments
|
|
225
227
|
|
|
@@ -231,33 +233,29 @@ This lab uses real webpack 5 + webpack-dev-server + Module Federation.
|
|
|
231
233
|
## Notes
|
|
232
234
|
|
|
233
235
|
- Ports are injected by the lab runner through environment variables.
|
|
234
|
-
-
|
|
236
|
+
- Each webpack config builds its shared dependency list from that app's runtime dependencies.
|
|
237
|
+
- If you add or remove dependencies in an app package.json, restart the webpack lab so npm workspaces reinstall them.
|
|
235
238
|
`,
|
|
236
239
|
"package.json": `{
|
|
237
240
|
"name": "webpack-module-federation-lab",
|
|
238
241
|
"private": true,
|
|
242
|
+
"workspaces": [
|
|
243
|
+
"apps/host",
|
|
244
|
+
"apps/profile",
|
|
245
|
+
"apps/checkout"
|
|
246
|
+
],
|
|
239
247
|
"scripts": {
|
|
240
|
-
"dev": "concurrently -k -n host,profile,checkout -c cyan,magenta,yellow 'npm --
|
|
241
|
-
"dev:host": "npm --
|
|
242
|
-
"dev:profile": "npm --
|
|
243
|
-
"dev:checkout": "npm --
|
|
244
|
-
"build": "npm --
|
|
245
|
-
"build:host": "npm --
|
|
246
|
-
"build:profile": "npm --
|
|
247
|
-
"build:checkout": "npm --
|
|
248
|
-
},
|
|
249
|
-
"dependencies": {
|
|
250
|
-
"react": "^19.0.0",
|
|
251
|
-
"react-dom": "^19.0.0"
|
|
248
|
+
"dev": "concurrently -k -n host,profile,checkout -c cyan,magenta,yellow 'npm run dev --workspace=@mf-lab/host' 'npm run dev --workspace=@mf-lab/profile' 'npm run dev --workspace=@mf-lab/checkout'",
|
|
249
|
+
"dev:host": "npm run dev --workspace=@mf-lab/host",
|
|
250
|
+
"dev:profile": "npm run dev --workspace=@mf-lab/profile",
|
|
251
|
+
"dev:checkout": "npm run dev --workspace=@mf-lab/checkout",
|
|
252
|
+
"build": "npm run build --workspace=@mf-lab/host && npm run build --workspace=@mf-lab/profile && npm run build --workspace=@mf-lab/checkout",
|
|
253
|
+
"build:host": "npm run build --workspace=@mf-lab/host",
|
|
254
|
+
"build:profile": "npm run build --workspace=@mf-lab/profile",
|
|
255
|
+
"build:checkout": "npm run build --workspace=@mf-lab/checkout"
|
|
252
256
|
},
|
|
253
257
|
"devDependencies": {
|
|
254
|
-
"concurrently": "^9.2.1"
|
|
255
|
-
"esbuild": "^0.28.0",
|
|
256
|
-
"esbuild-loader": "^4.4.3",
|
|
257
|
-
"html-webpack-plugin": "^5.6.7",
|
|
258
|
-
"webpack": "^5.106.2",
|
|
259
|
-
"webpack-cli": "^7.0.2",
|
|
260
|
-
"webpack-dev-server": "^5.2.3"
|
|
258
|
+
"concurrently": "^9.2.1"
|
|
261
259
|
}
|
|
262
260
|
}
|
|
263
261
|
`,
|
|
@@ -279,6 +277,19 @@ This lab uses real webpack 5 + webpack-dev-server + Module Federation.
|
|
|
279
277
|
"scripts": {
|
|
280
278
|
"dev": "webpack serve --config webpack.config.js",
|
|
281
279
|
"build": "webpack --config webpack.config.js"
|
|
280
|
+
},
|
|
281
|
+
"dependencies": {
|
|
282
|
+
"react": "^19.0.0",
|
|
283
|
+
"react-dom": "^19.0.0",
|
|
284
|
+
"react-router-dom": "^7.6.1"
|
|
285
|
+
},
|
|
286
|
+
"devDependencies": {
|
|
287
|
+
"esbuild": "^0.28.0",
|
|
288
|
+
"esbuild-loader": "^4.4.3",
|
|
289
|
+
"html-webpack-plugin": "^5.6.7",
|
|
290
|
+
"webpack": "^5.106.2",
|
|
291
|
+
"webpack-cli": "^7.0.2",
|
|
292
|
+
"webpack-dev-server": "^5.2.3"
|
|
282
293
|
}
|
|
283
294
|
}
|
|
284
295
|
`,
|
|
@@ -503,6 +514,44 @@ export function makeInspectableLazy(remoteKey, componentLoad, debugLoad) {
|
|
|
503
514
|
}
|
|
504
515
|
};
|
|
505
516
|
}
|
|
517
|
+
`,
|
|
518
|
+
"apps/shared/buildSharedConfig.js": `function createSharedConfig(packageJson) {
|
|
519
|
+
const dependencyVersions =
|
|
520
|
+
packageJson && typeof packageJson === "object"
|
|
521
|
+
? packageJson.dependencies || {}
|
|
522
|
+
: {};
|
|
523
|
+
|
|
524
|
+
const sharedOverrides = {
|
|
525
|
+
react: {
|
|
526
|
+
singleton: true,
|
|
527
|
+
requiredVersion: dependencyVersions.react || false,
|
|
528
|
+
},
|
|
529
|
+
"react-dom": {
|
|
530
|
+
singleton: true,
|
|
531
|
+
requiredVersion: dependencyVersions["react-dom"] || false,
|
|
532
|
+
},
|
|
533
|
+
"react-router-dom": {
|
|
534
|
+
singleton: true,
|
|
535
|
+
requiredVersion: dependencyVersions["react-router-dom"] || false,
|
|
536
|
+
},
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
// Add package names here if you want them installed but NOT shared.
|
|
540
|
+
const unsharedPackages = new Set([]);
|
|
541
|
+
|
|
542
|
+
return Object.fromEntries(
|
|
543
|
+
Object.keys(dependencyVersions)
|
|
544
|
+
.filter((packageName) => !unsharedPackages.has(packageName))
|
|
545
|
+
.map((packageName) => [
|
|
546
|
+
packageName,
|
|
547
|
+
sharedOverrides[packageName] ?? {
|
|
548
|
+
requiredVersion: dependencyVersions[packageName] || false,
|
|
549
|
+
},
|
|
550
|
+
]),
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
module.exports = { createSharedConfig };
|
|
506
555
|
`,
|
|
507
556
|
"apps/host/src/index.jsx": `import("./bootstrap");
|
|
508
557
|
`,
|
|
@@ -607,14 +656,13 @@ export default function App() {
|
|
|
607
656
|
const webpack = require("webpack");
|
|
608
657
|
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
609
658
|
const { ModuleFederationPlugin } = webpack.container;
|
|
659
|
+
const packageJson = require("./package.json");
|
|
660
|
+
const { createSharedConfig } = require("../shared/buildSharedConfig");
|
|
610
661
|
|
|
611
662
|
const hostPort = Number(process.env.HOST_PORT || 3100);
|
|
612
663
|
const profilePort = Number(process.env.PROFILE_PORT || 3101);
|
|
613
664
|
const checkoutPort = Number(process.env.CHECKOUT_PORT || 3102);
|
|
614
|
-
const sharedConfig =
|
|
615
|
-
react: { singleton: true, requiredVersion: false },
|
|
616
|
-
"react-dom": { singleton: true, requiredVersion: false },
|
|
617
|
-
};
|
|
665
|
+
const sharedConfig = createSharedConfig(packageJson);
|
|
618
666
|
const remoteConfig = {
|
|
619
667
|
profile: "profile@http://localhost:" + profilePort + "/remoteEntry.js",
|
|
620
668
|
checkout: "checkout@http://localhost:" + checkoutPort + "/remoteEntry.js",
|
|
@@ -695,6 +743,19 @@ module.exports = {
|
|
|
695
743
|
"scripts": {
|
|
696
744
|
"dev": "webpack serve --config webpack.config.js",
|
|
697
745
|
"build": "webpack --config webpack.config.js"
|
|
746
|
+
},
|
|
747
|
+
"dependencies": {
|
|
748
|
+
"react": "^19.0.0",
|
|
749
|
+
"react-dom": "^19.0.0",
|
|
750
|
+
"react-router-dom": "^7.6.1"
|
|
751
|
+
},
|
|
752
|
+
"devDependencies": {
|
|
753
|
+
"esbuild": "^0.28.0",
|
|
754
|
+
"esbuild-loader": "^4.4.3",
|
|
755
|
+
"html-webpack-plugin": "^5.6.7",
|
|
756
|
+
"webpack": "^5.106.2",
|
|
757
|
+
"webpack-cli": "^7.0.2",
|
|
758
|
+
"webpack-dev-server": "^5.2.3"
|
|
698
759
|
}
|
|
699
760
|
}
|
|
700
761
|
`,
|
|
@@ -758,12 +819,11 @@ export default function ProfileCard() {
|
|
|
758
819
|
const webpack = require("webpack");
|
|
759
820
|
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
760
821
|
const { ModuleFederationPlugin } = webpack.container;
|
|
822
|
+
const packageJson = require("./package.json");
|
|
823
|
+
const { createSharedConfig } = require("../shared/buildSharedConfig");
|
|
761
824
|
|
|
762
825
|
const profilePort = Number(process.env.PROFILE_PORT || 3101);
|
|
763
|
-
const sharedConfig =
|
|
764
|
-
react: { singleton: true, requiredVersion: false },
|
|
765
|
-
"react-dom": { singleton: true, requiredVersion: false },
|
|
766
|
-
};
|
|
826
|
+
const sharedConfig = createSharedConfig(packageJson);
|
|
767
827
|
const exposeConfig = {
|
|
768
828
|
"./ProfileCard": path.resolve(__dirname, "./src/ProfileCard.jsx"),
|
|
769
829
|
"./InspectorBridge": path.resolve(__dirname, "./src/inspectorBridge.js"),
|
|
@@ -803,6 +863,7 @@ module.exports = {
|
|
|
803
863
|
},
|
|
804
864
|
devServer: {
|
|
805
865
|
port: profilePort,
|
|
866
|
+
historyApiFallback: true,
|
|
806
867
|
hot: true,
|
|
807
868
|
headers: {
|
|
808
869
|
"Access-Control-Allow-Origin": "*",
|
|
@@ -844,6 +905,19 @@ module.exports = {
|
|
|
844
905
|
"scripts": {
|
|
845
906
|
"dev": "webpack serve --config webpack.config.js",
|
|
846
907
|
"build": "webpack --config webpack.config.js"
|
|
908
|
+
},
|
|
909
|
+
"dependencies": {
|
|
910
|
+
"react": "^19.0.0",
|
|
911
|
+
"react-dom": "^19.0.0",
|
|
912
|
+
"react-router-dom": "^7.6.1"
|
|
913
|
+
},
|
|
914
|
+
"devDependencies": {
|
|
915
|
+
"esbuild": "^0.28.0",
|
|
916
|
+
"esbuild-loader": "^4.4.3",
|
|
917
|
+
"html-webpack-plugin": "^5.6.7",
|
|
918
|
+
"webpack": "^5.106.2",
|
|
919
|
+
"webpack-cli": "^7.0.2",
|
|
920
|
+
"webpack-dev-server": "^5.2.3"
|
|
847
921
|
}
|
|
848
922
|
}
|
|
849
923
|
`,
|
|
@@ -915,12 +989,11 @@ export default function CheckoutPanel() {
|
|
|
915
989
|
const webpack = require("webpack");
|
|
916
990
|
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
917
991
|
const { ModuleFederationPlugin } = webpack.container;
|
|
992
|
+
const packageJson = require("./package.json");
|
|
993
|
+
const { createSharedConfig } = require("../shared/buildSharedConfig");
|
|
918
994
|
|
|
919
995
|
const checkoutPort = Number(process.env.CHECKOUT_PORT || 3102);
|
|
920
|
-
const sharedConfig =
|
|
921
|
-
react: { singleton: true, requiredVersion: false },
|
|
922
|
-
"react-dom": { singleton: true, requiredVersion: false },
|
|
923
|
-
};
|
|
996
|
+
const sharedConfig = createSharedConfig(packageJson);
|
|
924
997
|
const exposeConfig = {
|
|
925
998
|
"./CheckoutPanel": path.resolve(__dirname, "./src/CheckoutPanel.jsx"),
|
|
926
999
|
"./InspectorBridge": path.resolve(__dirname, "./src/inspectorBridge.js"),
|
|
@@ -960,6 +1033,7 @@ module.exports = {
|
|
|
960
1033
|
},
|
|
961
1034
|
devServer: {
|
|
962
1035
|
port: checkoutPort,
|
|
1036
|
+
historyApiFallback: true,
|
|
963
1037
|
hot: true,
|
|
964
1038
|
headers: {
|
|
965
1039
|
"Access-Control-Allow-Origin": "*",
|
package/template/cockpit.json
CHANGED