Skip to content

Conversation

@rosa
Copy link
Member

@rosa rosa commented Jan 26, 2026

This removes the fetch event listener that was added to address stale content when launching/resuming the PWA. I think the fix was ineffective for two reasons:

  1. The service worker fetch handler only runs when an actual navigation occurs (cold start, manual refresh, link click). It does not run when a tab or PWA is resumed from memory, which is the primary scenario where users see stale content. When you switch back to a backgrounded tab, the page is already loaded in memory; no fetch happens.

  2. Even when a fetch does occur, the cache: 'no-cache' option is redundant. The server already responds with Cache-Control: max-age=0, private, must-revalidate headers, which tells browsers to always revalidate before using cached HTML. The service worker was duplicating what the server headers already ensure.

The actual stale content problem stems from WebSocket disconnection when tabs are backgrounded - Turbo Stream broadcasts are missed, and when the user returns, they see the in-memory page state from before. Solving this properly requires JavaScript that detects visibility changes and triggers a refresh after extended background time (similar to the existing frame_reloader_controller pattern).

This removes the fetch event listener that was added in c345484 to
address stale content when launching/resuming the PWA. The fix was
well-intentioned but ineffective for two reasons:

1. The service worker fetch handler only runs when an actual navigation
   occurs (cold start, manual refresh, link click). It does NOT run when
   a tab or PWA is resumed from memory - which is the primary scenario
   where users see stale content. When you switch back to a backgrounded
   tab, the page is already loaded in memory; no fetch happens.

2. Even when a fetch does occur, the `cache: 'no-cache'` option is
   redundant. The server already responds with
   `Cache-Control: max-age=0, private, must-revalidate` headers, which
   tells browsers to always revalidate before using cached HTML. The
   service worker was duplicating what the server headers already ensure.

The actual stale content problem stems from WebSocket disconnection when
tabs are backgrounded - Turbo Stream broadcasts are missed, and when the
user returns, they see the in-memory page state from before. Solving this
properly requires JavaScript that detects visibility changes and triggers
a refresh after extended background time (similar to the existing
frame_reloader_controller pattern).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@rosa
Copy link
Member Author

rosa commented Jan 26, 2026

Looking a bit more into this, it seems the behaviour this was attempting to fix was a very specific cold start of the Safari PWA. That means that 1 would apply, and a fetch request would happen and be intercepted by the service worker. But without the service worker, this should work just fine because we return the right Cache-Control headers 😕 I guess this might be Safari being Safari... again?

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.

2 participants