Skip to content

Commit 9f9f5e9

Browse files
fix(rsc): harden runtime registration refresh and verification
1 parent ad147a6 commit 9f9f5e9

6 files changed

Lines changed: 426 additions & 19 deletions

File tree

examples/rsbuild-rsc-federation/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,13 @@ From repository root:
7474

7575
```bash
7676
pnpm --filter examples-rsbuild-rsc-federation... install
77-
pnpm --filter examples-rsbuild-rsc-federation run build
78-
pnpm --filter examples-rsbuild-rsc-federation run verify:manifest
77+
pnpm --filter examples-rsbuild-rsc-federation run build:verify
7978
```
8079

81-
The verification script fails fast on any mismatch and prints the resolved manifest file paths on success.
80+
The verification scripts fail fast on any mismatch and cover both:
81+
82+
- emitted manifest/stat expectations
83+
- runtime-plugin registration and invalidation behavior
8284

8385
## E2E smoke test
8486

examples/rsbuild-rsc-federation/e2e/app.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ for (const app of appUrls) {
7171
'./server-mixed',
7272
];
7373
const expectedClientExposes = ['./button', './composed'];
74+
const unexpectedClientExposes = ['./consumer', './server-mixed'];
7475

7576
const statsExposePaths = stats.exposes.map(
7677
(expose: { path: string }) => expose.path,
@@ -95,13 +96,30 @@ for (const app of appUrls) {
9596
expect(clientManifestExposePaths).toContain(exposePath);
9697
}
9798

99+
for (const exposePath of unexpectedClientExposes) {
100+
expect(clientStatsExposePaths).not.toContain(exposePath);
101+
expect(clientManifestExposePaths).not.toContain(exposePath);
102+
}
103+
98104
const sharedNames = stats.shared.map(
99105
(shared: { name: string }) => shared.name,
100106
);
101107
expect(sharedNames).toContain('rsbuild-rsc-federation-shared');
102108
expect(sharedNames).toContain(
103109
'rsbuild-rsc-federation-shared/server-actions',
104110
);
111+
const clientSharedNames = clientStats.shared.map(
112+
(shared: { name: string }) => shared.name,
113+
);
114+
const clientManifestSharedNames = clientManifest.shared.map(
115+
(shared: { name: string }) => shared.name,
116+
);
117+
expect(clientSharedNames).not.toContain(
118+
'rsbuild-rsc-federation-shared/server-actions',
119+
);
120+
expect(clientManifestSharedNames).not.toContain(
121+
'rsbuild-rsc-federation-shared/server-actions',
122+
);
105123

106124
const sharedActionsEntry = stats.shared.find(
107125
(shared: {

examples/rsbuild-rsc-federation/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"build": "rsbuild build",
77
"dev:e2e": "rsbuild dev --port 3330",
88
"verify:manifest": "node ./scripts/verify-manifest.mjs",
9-
"build:verify": "pnpm run build && pnpm run verify:manifest",
9+
"verify:runtime-plugin": "node --experimental-vm-modules ./scripts/verify-runtime-plugin.mjs",
10+
"build:verify": "pnpm run build && pnpm run verify:manifest && pnpm run verify:runtime-plugin",
1011
"test:e2e": "playwright test --config ./playwright.config.ts"
1112
},
1213
"dependencies": {

examples/rsbuild-rsc-federation/scripts/verify-manifest.mjs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,22 @@ invariant(
357357
clientStats.exposes.some((item) => item.path === './composed'),
358358
'Expected client stats to include expose "./composed"',
359359
);
360+
invariant(
361+
!clientStats.exposes.some((item) => item.path === './consumer'),
362+
'Did not expect client stats to include server-only expose "./consumer"',
363+
);
364+
invariant(
365+
!clientStats.exposes.some((item) => item.path === './server-mixed'),
366+
'Did not expect client stats to include server-only expose "./server-mixed"',
367+
);
368+
invariant(
369+
!clientManifest.exposes.some((item) => item.path === './consumer'),
370+
'Did not expect client manifest to include server-only expose "./consumer"',
371+
);
372+
invariant(
373+
!clientManifest.exposes.some((item) => item.path === './server-mixed'),
374+
'Did not expect client manifest to include server-only expose "./server-mixed"',
375+
);
360376
const expectedClientSingletonShares = [
361377
'react',
362378
'react/jsx-runtime',
@@ -375,6 +391,18 @@ for (const shareName of expectedClientSingletonShares) {
375391
`Expected client shared singleton "${shareName}" to be true`,
376392
);
377393
}
394+
invariant(
395+
!clientStats.shared.some(
396+
(item) => item.name === 'rsbuild-rsc-federation-shared/server-actions',
397+
),
398+
'Did not expect client stats to include server-only shared actions entry',
399+
);
400+
invariant(
401+
!clientManifest.shared.some(
402+
(item) => item.name === 'rsbuild-rsc-federation-shared/server-actions',
403+
),
404+
'Did not expect client manifest to include server-only shared actions entry',
405+
);
378406

379407
console.log('[verify-manifest] verified manifest and stats successfully');
380408
console.log(`[verify-manifest] stats: ${statsPath}`);

0 commit comments

Comments
 (0)