Cache Busting with File Hashing
Learn how content-hash filenames enable aggressive caching strategies. Understand how build tools generate hashed filenames and why this approach is superior to query strings.
Detailed Explanation
Cache Busting Techniques
Cache busting forces browsers and CDNs to download a fresh version of a resource that would otherwise be served from cache. Content hashing is the most reliable technique.
The Problem
You deploy a CSS file at /styles.css with max-age=31536000. A week later, you change the colors. Users who visited before still see the old colors because their browser has a cached version valid for a year.
Solution 1: Content Hash Filenames (Best)
/styles-a1b2c3d4.css → (v1)
/styles-e5f6g7h8.css → (v2, different hash = different URL)
Build tools compute a hash of the file contents and embed it in the filename. When the content changes, the hash changes, producing a new URL that bypasses all caches.
How build tools implement it:
// vite.config.ts
export default {
build: {
rollupOptions: {
output: {
entryFileNames: 'assets/[name]-[hash].js',
chunkFileNames: 'assets/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash].[ext]',
},
},
},
};
Solution 2: Query Strings (Avoid)
<link rel="stylesheet" href="/styles.css?v=2.3.1">
Problems:
- Some CDNs and proxies ignore query strings when caching
- URLs with query strings may not be cached at all by some proxies
- Less reliable than filename hashing
Solution 3: Directory Versioning
/v2.3.1/styles.css
Problems:
- Requires server-side URL rewriting
- Invalidates ALL assets on version bump, even unchanged ones
- Less granular than content hashing
Content Hash vs Version Number
| Aspect | Content Hash | Version Number |
|---|---|---|
| Granularity | Per-file | All files |
| Cache efficiency | Only changed files re-downloaded | All files re-downloaded |
| Build complexity | Handled by bundler | Manual or CI/CD |
| Cache header | max-age=31536000, immutable | Same |
The Complete Pipeline
- Build tool generates hashed filenames
- HTML references the hashed filenames
- Server sets
Cache-Control: public, max-age=31536000, immutable - CDN caches indefinitely
- On deploy, new HTML points to new hashed files
- Old files remain cached (for users who haven't refreshed)
- Old files are eventually evicted or cleaned up
Use Case
A large-scale web application with 200+ JavaScript chunks uses Vite's content hashing. Each deployment changes only the chunks that were actually modified — typically 5–10 out of 200. Returning users only download those 5–10 changed chunks while the other 190 are served from cache. Combined with 'max-age=31536000, immutable', this reduces average page load bandwidth by 95% for returning visitors.