<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Dave Geddes on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Dave Geddes</name>
  </author>
  <link href="https://web.dev/authors/geddski/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/admin/aU4CRVGbOgg8uSRuLAfh.jpg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Founder at Mastery Games</subtitle>
  
  
  <entry>
    <title>Service worker mindset</title>
    <link href="https://web.dev/service-worker-mindset/"/>
    <updated>2019-06-04T00:00:00Z</updated>
    <id>https://web.dev/service-worker-mindset/</id>
    <content type="html" mode="escaped">&lt;p&gt;Service workers are powerful and absolutely worth learning. They let you deliver an entirely new level of experience to your users. Your site can load &lt;em&gt;instantly&lt;/em&gt;. It can work &lt;em&gt;offline&lt;/em&gt;. It can be installed as a platform-specific app and feel every bit as polished—but with the reach and freedom of the web.&lt;/p&gt;
&lt;p&gt;But service workers are unlike anything most of us web devs are used to. They come with a steep learning curve and a handful of snags you&#39;ve got to watch out for.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/ChromiumDev&quot; rel=&quot;noopener&quot;&gt;Google Developers&lt;/a&gt; and I recently collaborated on a project—&lt;a href=&quot;https://serviceworkies.com/&quot; rel=&quot;noopener&quot;&gt;Service Workies&lt;/a&gt;—a free game for understanding service workers. While building it and working with the complex ins and outs of service workers, I ran into a few snags. What helped me the most was coming up with a handful of depictive metaphors. In this post we&#39;ll explore these mental models and wrap our brains around the paradoxical traits that make service workers both tricky and awesome.&lt;/p&gt;
&lt;h2 id=&quot;the-same,-but-different&quot;&gt;The same, but different &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#the-same,-but-different&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While coding your service worker, many things will feel familiar. You get to use your favorite new JavaScript language features. You listen to lifecycle events just like with UI events. You manage control flow with promises like you&#39;re used to.&lt;/p&gt;
&lt;p&gt;But other service worker behavior causes you to scratch your head in confusion. Especially when you refresh the page and don&#39;t see your code changes applied.&lt;/p&gt;
&lt;h3 id=&quot;a-new-layer&quot;&gt;A new layer &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#a-new-layer&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Normally when building a site you have just two layers to think about: the client and the server. The service worker is a brand new layer that sits in the middle.&lt;/p&gt;
&lt;img alt=&quot;A service worker acts as a middle layer between the client and the server&quot; decoding=&quot;async&quot; height=&quot;232&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/w6JgZDMJMoqp24IuC9UZ.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Think of your service worker as a sort of &lt;em&gt;browser extension&lt;/em&gt;—one that your site can install in your user&#39;s browser. Once installed, the service worker &lt;em&gt;extends&lt;/em&gt; the browser for your site with a powerful middle layer. This service worker layer can intercept and handle all of the requests your site makes.&lt;/p&gt;
&lt;p&gt;The service worker layer has its &lt;strong&gt;own lifecycle&lt;/strong&gt; independent of the browser tab. A simple page refresh isn&#39;t enough to update a service worker—just like you wouldn&#39;t expect a page refresh to update code deployed on a server. Each layer has its own unique rules for updating.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;https://serviceworkies.com/&quot; rel=&quot;noopener&quot;&gt;Service Workies&lt;/a&gt; game we cover the many details of the service worker lifecycle and give you a ton of practice working with it.&lt;/p&gt;
&lt;p&gt;&lt;video autoplay=&quot;&quot; controls=&quot;&quot; height=&quot;460&quot; loop=&quot;&quot; muted=&quot;&quot; width=&quot;800&quot; style=&quot;--vid-width: 800; --vid-height: 460&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/MhBc1XtdrEGOQn8iXtKZ.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Think of your service worker as a new middle layer with its own lifecycle and methods for updating. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;powerful,-but-limited&quot;&gt;Powerful, but limited &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#powerful,-but-limited&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Having a service worker on your site gives you incredible benefits. Your site can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;work flawlessly even when the user is offline&lt;/li&gt;
&lt;li&gt;gain massive performance improvements through &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Cache&quot; rel=&quot;noopener&quot;&gt;caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;use &lt;a href=&quot;https://web.dev/notifications/&quot;&gt;push notifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;be installed as a &lt;a href=&quot;https://web.dev/progressive-web-apps/&quot;&gt;PWA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With as much as service workers can do, they are limited by design. They can&#39;t do anything synchronous or in the same thread as your site. So that means no access to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;localStorage&lt;/li&gt;
&lt;li&gt;the DOM&lt;/li&gt;
&lt;li&gt;the window&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The good news is there are a handful of ways your page can communicate with its service worker, including direct &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Client/postMessage&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;postMessage&lt;/code&gt;&lt;/a&gt;, one-to-one &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/MessageChannel&quot; rel=&quot;noopener&quot;&gt;Message Channels&lt;/a&gt; and one-to-many &lt;a href=&quot;https://developer.chrome.com/blog/broadcastchannel&quot; rel=&quot;noopener&quot;&gt;Broadcast Channels&lt;/a&gt;.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Think of your service worker as something that lives outside of your page. You can talk to it, but it can&#39;t access your page directly. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;long-lived,-but-short-lived&quot;&gt;Long-lived, but short-lived &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#long-lived,-but-short-lived&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An active service worker goes on living even after a user leaves your site or closes the tab. The browser keeps this service worker around so that it will be ready the next time the user comes back to your site. Before the very first request is made, the service worker gets a chance to intercept it and take control of the page. This is what allows a site to work offline—the service worker can serve a cached version of the page itself, even if the user has no connection to the internet.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://serviceworkies.com/&quot; rel=&quot;noopener&quot;&gt;Service Workies&lt;/a&gt; we visualize this concept with Kolohe (a friendly service worker) intercepting and handling requests.&lt;/p&gt;
&lt;p&gt;&lt;video autoplay=&quot;&quot; controls=&quot;&quot; height=&quot;605&quot; loop=&quot;&quot; muted=&quot;&quot; width=&quot;800&quot; style=&quot;--vid-width: 800; --vid-height: 605&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/BeJWEOe4TPoMzdBTFVWI.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;&lt;/p&gt;
&lt;h3 id=&quot;stopped&quot;&gt;Stopped &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#stopped&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Despite service workers appearing to be immortal, they can be &lt;strong&gt;stopped&lt;/strong&gt; at almost any time. The browser doesn&#39;t want to waste resources on a service worker that isn&#39;t currently doing anything. Getting stopped isn&#39;t the same thing as getting &lt;em&gt;terminated&lt;/em&gt;—the service worker remains installed and activated. It&#39;s just put to sleep. The next time it&#39;s needed (e.g., to handle a request), the browser wakes it back up.&lt;/p&gt;
&lt;h3 id=&quot;waituntil&quot;&gt;waitUntil &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#waituntil&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Because of the constant possibility of getting put to sleep, your service worker needs a way to let the browser know when it&#39;s doing something important and doesn&#39;t feel like taking a nap. This is where &lt;code&gt;event.waitUntil()&lt;/code&gt; comes into play. This method extends the lifecycle it&#39;s used in, keeping it both from being stopped and from moving on to the next phase of its lifecycle until we&#39;re ready. This gives us time to setup caches, fetch resources from the network, etc.&lt;/p&gt;
&lt;p&gt;This example tells the browser that our service worker isn&#39;t done installing until the &lt;code&gt;assets&lt;/code&gt; cache has been created and populated with the picture of a sword:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;install&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;waitUntil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    caches&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;assets&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; cache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/weapons/sword/blade.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;watch-out-for-global-state&quot;&gt;Watch out for global state &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#watch-out-for-global-state&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When this start/stop happens the service worker&#39;s global scope is reset. So be careful not to use any global state in your service worker or you&#39;ll be sad the next time it wakes back up and has different state from what it was expecting.&lt;/p&gt;
&lt;p&gt;Consider this example that uses a global state:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; favoriteNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; hasHandledARequest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;fetch&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;favoriteNumber&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hasHandledARequest&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  hasHandledARequest &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;On each request this service worker will log a number—let&#39;s say &lt;code&gt;0.13981866382421893&lt;/code&gt;. The &lt;code&gt;hasHandledARequest&lt;/code&gt; variable also changes to &lt;code&gt;true&lt;/code&gt;. Now the service worker sits idle for a bit, so the browser stops it. The next time there&#39;s a request, the service worker is needed again, so the browser wakes it up. Its script is &lt;strong&gt;evaluated again&lt;/strong&gt;. Now &lt;code&gt;hasHandledARequest&lt;/code&gt; is reset to &lt;code&gt;false&lt;/code&gt;, and &lt;code&gt;favoriteNumber&lt;/code&gt; is something completely different—&lt;code&gt;0.5907281835659033&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can&#39;t rely on stored state in a service worker. Also, creating instances of things like Message Channels can cause bugs: you&#39;ll get a brand new instance every time the service worker stops/starts.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; This snag is especially important to keep in mind while working on your service worker code because when Chrome DevTools is open, the start/stop behavior is disabled. You may not even see bugs caused by relying on global state until they&#39;ve shipped to your users. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;In &lt;a href=&quot;https://gedd.ski/post/service-workies-chapter3/&quot; rel=&quot;noopener&quot;&gt;Service Workies chapter 3&lt;/a&gt; we visualize our stopped service worker as losing all color while it waits to be woken up.&lt;/p&gt;
&lt;img alt=&quot;visualization of a stopped service worker&quot; decoding=&quot;async&quot; height=&quot;313&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/QBmObxFoIRgNtjsUttkF.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Think of your service worker as a &lt;a href=&quot;https://www.akc.org/dog-breeds/whippet/&quot;&gt;whippet&lt;/a&gt; dog. It&#39;s fast, loyal and awesome. It&#39;ll stick around by your side no matter what. But mostly it just wants to sleep. All the time. You&#39;ve got to let it know when you want it to stay awake. Good dog! &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;together,-but-separate&quot;&gt;Together, but separate &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#together,-but-separate&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Your page can only be &lt;em&gt;controlled&lt;/em&gt; by one service worker at a time. But it can have two service workers &lt;em&gt;installed&lt;/em&gt; at once. When you make a change to your service worker code and refresh the page, you aren&#39;t actually editing your service worker at all. Service workers are &lt;em&gt;immutable&lt;/em&gt;. You&#39;re instead making a brand new one. This new service worker (let&#39;s call it SW2) will &lt;em&gt;install&lt;/em&gt; but it won&#39;t &lt;em&gt;activate&lt;/em&gt; yet. It has to &lt;em&gt;wait&lt;/em&gt; for the current service worker (SW1) to terminate (when your user leaves your site).&lt;/p&gt;
&lt;h3 id=&quot;messing-with-another-service-workers-caches&quot;&gt;Messing with another service worker&#39;s caches &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#messing-with-another-service-workers-caches&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While installing, SW2 can get things setup—usually creating and populating caches. But heads up: this new service worker has access to everything that the current service worker has access to. If you&#39;re not careful, your new waiting service worker can really mess things up for your current service worker. Some examples that could cause you trouble:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SW2 could delete a cache that SW1 is actively using.&lt;/li&gt;
&lt;li&gt;SW2 could edit the contents of a cache that SW1 is using, causing SW1 to respond with assets that the page isn&#39;t expecting.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;skip-skipwaiting&quot;&gt;Skip skipWaiting &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#skip-skipwaiting&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A service worker can also use the risky &lt;code&gt;skipWaiting()&lt;/code&gt; method to take control of the page as soon as it&#39;s done installing. This is generally a bad idea unless you&#39;re intentionally trying to replace a buggy service worker. The new service worker might be using updated resources that the current page isn&#39;t expecting, leading to errors and bugs.&lt;/p&gt;
&lt;h3 id=&quot;start-clean&quot;&gt;Start clean &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#start-clean&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The way to prevent your service workers from clobbering each other is to make sure they use different caches. The easiest way to accomplish that is to version the cache names they use.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; version &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; assetCacheName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;assets-&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;version&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;install&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  caches&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;assetCacheName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cache&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// confidently do stuff with your very own cache&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When you deploy a new service worker, you&#39;ll bump the &lt;code&gt;version&lt;/code&gt; so that it does what it needs with an entirely separate cache from the previous service worker.&lt;/p&gt;
&lt;img alt=&quot;visualization of a cache&quot; decoding=&quot;async&quot; height=&quot;435&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/7REuAR11sps94W4tO7ng.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;end-clean&quot;&gt;End clean &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#end-clean&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once your service worker reaches the &lt;code&gt;activated&lt;/code&gt; state, you know it has taken over, and the previous service worker is redundant. At this point it&#39;s important to clean up after the old service worker. Not only does it respect your users&#39; cache storage limits, but it can also prevent unintentional bugs.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/CacheStorage/match&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;caches.match()&lt;/code&gt;&lt;/a&gt; method is an often-used shortcut for retrieving an item from &lt;em&gt;any&lt;/em&gt; cache where there&#39;s a match. But it iterates through the caches in the order they were created. So let&#39;s say you&#39;ve got two versions of a script file &lt;code&gt;app.js&lt;/code&gt; in two different caches—&lt;code&gt;assets-1&lt;/code&gt; and &lt;code&gt;assets-2&lt;/code&gt;. Your page is expecting the newer script that&#39;s stored in &lt;code&gt;assets-2&lt;/code&gt;. But if you haven&#39;t deleted the old cache, &lt;code&gt;caches.match(&#39;app.js&#39;)&lt;/code&gt; is going to return the old one from &lt;code&gt;assets-1&lt;/code&gt; and most likely break your site.&lt;/p&gt;
&lt;p&gt;All it takes to clean up after previous service workers is to delete any cache that the new service worker doesn&#39;t need:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; version &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; assetCacheName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;assets-&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;version&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;activate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;waitUntil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    caches&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cacheNames&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;        cacheNames&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cacheName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cacheName &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; assetCacheName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; caches&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cacheName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Preventing your service workers from clobbering each other takes a bit of work and discipline but is worth the trouble.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Think of the combination of your service worker and your site as an &lt;a href=&quot;https://web.dev/installable&quot;&gt;installable&lt;/a&gt; app. Each version should work. Each version should be separate from the others. Imagine how buggy a game would be if the developer accidentally released a patch that used new game logic but outdated assets. You&#39;d rage on the forums so fast! Keep your app versions tidy &amp;amp; clean. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;service-worker-mindset&quot;&gt;Service worker mindset &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/service-worker-mindset/#service-worker-mindset&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Getting into the right mindset while thinking about service workers will help you build yours with confidence. Once you get the hang of them you&#39;ll be able to create incredible experiences for your users.&lt;/p&gt;
&lt;p&gt;If you want to understand all this by &lt;a href=&quot;https://gedd.ski/post/mastery-through-play/&quot; rel=&quot;noopener&quot;&gt;playing a game&lt;/a&gt;, then you&#39;re in luck! Go play &lt;a href=&quot;https://serviceworkies.com/&quot; rel=&quot;noopener&quot;&gt;Service Workies&lt;/a&gt; where you&#39;ll learn the ways of the service worker in order to slay the offline beasts.&lt;/p&gt;
&lt;p&gt;&lt;video autoplay=&quot;&quot; controls=&quot;&quot; height=&quot;519&quot; loop=&quot;&quot; muted=&quot;&quot; width=&quot;800&quot; style=&quot;--vid-width: 800; --vid-height: 519&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/cGQxYFGJrUUaUZyWhyt9yo5gHhs1/ammLWAa5Kc13D5CgstvK.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;&lt;/p&gt;
</content>
    <author>
      <name>Dave Geddes</name>
    </author>
  </entry>
</feed>
