Exploring Service Workers Creating a Service Worker
Transcript from the "Creating a Service Worker" Lesson
>> Kyle Simpson: All right, so let's actually take a look at a service worker, let's start to write a service worker. We need to understand a little bit more about that life cycle thing, because we're gonna store some variables in our service worker. But we need to understand, when does this service worker live?
[00:00:22] Well, as soon as we called register and it loaded up into the browser, it starts and runs this program. So it runs through it, but it may not have, it definitely has not, finished all of its installation, activation, all that other stuff. So it's gonna stay running for the entirety of the time your page is up.
[00:00:40] I don't know of any scenario where a browser kills the service worker while somebody's actually on the page. It keeps it alive while they're on the page. If they go away from the page, it still might be alive for up to 5 or 10, maybe 30 seconds at most.
[00:00:56] If it was doing something, it may stay alive for a little while. This is very opaque, the browsers don't let us control any of that. They manage the life cycle, but it's gonna stay alive for awhile. But it's entirely possible that somebody may have had your tab open and everything was alive.
[00:01:11] And then that went to a background tab, and they haven't had your page open for weeks, right, or days or even hours. It's entirely possible that the service worker may have been killed over a prolonged period of inactivity while the tab was in the background. The browser says, I don't need any of that.
[00:01:30] And so when the browser detects that your page has come back to life, it's now being used, if the service worker is not currently running, it's gonna restart it. Now what's important to understand here is, it restarts it, but it doesn't rerun it through the installation and activation phase.
[00:01:48] It just restarts the code that we write in the global scope of our service worker. That code runs at first installation, and it also runs at restart if the service worker has ever been killed. And we'll see actually in the developer tools how we can stop and start our service worker.
[00:02:07] But we need to be mindful of any stuff that we put into our service worker in our state of our global scope. It's not really very permanent, it's there the whole time the service worker is alive. But it's entirely possible our service worker dies and comes back to life, and then all that stuff gets reinitialized.
[00:02:24] So be careful what you do in the global scope, essentially.
>> Kyle Simpson: So one thing that we definitely want to store for now is, we wanna set up a version variable, and I'm gonna start it at version 1.
>> Kyle Simpson: Essentially, this is a constant, this isn't gonna change throughout the lifetime of this.
[00:02:49] So if you wanna make it a constant, that's fine, we're not gonna reassign this version variable. But from each time we make a major change to our application, to the logic, to any routing stuff that our service worker's doing, we wanna make sure the service worker gets updated.
[00:03:07] And a nice convenient way of making sure that the browser knows to update it is to just bump the version number. Okay, some people like to do that with a code comment instead of an actual variable. All you have to do is change one byte somewhere in the file, and it'll get seen as a new service worker.
[00:03:25] One reason why you might wanna use a version, which doesn't totally apply to what we're doing with this website, it applies a little bit more to applications. Is the idea of treating the entire set of resources as one atomic package. Meaning we don't want some updated HTML files but some old HTML files.
[00:03:47] That's generally how I think of things, even with a website. If I've made a change, I want everybody to see the entire change on every page. But sometimes you have so much stuff that it's okay that it's rolling out sort of progressively as somebody navigates along. The idea of having a version number that you bump is a little bit more like that app where you bump the version.
[00:04:10] And when we start messing around with caches in a little bit, it'll be like basically, blow away the old cache. And refresh the cache with all the new version of the stuff. So it's like everything is version 1, and then everything is version 2. If that doesn't work for you, if you have too many resources and you don't wanna do that update, you may not track your versions like this.
[00:04:29] You may not name your caches version specific. But even for a website, the way I think about it is, I want everything to be in sync. So I'm still gonna sort of approach it more like the app mindset. And I'm okay that somebody may end up then spending a little bit of extra bandwidth to reload my site anytime I've made a big code change.
[00:04:51] Certainly I wouldn't want them to have to reload everything just because I added a blog post. But if I've redone a bunch of code or a bunch of CSS or something, I want everything in sync. So that depends on how you see that, how you wanna update that stuff.
[00:05:09] You can do it incrementally or sort of all together, or somewhere in between. You have full control, you get to write whatever code works for you. Okay, so we're gonna approach it from that perspective. Each time we update the version, we're gonna re-prime the cache, instead of kinda incrementally getting the cache.
[00:05:30] Okay, so let's listen for some events, we wanna say self.addEventListener. And the first event that we wanna listen for is install.
>> Kyle Simpson: And then we'll listen for another event called,
>> Kyle Simpson: Activate.
>> Kyle Simpson: So obviously we're gonna need to define those functions. Before we do that, though, I am gonna define a place for my initialization that I want to run every time.
[00:06:27] And we'll talk in a little bit as we unfold the service worker, we'll talk about what kinds of things do we wanna initialize or not. But I'm in the old school C tradition, I'm gonna collect everything into a main function, that is the stuff that I want to have happen.
[00:06:41] And remember, this runs every time the service worker is started, even if it's already been installed. Any time you run an asynchronous function, make sure to remember to catch and log out any errors. Because any mistakes you make will be silent and you'll be pulling your hair out for hours and I've done that many, many times.
[00:07:03] Okay, so let's first define, we'll make this an async function. We don't need it to be async now, but we will later, so I'm just gonna go ahead and make it an async function. All we wanna do right now is say that my service worker. And to make things a little bit saner for us in our logging, I'm gonna drop in our version number.
[00:07:25] So that when we start updating versions, it's clear which version the console messages are coming from. We'll say has started, or maybe is starting.
>> Kyle Simpson: You can have your messages say whatever you want, I'm just giving you an idea. We're gonna watch this life cycle play out, okay?
[00:07:55] Then we're gonna want an async function called onInstall.
>> Kyle Simpson: And another one called onActivate.
>> Kyle Simpson: And essentially, I'm gonna do those same messages in all three of these. So that we can kind of see the life cycle play out.
>> Kyle Simpson: Since these are event handlers, they're both gonna receive an event object, which we're going to want to receive.
[00:08:42] For onInstall, we're not gonna be using that one right now. But in the installation phase, this is where I was talking a little bit earlier about the idea of, I've installed, but I'm in this waiting phase. That's the default, immediately after I've finished installing, and I've fired that install handler, I'm now in this waiting phase.
[00:09:01] And what we want in our particular use case is, we want our new service worker to take over right away. So it has a chance to load up all the new resources and get them in front of the user as quickly as possible. It still might be the case, if you were doing an app, this would be more true.
[00:09:18] It still might be the case that the user is physically seeing the old versions of all these files. Because this might be a new service worker and it's all the old content that's still showing. But that's when you then have the option to, for example, either wait until the next refresh or page load.
[00:09:39] Or you could proactively message to the user, hey, things have updated, if you wanna get the new stuff, click refresh. Or I guess if you really wanted to, you could just forcibly refresh it for them. So it depends on your scenario, what user experience works best for you.
[00:09:56] But to skip the waiting phase, you're gonna call self.skipWaiting.