Skip to content

perf(server): stream static files and cache hashed build assets - #239

Merged
leoisadev1 merged 4 commits into
mainfrom
leoisadev1/t3-port-static-cache
Sep 14, 2026
Merged

leoisadev1 merged 4 commits into
mainfrom
leoisadev1/t3-port-static-cache

Conversation

@leoisadev1

@leoisadev1 leoisadev1 commented Sep 10, 2026

Copy link
Copy Markdown
Member

Problem

Self-hosted static responses read whole files and sent no cache policy. Reloads re-downloaded unchanged bundles, and an atomic file replace could mix old headers with a new body.

Adaptation

Hashed files listed in Vite's build manifest use immutable caching. Other files, SPA fallback HTML, and hash-like custom names revalidate with constant-cost validators derived from the open file descriptor's device, inode, size, and nanosecond modification and change times. If descriptor identity is unavailable, the server omits the validator and returns the current representation. Date-only conditional requests for mutable files also return the current representation because an unchanged modification time cannot prove the content is unchanged. Each response opens one request-scoped handle for metadata, validation, and bytes, so replacements cannot mix versions. HTML stays no-cache.

The web build now emits .vite/manifest.json. Akeru path-traversal checks are unchanged.

Upstream credits

Reviewed adaptation of T3 Code #9669.

Scope

Static HTTP serving and caching only. Server replay, client subscriptions, config bootstrap, and reducer reference stability are separate PRs.

Verification

  • vp test run apps/server/src/server.test.ts -t 'static|dev URL': 9 passed, covering conditional validators, equal-size replacements with preserved mtimes, hashed vs mutable files, SPA fallback, missing or invalid manifests, atomic replacement, and handle cleanup after GET, HEAD, 304, and cancellation
  • Server typecheck passed
  • Targeted lint on changed files passed with one pre-existing unused test-helper warning

No live UI behavior changes in dev; Vite still owns that path. Production static serving is covered by the HTTP tests.

Grok 4.6 High in Grok Build authored the adaptation. Codex gpt-5.6-sol in T3 Code completed the review fix.

Self-hosted web reloads sent whole files with no validators. Hashed Vite manifest entries now get immutable caching. Other files, SPA HTML, and hash-like custom names revalidate with weak ETags. Each response reads metadata and bytes from one request-scoped handle so an atomic replace cannot mix old headers with a new body.

Adapted from T3 Code pingdotgg#9669. Path traversal checks stay in place.

Grok 4.6 High in Grok Build via Orca.
@vercel

vercel Bot commented Sep 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
akeru-bot-landing Skipped Skipped Sep 10, 2026 6:13pm UTC

Request Review

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Sep 10, 2026
@greptile-apps

greptile-apps Bot commented Sep 10, 2026

Copy link
Copy Markdown

Greptile Summary

This PR updates production static-file delivery to stream from request-scoped file handles, identify immutable build assets from Vite’s manifest, and apply revalidation behavior to mutable files.

Confidence Score: 5/5

Safe to merge.

No outstanding findings remain. The stale-validator thread was resolved by Greptile without explanation. The full-file validator-read thread was resolved by Greptile without explanation.

Reviews (3): Last reviewed commit: "fix(server): avoid reading static files ..." | Re-trigger Greptile

Comment thread apps/server/src/http.ts Outdated
@leoisadev1

Copy link
Copy Markdown
Member Author

This is Leo's agent. I independently reproduced the stale-validator finding against the shipped HTTP route on 1e9c307. After serving build A, an atomic replacement with different equal-length build B bytes and preserved mtime still returns 304 to the old If-None-Match validator. The regression expected 200 and fails in 91 ms. The nine existing focused static-route tests pass, but do not cover this case. A scoped repair and committed regression request was delivered to the existing worker; execution is currently blocked by service errors and exhausted weekly quota. This remains unaddressed and the PR stays open.

Comment thread apps/server/src/http.ts Outdated
@leoisadev1

Copy link
Copy Markdown
Member Author

This is Leo's agent. I independently confirmed the new full-file-read finding on exact head 2c9d25f through the shipped HTTP route. Restoring the no-additional-body-read assertion in closes static file handles after GET, HEAD, 304, and request cancellation fails after the real descriptor-close signal: HEAD increases readAlloc calls from 2 to 3 for the 19,456-byte mutable index. The supplemental test fails in 101 ms without sleeps or polling. The nine committed static-route tests pass, but the revised committed test now explicitly expects HEAD and 304 to read the body.

The preserved-mtime validator repair is real; please retain it. The remaining scoped repair is to avoid full mutable-file pre-reads on every request while preserving correct replacement invalidation and same-handle metadata/body behavior. Add regressions for GET read volume, repeated HEAD and conditional 304 reads, equal-size preserved-mtime replacement, and handle cleanup/cancellation. Do not revert to size+mtime-only validation or simply weaken the assertions to accept the regression. This remains held despite successful Repository checks. Orca access is unavailable here, so this GitHub request is not a claim of worker delivery or execution.

@leoisadev1
leoisadev1 merged commit 0dd672d into main Sep 14, 2026
11 checks passed
@leoisadev1
leoisadev1 deleted the leoisadev1/t3-port-static-cache branch September 14, 2026 01:43
This was referenced Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant