create-react-app: PWA / Service worker breaking production deployments
EDIT: Issue appears to be with Firebase only
Service workers aren’t refreshing index.html and therefore new deploys are showing old bundles.
This means production websites or really all deployed sites that use a single url/domain can not be updated.
PR #2441 - Is a hotfix (if needed) that just removes the service worker and updates docs to say they have been disabled temporarily.
@gaearon @timer @jeffposnick @addyosmani
Steps to reproduce
create-react-app sw-test
cd sw-test
npm install
npm run build
cd build
Deploy with firebase
firebase deploy
- Visit site https://[project].firebaseapp.com. Confirm working.
- Change app.js
npm run build
cd build
deploy firebase
Check website
- Visit site again and no changes shown. DevTools shows SW is providing index.html and old bundles.
- Force refresh a few times. No difference.
- Delete service worker.
- Refresh.
- See correctly updated site.
Can someone else confirm this is affecting them?
I am hoping I am doing something wrong and this isn’t affecting every production deploy.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 27
- Comments: 20 (13 by maintainers)
Commits related to this issue
- Don't cache service worker ref https://github.com/facebookincubator/create-react-app/issues/2440 — committed to Andersos/liste.mlsv.no by Andersos 7 years ago
- Don't cache service worker file https://github.com/facebook/create-react-app/issues/2440 This should resolve an issue where `index.html` is cached and pointing at an invalid JavaScript bundle. — committed to BlakeWilliams/osquery-site by BlakeWilliams 6 years ago
- prevent service worker from caching and therefore not updating site. According to: https://github.com/facebook/create-react-app/issues/2440#issuecomment-305592301 — committed to FlorinSenoner/cas_fee_02 by TheMen4ce 6 years ago
- Fix blank page SW deploy. See https://github.com/facebook/create-react-app/issues/2440 — committed to vonkanehoffen/fold-react-firebase by deleted user 6 years ago
For those who come across this issue, here is how you should be able to fix it for Firebase Hosting. Edit your
firebase.json
and add headers like so:What you’re running into with https://cra-sw.firebaseapp.com/ is described in item 5 of the “Offline-First Considerations”, and is due to
service-worker.js
being served with HTTP caching headers.It’s unfortunately a common pain point, since many hosting providers will default to a medium-length cache lifetime for assets like
.js
files. Updating your web app’s assets relies on detecting an updatingservice-worker.js
file, and that is complicated when the browser’s cache comes into play. (The cache headers are always ignored if the file is over 24 hours old; it there’s more historical detail here.)The service worker specification was changed to cause HTTP caching of
service-worker.js
to only happen when a developer explicitly opts-in, and Firefox has already implemented that change in FF53+.Chrome has unfortunately not caught up, and still honors the HTTP caching headers. I was just asking about the status of this internally yesterday, and I’ll point the relevant folks to these discussions, given the larger audience that is likely to inadvertently run into this.
Thanks @mbleigh, it works! There is a typo in your json though: firebase expects a
headers
array instead of aheader
object. Here is the adapted json:Yes,
service-worker.js
is modified with every deployment. It contains versioning information for all of the URLs it knows about—including URLs likeindex.html
that can’t be renamed to include inline hashes (no one will navigate toindex.<md5>.html
). Someone’s written up a very thorough explainer that goes into all the details if you’re curious.The best practice is to keep the service worker file name constant (i.e.
service-worker.js
,sw.js
or whatnot) instead of including a hash in the file name.Including a hash in the file name means that you couldn’t serve the file that contains the
navigator.serviceWorker.register('service-worker.<md5>.js')
statement using a cache-first strategy, since if you did serve it cache-first, you’d never pick up the new<md5>
value.Keeping the file name consistent, and relying on the service worker update flow to handle cache updates, means that you can serve all your static content cache-first. But it also means that if your
service-worker.js
is served with HTTP cache headers enabled, Chrome currently will respect those headers for up to 24 hours, leading to the frustration that you bumped up against in this issue.Just to prove I am not crazy and this is a thing on firebase.
Deploying changes with
serve
,now
,surge
andfirebase
. Approximately 3 minutes https://www.youtube.com/watch?v=oYy-WqkgS1QThanks, I updated my snippet to match yours. That’s what I get for assuming I remember all of my product’s config from the top of my head. 🤦♂️
cc’ing @davideast from Firebase as an FYI regarding the current cache-control max-age above. Jeff’s summary is quite accurate but it would be good to get a check-in on the medium-length lifetime for static assets. Checking back in on https://github.com/facebookincubator/create-react-app/pull/2441, it appears this is now only an issue for Firebase hosted content vs other hosts.
I’m going to chase trying to get some resource behind working on this internally.
Hi everyone, sorry for asking a similar question in a closed issue, thought it is related to it and the solution might be simple.
I am trying to set cache header for sw with nginx, in the configuration like it has been done in firebase, I tried
However when I load my page, sw registration fails with the message.
A bad HTTP response code (404) was received when fetching the script. registerServiceWorker.js:71 Error during service worker registration: TypeError: Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script.
@gaearon @Timer @jeffposnick @addyosmani @mbleigh
Can someone please help me with this?