From 6e5dee38e927fac86855d17dfb614fbb64b172b3 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Mon, 5 Oct 2026 09:42:05 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(frontend)=20cache=20hashed=20next?= =?UTF-8?q?=20static=20assets=20and=20revalidate=20html?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Files under /_next/static/ carry a content hash in their name but were served without Cache-Control, so browsers fell back to heuristic freshness and revalidated each of the ~45 files of a page with a conditional request. Serve them with a one-year immutable lifetime. HTML pages, service-worker.js and public files keep a stable name: send Cache-Control: no-cache so the browser revalidates them and always gets the chunk list and service worker of the current release. The headers are repeated in every location, as nginx drops the inherited add_header directives as soon as a location defines its own. Closes #2770 Signed-off-by: Anthony LC --- CHANGELOG.md | 1 + src/frontend/apps/impress/conf/default.conf | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7460005f6..e6b5005e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -90,6 +90,7 @@ and this project adheres to - 🐛(documentation) fix minio port and keycloak realm in the k8s guide #2751 - 🐛(collaboration) bound the calls yhub makes to the backend with a timeout, `YHUB_BACKEND_REQUEST_TIMEOUT_MS`, 5s by default #2753 +- 🐛(frontend) cache hashed `/_next/static/` assets and revalidate HTML #2770 - 🐛(backend) compensate document duplication failures #2755 - 🐛(frontend) open search results in a new tab with ctrl/cmd+click #2719 - 🐛(docker) pull minio images from pgsty diff --git a/src/frontend/apps/impress/conf/default.conf b/src/frontend/apps/impress/conf/default.conf index 94be06860..43445f72b 100644 --- a/src/frontend/apps/impress/conf/default.conf +++ b/src/frontend/apps/impress/conf/default.conf @@ -5,21 +5,37 @@ server { root /app; + # Files under /_next/static/ have a content hash in their name: they never + # change, so browsers can keep them for good. + # `add_header` is not inherited when a location defines its own. + location /_next/static/ { + try_files $uri =404; + + add_header Cache-Control "public, max-age=31536000, immutable"; + add_header X-Frame-Options DENY always; + } + + # Everything else (HTML pages, service-worker.js, public files) has a stable + # name: the browser must revalidate it, so that it always gets the chunk list + # of the current release and the latest service worker. location / { try_files $uri index.html $uri/index.html =404; + add_header Cache-Control "no-cache"; add_header X-Frame-Options DENY always; } location ~ "^/docs/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/?$" { try_files $uri /docs/[id]/index.html; + add_header Cache-Control "no-cache"; add_header X-Frame-Options DENY always; } location ~ "^/user-reconciliations/(active|inactive)/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/?$" { try_files $uri /user-reconciliations/$1/[id]/index.html; + add_header Cache-Control "no-cache"; add_header X-Frame-Options DENY always; }