Content Hashing for Static Assets
Overview
Content hashing fingerprints static assets (CSS, JS, images, fonts) by embedding a SHA-256 hash in the filename. This enables browsers and CDNs to cache assets indefinitely with Cache-Control: immutable.
Example: style.css becomes style.a1b2c3d4e5f67890.css
Configuration
Add to site.toml:
[build.content_hash]
enabled = true
Custom exclusions
[build.content_hash]
enabled = true
exclude = [
"favicon.ico",
"robots.txt",
"CNAME",
"_headers",
"_redirects",
".well-known/**",
"sw.js", # service workers need stable URLs
"manifest.json", # PWA manifests need stable URLs
]
How It Works
Three Phases
Phase 1 (Build Manifest): During
copy_static_assets, files indist/are hashed and renamed. A manifest maps original paths to hashed paths.Phase 2 (Template Resolution): The
asset()template function uses the manifest to return hashed paths at render time.Phase 3 (Post-Render Rewrite): After all rendering, a final pass rewrites any remaining hardcoded asset references in
.html,.css, and.jsfiles.
Template Usage
Always use the asset() function for static asset references:
<link rel="stylesheet" href="{{ asset('/css/style.7d5581acfb6a0b68.css') }}">
<script src="{{ asset('/js/app.js') }}"></script>
<img src="{{ asset('/images/logo.png') }}" alt="Logo">
Hardcoded paths also work (Phase 3 rewrites them), but asset() is preferred because it gives templates the correct URL at render time.
Default Exclusions
These files are excluded from hashing by default (they must keep stable names for deployment platforms):
favicon.icorobots.txtCNAME_headers_redirects.well-known/**
Dev Server
Content hashing is always disabled during dev server operation. The asset() function returns paths unchanged in dev mode.
Interactions
- Image optimization: Works correctly. Use
asset()for source image paths; image optimization reads the hashed filename from dist. - Critical CSS: Enhanced to resolve hashed paths via manifest fallback when the original file path is not found.
- Resource hints: Preload/prefetch URLs naturally use hashed paths when templates use
asset(). - Asset localization: Downloaded assets are not hashed (they already have content-based filenames).
Limitations
- Relative CSS
url()paths (e.g.,../images/icon.png) are not rewritten. Use absolute paths in CSS files. - Dynamic JavaScript references constructed at runtime cannot be statically rewritten.
- Source map relative references may not be rewritten. Use absolute paths or exclude
*.mapfiles.
Module Location
src/build/content_hash.rs -- single-file module containing AssetManifest, build_manifest(), and rewrite_references().