Documentation Index Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
Use this file to discover all available pages before exploring further.
Proper caching is crucial for frontend performance. Mizu implements intelligent caching based on asset types, content fingerprinting, and best practices.
Overview
The frontend middleware automatically applies caching based on three factors:
File type (HTML, JS, CSS, images, etc.)
Content fingerprinting (hash in filename)
Custom patterns (your configuration)
Default Caching Strategy
Asset Type Pattern Cache Duration Cache-Control Hashed assets *.abc123.js1 year public, max-age=31536000, immutableUnhashed assets logo.png1 week public, max-age=604800HTML files *.htmlNone no-cache, no-store, must-revalidateSource maps *.mapNone no-cache
How Content Hashing Works
When you build your frontend, tools like Vite add content hashes to filenames:
Before build:
main.js
styles.css
After build:
main.a1b2c3d4.js ← Hash added
styles.e5f6g7h8.css ← Hash added
The hash is based on file contents. If the file changes, the hash changes:
main.a1b2c3d4.js → main.x9y8z7w6.js
Why This Matters
Old approach (without hashing):
< script src = "/main.js" ></ script >
Problem: Browsers cache main.js. When you update it, users might still see the old cached version.
New approach (with hashing):
< script src = "/main.a1b2c3d4.js" ></ script >
Benefit: When you update the file, the filename changes:
< script src = "/main.x9y8z7w6.js" ></ script >
Browsers see a new filename and fetch the new file. The old file stays cached harmlessly.
Asset Classification
Mizu automatically classifies assets:
// Hashed assets (detected by pattern)
app . a1b2c3 . js → 1 year cache , immutable
vendor . xyz789 . css → 1 year cache , immutable
logo . abc123 . png → 1 year cache , immutable
// Unhashed assets
logo . png → 1 week cache
favicon . ico → 1 week cache
// HTML files
index . html → no - cache
about . html → no - cache
// Source maps
app . js . map → no - cache ( blocked by default )
Hash Detection Pattern
Mizu looks for this pattern in filenames:
Examples that match:
main.a1b2c3.js ✅
vendor-xyz789.css ✅
chunk.ABC123DEF.js ✅
logo_12ab34cd.png ✅
Examples that don’t match:
main.js ❌ (no hash)
version-1.2.3.js ❌ (not a hex hash)
user-123.png ❌ (too short)
Custom Cache Configuration
Override Defaults
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeProduction ,
Root : "./dist" ,
CacheControl : frontend . CacheConfig {
HashedAssets : 180 * 24 * time . Hour , // 6 months instead of 1 year
UnhashedAssets : 24 * time . Hour , // 1 day instead of 1 week
HTML : 0 , // no-cache (default)
},
}))
Pattern-Based Caching
Cache specific file types differently:
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeProduction ,
Root : "./dist" ,
CacheControl : frontend . CacheConfig {
Patterns : map [ string ] time . Duration {
// Fonts: cache for 30 days
"*.woff2" : 30 * 24 * time . Hour ,
"*.woff" : 30 * 24 * time . Hour ,
"*.ttf" : 30 * 24 * time . Hour ,
// Images: cache for 14 days
"*.jpg" : 14 * 24 * time . Hour ,
"*.jpeg" : 14 * 24 * time . Hour ,
"*.png" : 14 * 24 * time . Hour ,
"*.svg" : 14 * 24 * time . Hour ,
"*.webp" : 14 * 24 * time . Hour ,
// Manifests and configs: no cache
"manifest.json" : 0 ,
"robots.txt" : 0 ,
"sitemap.xml" : 0 ,
},
},
}))
Pattern matching order:
Check custom patterns first
If no match, check if file has hash
If hashed → use HashedAssets duration
If unhashed → use UnhashedAssets duration
If HTML → use HTML duration
Environment-Specific Caching
func getCacheConfig ( env string ) frontend . CacheConfig {
if env == "production" {
return frontend . CacheConfig {
HashedAssets : 365 * 24 * time . Hour ,
UnhashedAssets : 7 * 24 * time . Hour ,
}
}
// Shorter cache for staging
return frontend . CacheConfig {
HashedAssets : 24 * time . Hour ,
UnhashedAssets : 1 * time . Hour ,
}
}
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeProduction ,
Root : "./dist" ,
CacheControl : getCacheConfig ( os . Getenv ( "ENV" )),
}))
Cache-Control Directives
immutable
Hashed assets get the immutable directive:
Cache-Control: public, max-age=31536000, immutable
What it means:
public: Can be cached by browsers and CDNs
max-age=31536000: Cache for 1 year (in seconds)
immutable: File will never change (safe to cache forever)
Modern browsers skip revalidation for immutable resources.
no-cache vs no-store
HTML files get aggressive no-cache headers:
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
What each means:
no-cache: Revalidate before using cached copy
no-store: Don’t cache at all
must-revalidate: Obey the rules strictly
Pragma: no-cache: HTTP/1.0 compatibility
Expires: 0: Old-style expiration
CDN Caching
When using a CDN (CloudFlare, Fastly, etc.):
app . Use ( frontend . WithOptions ( frontend . Options {
Mode : frontend . ModeProduction ,
Root : "./dist" ,
CacheControl : frontend . CacheConfig {
// Aggressive caching for CDN
HashedAssets : 365 * 24 * time . Hour ,
UnhashedAssets : 7 * 24 * time . Hour ,
Patterns : map [ string ] time . Duration {
// Cache fonts for a very long time
"*.woff2" : 365 * 24 * time . Hour ,
},
},
}))
CDN benefits:
Files cached at edge locations
Faster delivery to users
Reduced origin server load
Mizu’s cache headers work automatically
Best Practices
1. Always Use Asset Fingerprinting
Ensure your build tool fingerprints assets:
Vite:
// vite.config.ts
export default {
build: {
rollupOptions: {
output: {
entryFileNames: 'assets/[name].[hash].js' ,
chunkFileNames: 'assets/[name].[hash].js' ,
assetFileNames: 'assets/[name].[hash].[ext]'
}
}
}
}
Angular:
{
"architect" : {
"build" : {
"configurations" : {
"production" : {
"outputHashing" : "all"
}
}
}
}
}
2. Never Cache HTML Files
Always set HTML caching to 0:
CacheControl : frontend . CacheConfig {
HTML : 0 , // Critical!
}
Why: HTML files reference the hashed assets. If HTML is cached, users might request old asset filenames that no longer exist.
3. Use Longer Cache for Fonts
Fonts rarely change:
Patterns : map [ string ] time . Duration {
"*.woff2" : 30 * 24 * time . Hour , // 30 days
}
Check headers with curl:
curl -I https://yourdomain.com/assets/main.abc123.js
Should show:
HTTP/2 200
cache-control: public, max-age=31536000, immutable
5. Monitor Cache Hit Rates
Use CDN analytics to track:
Cache hit rate (aim for >90%)
Bandwidth saved
Origin requests (should be minimal)
Debugging Cache Issues
Clear Browser Cache
Chrome:
Cmd/Ctrl + Shift + R (hard refresh)
Programmatically:
// In browser console
caches . keys (). then ( names => {
names . forEach ( name => caches . delete ( name ))
})
# Check a hashed asset
curl -I localhost:3000/assets/main.abc123.js
# Should show long cache
cache-control: public, max-age=31536000, immutable
# Check HTML
curl -I localhost:3000/
# Should show no-cache
cache-control: no-cache, no-store, must-revalidate
Common Issues
Problem: Users see old version after deployment
Solution: Check that:
HTML files have cache-control: no-cache
Asset filenames include content hash
Build generated new hashes
Problem: Assets not caching
Solution: Check that:
Filenames include hash pattern
Server is returning cache headers
HTTPS is enabled (required for some cache APIs)
Next Steps
Production Mode Production optimization guide
Security Security headers and best practices
Manifest Build manifest integration
Static Hosting Deploy to CDN