levineuwirth.org/nginx/static-assets.conf

79 lines
3.3 KiB
Plaintext

# static-assets.conf — Compression + long-lived cache headers for static assets.
#
# Place at /etc/nginx/snippets/static-assets.conf and `include` it inside
# the server { } block of the levineuwirth.org vhost:
#
# server {
# server_name levineuwirth.org;
# root /var/www/levineuwirth.org;
# ...
# include snippets/static-assets.conf;
# include snippets/popup-proxy.conf;
# }
#
# Pairs with tools/compress-assets.sh, which pre-generates .gz and .br
# sidecars at build time so nginx never pays the compression cost at
# request time.
# ── On-the-fly gzip (fallback) ───────────────────────────────────────
# Covers dynamically generated responses and any file for which a .gz
# sidecar was not produced (e.g. files smaller than compress-assets.sh's
# MIN_SIZE threshold, or extensions not on its allow-list).
gzip on;
gzip_vary on;
gzip_comp_level 6;
gzip_min_length 256;
gzip_proxied any;
gzip_types text/plain
text/css
text/xml
application/javascript
text/javascript
application/json
application/xml
application/xml+rss
application/wasm
image/svg+xml;
# ── Pre-compressed sidecars ──────────────────────────────────────────
# Serve <file>.gz / <file>.br when the client advertises a matching
# Accept-Encoding. Zero request-time CPU; maximum compression ratio
# because the sidecars were produced with gzip -9 / brotli -Z.
gzip_static on;
# brotli_static requires the ngx_brotli module:
# Arch: pacman -S nginx-mod-brotli (or build nginx-mainline with the module)
# Debian/Ubuntu: apt install libnginx-mod-brotli
# If the module is absent, comment out the two brotli lines below; gzip_static
# will still cover every modern browser. Chromium/Firefox/Safari all accept gzip.
brotli_static on;
brotli off; # we ship pre-compressed sidecars only, no on-the-fly brotli
# ── Cache headers ────────────────────────────────────────────────────
# PDF.js viewer is version-pinned in tools/download-pdfjs.sh — bumping
# the pin is a deploy, so `immutable` is safe and makes repeat visits
# instantaneous. Same reasoning applies to fingerprinted fonts and the
# locally vendored ML model files.
location ^~ /pdfjs/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
access_log off;
}
location ^~ /fonts/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
access_log off;
}
location ^~ /models/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
access_log off;
}
# Per-extension caching for assets that live alongside HTML. CSS and JS
# in this repo are not fingerprinted, so a 1-day cache with must-revalidate
# keeps them responsive to deploys without forcing a fetch on every page.
location ~* \.(?:css|js|mjs|woff2?|svg|webp|png|jpg|jpeg|ico)$ {
add_header Cache-Control "public, max-age=86400, must-revalidate" always;
access_log off;
}