feat: image cache warmup, query params, and docs#110
Conversation
- Remove 500 entry cache limit and eviction logic - Extract optimizeImage function for reuse - Add image-warmup Nitro plugin that pre-caches all content images as webp at default width after first response - Export STORAGE_KEY and cacheKey for plugin access Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
More reviews will be available in 37 minutes and 51 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThe PR extracts image optimization logic from the request handler into a reusable public function and introduces a server startup plugin that pre-warms the image cache by scanning the content directory and optimizing undiscovered raster images with default parameters. ChangesImage Cache Optimization and Warmup
🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/chronicle/src/server/api/image.ts`:
- Around line 123-125: The cache key generation for optimized images (variable
key, created via cacheKey) lacks a source fingerprint, so replacing the original
file can leave stale optimized bytes in the fs-backed image-cache; update the
logic around the work closure that calls optimizeImage and storage.setItemRaw to
include a source version signal (e.g., file mtime or a content hash) in the
cache key or store metadata with the cached entry and validate staleness before
returning cached data. Concretely, compute a fingerprint from
fs.stat(filePath).mtimeMs or a short hash of the source file, incorporate that
fingerprint into cacheKey(url, w, q, format, fingerprint) when writing via
storage.setItemRaw, and ensure the read path that looks up cached entries
verifies the same fingerprint (or checks stored metadata) and falls back to
re-optimizing when mismatched.
In `@packages/chronicle/src/server/plugins/image-warmup.ts`:
- Around line 16-20: The code currently allows recursion when
entry.isSymbolicLink() is true, which can follow symlinks outside the content
tree; update the logic in findImages so you do not recurse into symlinked
directories: use fs.lstat or the Dirent methods to detect symlinks
(entry.isSymbolicLink()) and skip them when deciding to recurse, and only
recurse when the target is a real directory (e.g., keep the stat check and call
images.push(...await findImages(fullPath)) only when entry.isDirectory() is true
and entry.isSymbolicLink() is false or when lstat confirms it's not a symlink).
- Around line 35-52: The warmup currently hard-codes format = 'webp' so warmed
cache misses AVIF-capable requests; change the warmup to produce the same
formats the image handler would negotiate by either calling/shared negotiation
logic from the image handler (if there's an exported function) or iterating the
preferred formats (e.g. 'avif' then 'webp') and generating cache entries for
each format: update image-warmup.ts to replace the single const format = 'webp'
with a loop over formats (or call the handler's negotiate function), then call
cacheKey(url, w, q, format), storage.getItemRaw/setItemRaw and
optimizeImage(filePath, w, q, format) for each format to ensure AVIF cache
entries are created too.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2a78c8f3-a383-4893-b24a-31546ae3ef6e
📒 Files selected for processing (2)
packages/chronicle/src/server/api/image.tspackages/chronicle/src/server/plugins/image-warmup.ts
Delete separate image-warmup plugin. Warmup now uses getPages() + getPageImages() from source.ts (images already collected by remark plugin). Triggered from ready probe alongside search index. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Authors can now specify w and q on image URLs:  Params are parsed from the URL, stripped before file resolution, and passed through to the optimization endpoint. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covers format negotiation, query params (w/q), allowed values, API endpoint, caching, and warmup behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cache key now includes source file mtime — replacing an image invalidates stale cache entries. Added biome-ignore for useStorage in warmupImageCache. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| export async function warmupImageCache() { | ||
| const { getPages, getPageImages } = await import('@/lib/source'); | ||
| // biome-ignore lint/correctness/useHookAtTopLevel: useStorage is a Nitro DI accessor, not a React hook | ||
| const storage = useStorage(STORAGE_KEY); |
There was a problem hiding this comment.
Would this work with other toolkits apart from nitro?
There was a problem hiding this comment.
No, it needs nitro. but we get abstration over different run time and different stoage options
https://nitro.build/docs/storage
Summary
optimizeImagefunction for reusewarmupImageCache()usinggetPages()+getPageImages(), triggered from readiness probe?w=640&q=90query params on image URLs in markdownChanges
src/server/api/image.ts— remove cache limit, extractoptimizeImage, addwarmupImageCachesrc/server/api/ready.ts— trigger warmup alongside search indexsrc/lib/remark-resolve-images.ts— parse w/q query params from image URLsdocs/content/docs/image-optimization.mdx— full documentationTest plan