Skip to content

perf: add long-lived cache headers for content-hashed static assets in nginx #686

@Aureliolo

Description

@Aureliolo

Summary

Vite produces content-hashed filenames (e.g., app.abc123.js) but nginx serves them without explicit long-lived cache headers. Adding Cache-Control: public, immutable with a long expires for hashed assets would eliminate unnecessary revalidation requests.

Context

Docker Desktop AI analysis flagged this as an optimization. Validated against actual code -- this is the one genuinely useful recommendation from that analysis.

Details

Add a location block for hashed static assets in web/nginx.conf:

location ~* \.(js|css|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

Important caveat: nginx does NOT inherit add_header directives from the server block into location blocks that define their own add_header (documented in our nginx.conf lines 23-25). All security headers must be repeated in this new location block:

  • X-Content-Type-Options
  • X-Frame-Options
  • Referrer-Policy
  • Permissions-Policy
  • Content-Security-Policy
  • Strict-Transport-Security

Investigation needed

  • Confirm Vite's output uses content hashes for all JS/CSS (check web/dist/ after a build)
  • Decide whether index.html should get a shorter cache (e.g., no-cache) since it's the entry point that references hashed assets
  • Consider extracting repeated security headers into an include snippet to avoid duplication
  • Measure actual cache-hit improvement (may be marginal for self-hosted single-user setups)

Acceptance criteria

  • Hashed static assets served with Cache-Control: public, immutable and long expiry
  • Security headers preserved on all responses (no regression from location block override)
  • index.html cache policy explicitly set (short or no-cache)

Metadata

Metadata

Assignees

No one assigned

    Labels

    prio:lowNice to have, can deferscope:smallLess than 1 day of worktype:choreMaintenance, cleanup, dependency updatesv0.4Minor version v0.4v0.4.8Patch release v0.4.8

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions