mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
e372ff336a
Vitest integration CI shards by test file, so the 340-test App Router integration file becomes one oversized scheduling unit. That makes the slowest shard depend on one monolithic file even after adding native shards. Split the App Router integration coverage into focused files and increase the integration matrix to four native Vitest shards. This keeps fileParallelism disabled for shared-fixture safety while giving CI smaller scheduling units to distribute. Validation: vp check tests/app-router-*.test.ts vite.config.ts .github/workflows/ci.yml; vp test run --project integration tests/app-router-client-preloading.test.ts tests/app-router-dev-server.test.ts tests/app-router-external-rewrite.test.ts tests/app-router-font-google-prod.test.ts tests/app-router-isr-codegen.test.ts tests/app-router-malformed-url.test.ts tests/app-router-metadata-routes.test.ts tests/app-router-middleware-next-request.test.ts tests/app-router-next-config-codegen.test.ts tests/app-router-next-config-dev.test.ts tests/app-router-origin-check.test.ts tests/app-router-production-build.test.ts tests/app-router-production-server.test.ts tests/app-router-rsc-flight-hint.test.ts tests/app-router-rsc-plugin.test.ts tests/app-router-static-export.test.ts tests/app-router-worker-entry.test.ts
62 lines
2.8 KiB
TypeScript
62 lines
2.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
describe("Client reference preloading (Issue #256)", () => {
|
|
it("preloading correctly warms the memoize cache", async () => {
|
|
// Replicate the memoize + lazy-load pattern from @vitejs/plugin-rsc
|
|
// to verify that preloading prevents the first-request 500.
|
|
const loadCounts = new Map<string, number>();
|
|
|
|
function memoize(f: (id: string) => Promise<Record<string, unknown>>) {
|
|
const cache = new Map<string, Promise<Record<string, unknown>>>();
|
|
return (id: string) => {
|
|
const cached = cache.get(id);
|
|
if (cached !== undefined) return cached;
|
|
const result = f(id);
|
|
cache.set(id, result);
|
|
return result;
|
|
};
|
|
}
|
|
|
|
// Simulate lazy client module loading (async import)
|
|
const requireModule = memoize(async (id: string) => {
|
|
loadCounts.set(id, (loadCounts.get(id) ?? 0) + 1);
|
|
// Simulate async module load
|
|
await new Promise((r) => setTimeout(r, 10));
|
|
return { default: `component-${id}` };
|
|
});
|
|
|
|
const clientRefs = { "comp-a": true, "comp-b": true, "comp-c": true };
|
|
|
|
// Without preloading: requireModule returns unresolved promises
|
|
const beforePreload = requireModule("comp-a");
|
|
// The promise is pending — this is what causes the 500 on first request
|
|
expect(beforePreload).toBeInstanceOf(Promise);
|
|
|
|
// Preload all references (the fix)
|
|
await Promise.all(Object.keys(clientRefs).map((id) => requireModule(id)));
|
|
|
|
// After preloading: memoize cache is warm, promises are resolved.
|
|
// Calling requireModule again returns the same (now-resolved) promise.
|
|
const afterPreload = requireModule("comp-a");
|
|
expect(afterPreload).toBeInstanceOf(Promise);
|
|
const resolved = await afterPreload;
|
|
expect(resolved).toEqual({ default: "component-comp-a" });
|
|
|
|
// Critical invariant: after preloading, the cached promise must be
|
|
// already settled. React SSR calls __vite_rsc_client_require__ and
|
|
// expects a synchronously resolvable value — if the promise is still
|
|
// pending, renderToReadableStream rejects (the original 500 bug).
|
|
const SETTLED = Symbol("settled");
|
|
const raceResult = await Promise.race([requireModule("comp-b"), Promise.resolve(SETTLED)]);
|
|
// If the cached promise were still pending, raceResult would be SETTLED.
|
|
// A resolved cache means the module value wins the race.
|
|
expect(raceResult).toEqual({ default: "component-comp-b" });
|
|
|
|
// Each module should only be loaded once (memoize dedup)
|
|
expect(loadCounts.get("comp-a")).toBe(1);
|
|
expect(loadCounts.get("comp-b")).toBe(1);
|
|
expect(loadCounts.get("comp-c")).toBe(1);
|
|
});
|
|
});
|
|
// ── Auto-registration of @vitejs/plugin-rsc ─────────────────────────────────
|