CACHE-002 recommended Static Asset Caching
Content hashes for cache invalidation
Asset filenames include content hashes enabling long TTLs with automatic invalidation on changes
Question to ask
"Do users need to hard-refresh to get your latest deploy?"
Verification guide
Severity: Recommended
Static asset filenames should include content hashes (e.g., main.a1b2c3d4.js). This enables aggressive caching while ensuring users always get the latest version when code changes.
Check automatically:
- Check build output for hashed filenames:
# Look for hash patterns in dist/build folder
ls -la dist/assets/ 2>/dev/null | grep -E '\.[a-f0-9]{6,}\.(js|css)$'
# Or in Next.js
ls -la .next/static/chunks/ 2>/dev/null | head -5
# Or in Vite
ls -la dist/assets/ 2>/dev/null | head -5
- Check HTML references for hashed assets:
# Extract script/link tags and check for hashes
curl -sL https://example.com | grep -oE '(src|href)="[^"]*\.[a-f0-9]{6,}\.(js|css)"' | head -5
- Check build config for content hashing:
# Vite (default enabled)
grep -r "build" vite.config.* 2>/dev/null | grep -i hash
# Webpack
grep -rE "contenthash|chunkhash" webpack.config.* 2>/dev/null
# Next.js (enabled by default, no config needed)
Cross-reference with:
- CACHE-001 (hashed assets should have immutable/long-TTL cache headers)
Pass criteria:
- JS and CSS filenames include content hashes (e.g.,
main.a1b2c3d4.js) - HTML references updated on each build to point to new hashes
- Cache-Control set to long TTL (1 year) or
immutablesince hash handles invalidation
Fail criteria:
- Static assets use fixed filenames (
main.js,styles.css) - Query string cache busting only (
main.js?v=123) - less reliable - No build pipeline (hand-editing JS/CSS files)
Evidence to capture:
- Sample hashed filenames from build output
- Build tool used (Vite, Webpack, Next.js, etc.)
- Cache-Control header on hashed assets