Skip to content

Hashed assets are never cached: the immutable location is unreachable for prefixed paths #66

Description

@oto-macenauer-absa

Summary

nginx.conf declares a long-cache policy for hashed assets:

location ~* \.(css|js|woff2?|ttf|eot|ico|svg|png|jpg|gif|webp)$ {
    include /etc/nginx/kb-headers.conf;
    expires 1y;
    add_header Cache-Control "public, immutable";
}

It never runs in production. Every asset is served under a prefix, and both prefix locations are declared with ^~:

location ^~ /__wf/knowledge-base/ {}
location ^~ /knowledge-base/      {add_header Cache-Control "no-transform" always;}

^~ tells nginx to stop and not evaluate regex locations once the prefix matches. So:

request location that serves it Cache-Control
/knowledge-base/_astro/x-HASH.css ^~ /knowledge-base/ no-transform
/__wf/knowledge-base/style.css ^~ /__wf/knowledge-base/ (none)
/_astro/x-HASH.css regex public, immutable, 1y

Only the third row exists in a direct-to-root deployment, which is not how this is served.

Effect

  1. Content-hashed assets get no caching policy at all. Browsers fall back to heuristic freshness. The hashing work (_astro/[name]-[hash][extname]) buys nothing.
  2. no-transform is not a caching directive. It was added for a real reason (Security: nginx location blocks silently drop every inherited CORS and security header #45-era gateway re-encoding), but as the only Cache-Control token on the response it silently replaced the caching intent.
  3. /__wf/knowledge-base/* responses carry no Cache-Control at all — that block declares no add_header, so it inherits the server-level set (which has no Cache-Control) and skips the regex block.

Complication: the one asset that must not be cached that way

dist/style.css is deliberately unhashed — sub-app pages reference /{prefix}/style.css literally (see #50, fixed in #65). It is the one asset that cannot be content-addressed, so if the immutable policy is made reachable it must exclude that path, or a deploy that changes the marketplace CSS will not reach returning browsers for a year.

Suggested fix

Set the caching policy inside the prefix locations, alongside no-transform, rather than relying on a regex location that can never be reached:

  • hashed assets (_astro/…, anything with a hash in the name) → public, immutable, max-age=31536000, no-transform
  • style.csspublic, max-age=0, must-revalidate, no-transform
  • HTML → unchanged

add_header does not merge across levels, so every block that sets one must still include /etc/nginx/kb-headers.conf (#45).

tests/fragment-server.mjs mirrors these rewrites and must change with them; npm run test:container is the only place the shipped config actually executes, so the change has to be proven there. tests/container.spec.js currently asserts no-transform on knowledge-base responses and would need extending to assert the caching policy per asset class.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions