Last active
          October 28, 2025 04:26 
        
      - 
            
      
        
      
    Star
      
          
          (1,162)
      
  
You must be signed in to star a gist 
- 
              
      
        
      
    Fork
      
          
          (63)
      
  
You must be signed in to fork a gist 
- 
      
- 
        Save Rich-Harris/fd6c3c73e6e707e312d7c5d7d0f3b2f9 to your computer and use it in GitHub Desktop. 
Revisions
- 
        Rich-Harris revised this gist Jun 15, 2019 . 1 changed file with 5 additions and 3 deletions.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -5,16 +5,18 @@ I recently had several days of [extremely frustrating experiences](https://twitt I'll add to this list over time – suggested additions welcome in the comments or via [twitter.com/rich_harris](https://twitter.com/rich_harris). ### ~~Use Canary for development instead of Chrome stable~~ ~~Chrome 51 has some pretty wild behaviour related to `console.log` in service workers. Canary doesn't, and it has a load of really good service worker related stuff in devtools.~~ *^ no longer necessary* ### Reloading the page doesn't behave as you'd expect If you make a change to your service worker, then reloading the page won't kill the old one and activate the new one (it detects the change by requesting the service worker file each time and comparing the old and the new byte-for-byte), leaving you somewhat confused as to why your changes haven't taken effect. This is because the old window is never actually closed, meaning there's never a time to swap them out – you need to kill the tab completely then reopen it. Or you can have the browser do that for you by going to the Application tab in devtools ~~(in Canary, not stable Chrome yet)~~, going to the Service Workers section, and checking 'Update on reload'. ### The new service worker isn't fetched by the old one 
- 
        Rich-Harris revised this gist Jul 21, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -51,7 +51,7 @@ document.querySelector( '.fetch-content' ).addEventListener( 'click', () => { ### You're not alone A lot of people have experienced the same frustrations you have and know how to fix them. In particular, [Jake](https://twitter.com/jaffathecake) and other folks at Google and Mozilla involved in implementing this stuff are unreasonably helpful if you reach out to them (not that I encourage you to spam their mentions every time you get stuck, but if you *really* need help...). I still think the API is a bit lumbering in several places (if the JS convention for the naming relationship between instances and classes is `foo = new Foo()`, why is `navigator.serviceWorker` an instance of `ServiceWorkerContainer` while `navigator.serviceWorker.controller` is an instance of `ServiceWorker`? And what the hell is a `ServiceWorkerRegistration`? Never mind all the [many other interfaces](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API#Interfaces) we now need to learn), and I'm worried about how learnable this stuff is by people who don't have the time and inclination to study hard, but at the very least knowing the stuff above has made my experience with service workers much nicer. 
- 
        Rich-Harris revised this gist Jul 21, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -35,7 +35,7 @@ The first time you load a page, `navigator.serviceWorker.controller === null`. T If you're using service workers you're probably caching the resources that make up your app shell. Perhaps, like me, you want to give the user to separately download *content*, e.g. fetch large files while they're on WiFi so they don't chew through their data plan. If so, you probably want some kind of progress notification. My first instinct was to have the service worker do all the background caching (and checking of which files are already cached, importantly) and broadcast messages to connected clients. That sucks because service worker messaging sucks. But it turns out it's not necessary, because you can do it directly in the client: ```js document.querySelector( '.fetch-content' ).addEventListener( 'click', () => { 
- 
        Rich-Harris revised this gist Jul 21, 2016 . 1 changed file with 16 additions and 3 deletions.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,12 +12,19 @@ Chrome 51 has some pretty wild behaviour related to `console.log` in service wor ### Reloading the page doesn't behave as you'd expect If you make a change to your service worker, then reloading the page won't kill the old one and activate the new one (it detects the change by requesting the service worker file each time and comparing the old and the new byte-for-byte), leaving you somewhat confused as to why your changes haven't taken effect. This is because the old window is never actually closed, meaning there's never a time to swap them out – you need to kill the tab completely then reopen it. Or you can have the browser do that for you by going to the Application tab in devtools (in Canary, not stable Chrome yet), going to the Service Workers section, and checking 'Update on reload'. ### The new service worker isn't fetched by the old one For a while I thought that maybe the reason my changes weren't taking effect was because the old service worker was serving a cached version of itself, because it was intercepting all requests and caching them. So I was doing all sorts of daft stuff like registering `service-worker.js?${Math.random()}` in an attempt to 'fix' it. Turns out that when you call `navigator.serviceWorker.register('service-worker.js)` the request for `service-worker.js` *isn't* intercepted by any service worker's `fetch` event handler. ### `navigator.serviceWorker.controller` is the service worker that intercepts `fetch` requests The first time you load a page, `navigator.serviceWorker.controller === null`. This continues to be true after a service worker has been successfully registered and installed. @@ -46,4 +53,10 @@ document.querySelector( '.fetch-content' ).addEventListener( 'click', () => { Turns out a lot of people have experienced the same frustrations you have and know how to fix them. In particular, [Jake](https://twitter.com/jaffathecake) and other folks at Google and Mozilla involved in implementing this stuff are unreasonably helpful if you reach out to them (not that I encourage you to spam their mentions every time you get stuck, but if you *really* need help...). I still think the API is a bit lumbering in several places (if the JS convention for the naming relationship between instances and classes is `foo = new Foo()`, why is `navigator.serviceWorker` an instance of `ServiceWorkerContainer` while `navigator.serviceWorker.controller` is an instance of `ServiceWorker`? And what the hell is a `ServiceWorkerRegistration`? Never mind all the [many other interfaces](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API#Interfaces) we now need to learn), and I'm worried about how learnable this stuff is by people who don't have the time and inclination to study hard, but at the very least knowing the stuff above has made my experience with service workers much nicer. ### Stuff I still don't understand * If I have code in my service worker that runs outside an event handler, when does it run? * Probably some other things I've forgotten for now 
- 
        Rich-Harris revised this gist Jul 21, 2016 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ # Stuff I wish I'd known sooner about service workers I recently had several days of [extremely frustrating experiences](https://twitter.com/Rich_Harris/status/755794434403467265) with service workers. Here are a few things I've since learned which would have made my life much easier but which isn't particularly obvious from most of the blog posts and videos I've seen. I'll add to this list over time – suggested additions welcome in the comments or via [twitter.com/rich_harris](https://twitter.com/rich_harris). 
- 
        Rich-Harris created this gist Jul 21, 2016 .There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,47 @@ I recently had several days of [extremely frustrating experiences](https://twitter.com/Rich_Harris/status/755794434403467265) with service workers. Here are a few things I've since learned which would have made my life much easier but which isn't particularly obvious from most of the blog posts and videos I've seen. I'll add to this list over time – suggested additions welcome in the comments or via [twitter.com/rich_harris](https://twitter.com/rich_harris). ### Use Canary for development instead of Chrome stable Chrome 51 has some pretty wild behaviour related to `console.log` in service workers. Canary doesn't, and it has a load of really good service worker related stuff in devtools. ### Reloading the page doesn't behave as you'd expect If you make a change to your service worker, then reloading the page won't kill the old one and activate the new one, leaving you somewhat confused as to why your changes haven't taken effect. This is because the old window is never actually closed, meaning there's never a time to swap them out – you need to kill the tab completely then reopen it. Or you can have the browser do that for you by going to the Application tab in devtools (in Canary, not stable Chrome yet), going to the Service Workers section, and checking 'Update on reload'. ### `navigator.serviceWorker.controller` is the worker that intercepts `fetch` requests The first time you load a page, `navigator.serviceWorker.controller === null`. This continues to be true after a service worker has been successfully registered and installed. (The relationship between `navigator.serviceWorker.controller` and the service workers you can get via `navigator.serviceWorker.getRegistration()` continues to be slightly confusing to me – particularly when it comes to knowing which service worker you're supposed to send messages to if you need to send messages. And don't get me started on `self.skipWaiting()` and `self.clients.claim()`, which on the face of it seem like a recipe for chaos. Though I'm sure it's just a matter of understanding when to use them.) ### You can access `self.caches` in the browser as `window.caches` If you're using service workers you're probably caching the resources that make up your app shell. Perhaps, like me, you want to give the user to separately download *content*, e.g. fetch large files while they're on WiFi so they don't chew through their data plan. If so, you probably want some kind of progress notification. My first instinct was to have the service worker do all the background fetching and bradcast messages to connected clients. That sucks because service worker messaging sucks. But it turns out it's not necessary, because you can do it directly in the client: ```js document.querySelector( '.fetch-content' ).addEventListener( 'click', () => { window.caches.open( myCache ) .then( cache => cache.addAll( content ) ) .then( () => alert( 'content is now available offline' ) ) .catch( () => alert( 'oh noes! something went wrong' ) ); }); ``` (Obviously you'd probably want a more granular strategy that made it possible to report download progress, but you get the idea.) ### You're not alone Turns out a lot of people have experienced the same frustrations you have and know how to fix them. In particular, [Jake](https://twitter.com/jaffathecake) and other folks at Google and Mozilla involved in implementing this stuff are unreasonably helpful if you reach out to them (not that I encourage you to spam their mentions every time you get stuck, but if you *really* need help...). I still think the API is a bit lumbering in several places (if the JS convention for the naming relationship between instances and classes is `foo = new Foo()`, why is `navigator.serviceWorker` an instance of `ServiceWorkerContainer` while `navigator.serviceWorker.controller` is an instance of `ServiceWorker`? And what the hell is a `ServiceWorkerRegistration`? Never mind all the [many other interfaces](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API#Interfaces) we now need to learn), and I'm worried about how learnable this stuff is by people who don't have the time and inclination to study hard, but at the very least knowing the stuff above has made my experience with service workers much nicer.