Revalidating cache on app assets; site title survives SPA navigation
Test / test (push) Successful in 24s

pkg files keep stable names across releases, so an uncontrolled
browser cache could pair last release's wasm with the new server's
server-fn wire format - every page then renders its error branch
(redoal.com's 'Nothing here' after v0.2.0). Cache-Control: no-cache
on /pkg and /yes.js makes clients revalidate (a 304 per load) instead
of guessing. The content-declared site title also moves out of the
question Suspense: remounting with each navigation lost the
leptos_meta race to the compile-time fallback, flipping redoal.com's
tab to 'uhhm' on the first client-side nav.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bendik Aagaard Lynghaug
2026-08-24 22:40:29 +02:00
co-authored by Claude Fable 5
parent c67f6f1a59
commit a0305282ef
3 changed files with 40 additions and 10 deletions
+27 -2
View File
@@ -143,7 +143,22 @@ async fn main() -> anyhow::Result<()> {
.route("/upload", post(upload::upload))
.route("/gitea-repo", get(content::gitea_repo_handler))
.route("/automation/kv/{bucket}", get(content::automation_kv_handler))
.nest_service("/pkg", ServeDir::new(pkg_dir))
// no-cache = "revalidate before reuse", not "don't cache":
// pkg files keep the same names across releases (portal.js,
// portal.wasm), and without this browsers heuristically cache
// them - a stale wasm from the previous release then talks to
// a server whose server-fn wire format has moved on and every
// page renders as its error branch. A 304 per load is the
// price of never shipping that skew again.
.nest_service(
"/pkg",
tower::ServiceBuilder::new()
.layer(tower_http::set_header::SetResponseHeaderLayer::overriding(
axum::http::header::CACHE_CONTROL,
axum::http::HeaderValue::from_static("no-cache"),
))
.service(ServeDir::new(pkg_dir)),
)
.nest_service("/fonts", ServeDir::new(fonts_dir))
.route_service("/favicon-light.svg", ServeFile::new(favicon_light_path))
.route_service("/favicon-dark.svg", ServeFile::new(favicon_dark_path))
@@ -152,7 +167,17 @@ async fn main() -> anyhow::Result<()> {
"/swiper-element-bundle.min.js",
ServeFile::new(swiper_path),
)
.route_service("/yes.js", ServeFile::new(yes_path))
// Same skew concern as /pkg: the wasm's raw_module import and
// the hero's inline script both load this by fixed name.
.route_service(
"/yes.js",
tower::ServiceBuilder::new()
.layer(tower_http::set_header::SetResponseHeaderLayer::overriding(
axum::http::header::CACHE_CONTROL,
axum::http::HeaderValue::from_static("no-cache"),
))
.service(ServeFile::new(yes_path)),
)
.leptos_routes_with_context(
&state,
routes,