Skip to content

fix(webapp): serve the service worker script with no-cache - #6401

Open
rebelchris wants to merge 1 commit into
mainfrom
fix/sw-no-cache
Open

fix(webapp): serve the service worker script with no-cache#6401
rebelchris wants to merge 1 commit into
mainfrom
fix/sw-no-cache

Conversation

@rebelchris

@rebelchris rebelchris commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

The problem

After #6400 deployed, production still showed the broken wide cards for logged-in users — while every logged-out check (and the preview deployment) looked fixed.

Cause: the webapp registers its Serwist service worker only for logged-in users (register={!!user} in _app.tsx), and the SW precaches the app shell. Clients only pick up a new deployment when they re-fetch /serwist/sw.js (it has skipWaiting: true, so a fresh script activates immediately) — but that fetch honors HTTP caching, and production served the script with cache-control: public, max-age=14400. Net effect: every deploy takes up to 4+ hours to reach logged-in users, our whole active audience.

The route (app/serwist/[path]/route.ts, a force-static handler from @serwist/turbopack) sets Content-Type and Service-Worker-Allowed but no Cache-Control, so it fell through to default static caching.

The fix

Serve the SW script with Cache-Control: no-cache, must-revalidate so every SW update check revalidates (ETag makes the common case a cheap 304):

  • Wrap the route handler's GET to set the header — it's stored in the prerender (sw.js.meta now records cache-control: no-cache, must-revalidate).
  • Mirror the rule in next.config.ts headers() for /serwist/:path* as a routing-layer backstop.

Testing

  • pnpm --filter webapp build passes; the prerendered /serwist/sw.js response metadata contains the new header.
  • Lint + strict typecheck guard pass.
  • Please verify on this PR's preview: curl -sI https://<preview>/serwist/sw.js | grep -i cache-control should show no-cache, must-revalidate.

Note: if Cloudflare in front of production has a "Browser Cache TTL" override or cache rule matching *.js, it may still rewrite this header — worth checking the zone config after merge.

🤖 Generated with Claude Code

Preview domain

https://fix-sw-no-cache.preview.app.daily.dev

/serwist/sw.js was served with a multi-hour browser TTL, so logged-in
clients (the only ones with the SW registered) kept running the
previous build's precache long after a deploy — fixes looked shipped
but production stayed broken for them until the TTL lapsed.

Browsers only pick up a new deployment once they re-fetch the SW
script, and that fetch honors HTTP caching. Override Cache-Control at
the route handler (stored in the prerender) and mirror it in
next.config headers so update checks revalidate every time.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
daily-webapp Ready Ready Preview Jul 31, 2026 11:12am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
storybook Ignored Ignored Jul 31, 2026 11:12am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant