Skip to content

Add an opt-in image cache to capture#51

Merged
jeremyfelt merged 1 commit into
trunkfrom
image-cache
Jun 16, 2026
Merged

Add an opt-in image cache to capture#51
jeremyfelt merged 1 commit into
trunkfrom
image-cache

Conversation

@jeremyfelt

Copy link
Copy Markdown
Member

What

Adds an opt-in imageCache option to reglance.json so capture runs answer repeat image requests from a local disk cache instead of re-fetching every image from the origin once per viewport per parallel context.

"imageCache": true                  // per-run cache, cleared each capture
"imageCache": { "persist": true }   // kept across runs; clear with --fresh-images

How

No proxy server and no URL rewriting. Image requests are intercepted with the same context.route() hook already used for blockHosts and fulfilled from .reglance/image-cache/, so nothing in the DOM, the HTML snapshots, or the screenshots changes:

  • Cache key = the full request URL, query string included — CDN resize variants (photo.jpg?w=400 vs ?w=800) are distinct entries. Covers srcset, <picture>, and CSS background images automatically since interception happens at the network layer.
  • In-flight coalescing — parallel contexts requesting the same image at the same moment share one origin fetch, so even a cold first run only hits the origin once per distinct URL.
  • Scope is deliberately narrow — only GET image requests, only 2xx responses cached. Documents/CSS/JS are the content under test and always load from the origin; a broken image stays broken in the capture.
  • Failure-safe — any cache error hands the request back to the browser; a damaged entry reads as a miss; a failed disk write warns and serves the response uncached.

The default per-run mode is cleared at the start of every capture, so there is zero risk of a stale cached image masking a real origin change between control and compare runs. Persistence is a conscious opt-in for rapid re-capture loops, with --fresh-images as the escape hatch (documented trade-off in the README).

Verification

  • 118 tests pass (13 new: cache roundtrip, query-string keys, coalescing, non-2xx passthrough, rejection recovery, clear-on-open, stats, and config normalization); lint clean.
  • End-to-end smoke test against a local request-counting server, 2 viewports × 4 distinct image URLs:
    • Cold run: each image URL fetched from the origin exactly once (4 fetches, 4 served locally).
    • Warm persistent run: 0 origin image fetches, all 8 served locally; the HTML document still loaded fresh each navigation.
    • --fresh-images: cache cleared and re-seeded, one fetch per URL again.

🤖 Generated with Claude Code

Capturing a site once per viewport per parallel context re-fetches every
image from the origin each time, which can swarm a server — especially
uncached local or staging environments. The new "imageCache" option in
reglance.json answers repeat image requests locally instead.

No proxy server and no URL rewriting: image requests are intercepted via
the existing context.route() hook and fulfilled from a disk cache under
.reglance/image-cache/. The cache key is the full request URL, query
string included, so CDN resize variants stay distinct. Simultaneous
requests for the same URL share a single origin fetch. Only GET image
requests are cached — documents, CSS, and JS always load from the
origin — and only 2xx responses are stored, so a broken image stays
broken in the capture.

"imageCache": true gives a per-run cache cleared at the start of every
capture, so repeat traffic drops with no risk of a stale image masking a
real change between control and compare runs. { "persist": true } keeps
the cache across runs for rapid re-capture loops, with --fresh-images to
clear it on demand.

Co-Authored-By: Claude Fable 5 <[email protected]>
@jeremyfelt jeremyfelt merged commit 0a269fd into trunk Jun 16, 2026
2 checks passed
@jeremyfelt jeremyfelt deleted the image-cache branch June 16, 2026 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant