mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[GH-ISSUE #389] perf: emit pre-compiled regex literals for config patterns at build time #85
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#85
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @james-elicx on GitHub (Mar 9, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/389
Background
PR #387 fixed the dominant per-request CPU bottleneck in
matchConfigPatternby adding a module-levelMapcache so the tokeniser,isSafeRegexscan, andnew RegExp()call run at most once per unique pattern string per isolate lifetime.That fix is sufficient for long-lived isolates (Cloudflare Workers reuses isolates aggressively for popular routes). The remaining opportunity is to move pattern compilation entirely to build time so even the first request after a cold start pays zero compilation cost.
What this would look like
Redirect/rewrite
sourcepatterns are already baked into the bundle as JSON-serialized arrays:With build-time compilation, the code generator would also emit a parallel compiled array as raw JS regex literals, completely bypassing
matchConfigPattern's regex branch at runtime:matchRedirectwould accept an optional pre-compiled array and skipmatchConfigPatternentirely when it's present.What needs to change
Extract a
compileConfigPattern(pattern)function frommatchConfigPatternthat returns{ re: RegExp; paramNames: string[] } | null— the same logic currently cached by_compiledPatternCache, made callable from the code generators.generateRscEntry(App Router) — callcompileConfigPatternfor each redirect/rewrite/header source at code-gen time; emit__compiledRedirects,__compiledRewrites,__compiledHeadersas JS regex literals alongside the existing__configRedirectsJSON arrays.generateServerEntry(Pages Router) — same: embed compiled forms into thevinextConfigexport or as separate module-level constants.matchRedirect/matchRewrite— add an overload (or a newmatchRedirectCompiled) that accepts the pre-compiled array and skips tore.execdirectly.Dev server (
index.tsconnect handler) — the dev server callsapplyRedirects/applyRewriteswhich callmatchRedirect/matchRewritewith the livenextConfigarrays. Pre-compilation here would mean compiling once at plugin init time (afterresolveNextConfig) and keeping a compiled copy alongsidenextConfig. Worth doing for consistency, though the module-level cache inconfig-matchers.tsalready covers this path.Emit regex source correctly —
re.source+re.flagscan be used to reconstruct a regex literal as a string:`/${re.source}/${re.flags}`. Flags are""for all current patterns (noi,g, etc.), so the output is simply/${re.source}/.Why the current cache is sufficient for most cases
The module-level
Mapcache (PR #387) means:Map.getper rule — identical to reading a module constantBuild-time emission only helps the first request after a cold start on low-traffic routes where isolates are recycled frequently. For high-traffic routes Workers keeps isolates alive long enough that the cache is always warm.
When to prioritise this
Worth revisiting if profiling shows measurable p99 cold-start latency from pattern compilation, or if the codebase moves toward a model where isolates are intentionally short-lived (e.g. per-request isolate mode).