mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
88ed49e11d
* perf(build): cache repeated compatibility transforms App Router builds run pure dynamic-request and typeof window transforms repeatedly across RSC, SSR, and analysis passes. Re-parsing identical module input adds build work without changing output. The transform hooks now reuse results for exact module id, source, and environment replacement keys while replacing stale per-id source entries. Focused tests cover cache reuse and key separation. * perf(build): reuse pure compatibility transforms Repeated build environments can parse and rewrite the same module source more than once. The transform result is deterministic once the module id, source, and environment-derived variant are fixed. Share the existing bounded per-module cache across the compatible transform plugins and cover source, module, variant, and null-result boundaries. * fix(build): invalidate cached source identities after junction retargets Repeated transforms can keep emitting import.meta.url and CJS globals for a junction's previous canonical target when the raw ID and source stay unchanged. The import-meta-url cache variant omitted the canonical path even though the rewrite derives its output from that path. Include canonicalId in the variant and cover retargeting between identical source files. * ci: rerun performance benchmarks * perf(build): avoid composite import-meta cache keys Eligible import-meta transforms allocate and hash a composite string containing the canonical root and module path on every invocation, including cache hits. That adds deterministic work to dev cold start. Keep source, canonical root, and canonical id as direct equality fields in a per-module entry. Retain only the two-value environment result map so canonical-path invalidation remains correct without composite key allocation. --------- Co-authored-by: James <james@eli.cx>
75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
import { describe, expect, it } from "vite-plus/test";
|
|
import { createTransformCache } from "../packages/vinext/src/plugins/transform-cache.js";
|
|
|
|
describe("createTransformCache", () => {
|
|
it("returns the cached result for a repeated id/source pair without recomputing", () => {
|
|
const cache = createTransformCache<undefined, { code: string }>();
|
|
let calls = 0;
|
|
const compute = () => {
|
|
calls += 1;
|
|
return { code: "out" };
|
|
};
|
|
|
|
const first = cache("/app/page.tsx", "in", undefined, compute);
|
|
const second = cache("/app/page.tsx", "in", undefined, compute);
|
|
|
|
expect(second).toBe(first);
|
|
expect(calls).toBe(1);
|
|
});
|
|
|
|
it("recomputes and replaces the entry when the source changes for an id", () => {
|
|
const cache = createTransformCache<undefined, string>();
|
|
let calls = 0;
|
|
const compute = () => {
|
|
calls += 1;
|
|
return `result-${calls}`;
|
|
};
|
|
|
|
expect(cache("/app/page.tsx", "v1", undefined, compute)).toBe("result-1");
|
|
expect(cache("/app/page.tsx", "v2", undefined, compute)).toBe("result-2");
|
|
// The v1 entry was replaced, not retained alongside v2.
|
|
expect(cache("/app/page.tsx", "v1", undefined, compute)).toBe("result-3");
|
|
});
|
|
|
|
it("caches variants independently for the same id/source pair", () => {
|
|
const cache = createTransformCache<string, string>();
|
|
let calls = 0;
|
|
const compute = (variant: string) => () => {
|
|
calls += 1;
|
|
return `${variant}-${calls}`;
|
|
};
|
|
|
|
const server = cache("/app/page.tsx", "in", "server", compute("server"));
|
|
const client = cache("/app/page.tsx", "in", "client", compute("client"));
|
|
|
|
expect(server).toBe("server-1");
|
|
expect(client).toBe("client-2");
|
|
expect(cache("/app/page.tsx", "in", "server", compute("server"))).toBe(server);
|
|
expect(cache("/app/page.tsx", "in", "client", compute("client"))).toBe(client);
|
|
expect(calls).toBe(2);
|
|
});
|
|
|
|
it("caches null results instead of recomputing them", () => {
|
|
const cache = createTransformCache<undefined, string | null>();
|
|
let calls = 0;
|
|
const compute = () => {
|
|
calls += 1;
|
|
return null;
|
|
};
|
|
|
|
expect(cache("/app/page.tsx", "in", undefined, compute)).toBeNull();
|
|
expect(cache("/app/page.tsx", "in", undefined, compute)).toBeNull();
|
|
expect(calls).toBe(1);
|
|
});
|
|
|
|
it("keys entries by id so distinct modules with identical source do not collide", () => {
|
|
const cache = createTransformCache<undefined, { id: string }>();
|
|
|
|
const a = cache("/app/a.tsx", "same", undefined, () => ({ id: "a" }));
|
|
const b = cache("/app/b.tsx", "same", undefined, () => ({ id: "b" }));
|
|
|
|
expect(a).not.toBe(b);
|
|
expect(cache("/app/a.tsx", "same", undefined, () => ({ id: "recomputed" }))).toBe(a);
|
|
});
|
|
});
|