Service Workers and Server-Side Redirects
TLDR
Do not include any dynamic, user-specific, or redirecting URLs in the STATIC_ASSETS of your service worker. Also, make sure to never serve or cache redirected URLs from the service worker.
The app
I am building a Ruby on Rails recipe tracker web app. For the frontend uses the usual Rails stack (ERB templates, Hotwire, etc.) but I have added a service worker for caching on the client side. It pre-caches all URLs in a list called STATIC_ASSETS, and intercepts GET requests for responding with a cached page (if one exists).
The change resulting in the bug
I added a redirect in my Rails app, which redirects / to /recipes by changing the routes. When visiting /, this resulted in errors like this: Response served by service worker has redirections in both Safari and Chrome.
Debugging
So the first mistake I had to fix, was that I was pre-caching /in the STATIC_ASSETS of my service worker. After the route change, / then always returned a 301 status code (mdn: 301 Moved Permanently).
But apparently service workers are not allowed to handle navigation requests with redirect responses.
So the fix was to
- Remove the URL from
STATIC_ASSETS - Skip the handling of
/in the service worker’sfetchhandler
// let the browser handlle the request normally
if (url.pathname === "/") return
Another error
After this, I did some more testing and noticed that when logging in:
- I open a fresh, private tab and go to
/ - This redirects me to
/session/new, where I log in - After logging in,
/recipesopens and everything seems fine - But if I now manually visit
/, the same error happens as before.
Once again the reason was that I also had /recipes in STATIC_ASSETS.
Ensuring redirects are never cached or served
To make sure that I will never cache or return redirected pages from the service worker, I have added a check like !response.redirected at all the locations where i am either (i) saving to cache, or (ii) returning responses from the cache.