 I'm Jeff Posnick from Google's developer relations team. So I'm happy to be here today talking about the tools that can help provide the foundation for your service worker, which is a key piece of any progressive web app. And we'll be covering both existing tools, as well as providing preview of the next generation of service worker libraries. So you might be asking yourself, why use tools to build your progressive web app? Many folks have seen canonical service worker code samples that turn up in articles and getting started guides out there. You could be tempting to just copy, paste, and then ship that code into production. Now, I don't want to sound too negative here. I'm personally responsible for writing a lot of those early service worker code samples. And they're very useful for learning the basics of the service worker API. So I don't want to say that they're not useful. But there are certain things that you need to worry about and pitfalls when using those code snippets in production. So for instance, here's a common code pattern for pre-caching a set of resources during your service worker's installation. URLs to be pre-cached here are stored in an array. And you need to increment your version variable whenever you decide that you need to change one of those resources if you want to trigger the service worker update. But in a production web app, if you are following modern best practices, you won't be loading in this list of friendly file names in your URLs array. You're much more likely to have a file name that has some sort of unique hash based on the contents of that file. So it's unique file names that need to be in your URLs array. And also, what about that brand new image that you added to your page, but forgot to include in your URLs array? And what about scenarios where you have an existing file like that index.html, but you make a change and you forget to update version? These are all some common pitfalls you might run into. And these pitfalls extend to the code that you use to clean up your pre-cached entries, which is something that normally happens inside the Activate Handler in a service worker. So you can see code snippet here used to delete old pre-cached content whenever a new service worker activates. But what if your service worker updated because of just a small change to a single file? Why throw away everything else that was previously pre-cached instead of reusing the entries that haven't changed? And finally, you may have seen samples like this of a fetch handler that performs runtime catching. And in this case, it's using a cache-first policy. Problem is, the code adds to the runtime cache, but never cleans up entries. So you may not realize it, but the CacheStorage API just ignores the cache expiration HTTP response headers. When you're dealing with the CacheStorage API, it's not going to look at the max age and things like that and automatically expire entries for you. So you can easily clog up every user's device with larger resources that were needed for one specific page maybe a month ago, but they're never going to be used again. So hopefully, I've opened your eyes to a few of the things you want to avoid. But on the flip side, let's talk about what you should implement whenever you're building a production-ready service worker. So first, your service worker should use an AssetManifest generated based on the actual files that you're deploying to your site, including whatever fingerprints might be in the file names and things like that. That manifest should determine which resources are used to pre-cache rather than a hard-go to list. And this means that you don't have to worry about leaving out crucial files that you added in late in your build process and forgot to update the service worker to pick up. Second, the AssetManifest should keep track of the hashes or fingerprints of each file for you and make sure that only files that have been changed are invalidated and downloaded again. So anything that hasn't changed should be kept around rather than being thrown away. And this means you never have to worry about remembering to bump that version variable each time you change a file. And it also means that your ActivateHandler isn't going to throw away content that's still valid and useful. Finally, you need at least recently used expiration policy for your runtime caches. You might use maximum number of entries or you might want to have a maximum age for the entries or you might want to have a mix of both. And this prevents your caches from growing indefinitely and ensures that frequently used content is kept around while assets that were only used in the past will be cleaned up. All right. So how can you make sure that all the production ready checklist items are taken care of? Hopefully everybody wants to go and build something right now. And not surprisingly, the answer is tooling. So despite that tongue-in-cheek text on the slide, I'm actually a big fan of using the right tools for a given job. And there are a few tools available today that we could specifically recommend for building a production ready service worker. So first is SW Precache. It's a build time tool that generates your service worker file for you. So the generated file contains an asset manifest and install, activate, and fetch handlers that follow the best practices we've been talking about all along. There's also SW Toolbox. And this is a runtime library that extends the behavior of an existing service worker and specifically focuses on runtime caching strategies. So it implements a number of common strategies that you could use right out of the box without having to write your own code or more likely go to Jake's offline cookbook and copy and paste that code. And we've done that for you. So even if you don't realize that what you see in this diagram is a still while revalidate strategy, you can make use of it right away. And SW Toolbox also takes care of cache expiration for anything that's added to these runtime caches. So SW Precache and SW Toolbox complement each other. And they can be used together to handle both the precaching and the runtime caching for your progressive web app. So in fact, we've got a few projects that are pre-configured to use both the libraries out of the box. First of all, we have Web Starter Kit. And it provides boilerplate for common web development scenarios. SW Precache and SW Toolbox are baked right in to the build process that it uses, making your new web app offline first by default. West Web Polymer Starter Kit, and it's another great jumping off point for developers who want to build their progressive web app with web components. And the service worker libraries are included here as well. So they ensure that the assets needed to render routes are loaded quickly and that everything works offline. But we know that not everybody is going to be beginning from scratch with a Starter Kit though. Many developers for the existing projects are using a webpack-based build process. And SW Precache works for them too. So a member of the community, Will Farley, shout out to Will, is kind enough to maintain the SW Precache webpack plugin. And we appreciate his hard work there. So in fact, Lyft talked a little bit about their new PWA. This is what they're using under the hood to generate their service worker. And we know there's folks out there who like doing everything using command line tools, either manually or wrapping them in NPM scripts to kick off a build process. So we've got you covered as well. SW Precache just has a command line interface that we use to hook into these build processes. And you can trigger it as part of your normal build setup. So I barely scratched the surface of what SW Precache and SW Toolbox could do or how to configure them. But I'd encourage folks to visit our new service worker libraries landing page to learn more. And we have a ton of examples there and links to some previous videos that we've done and articles that you can read talking about best practices. And we've talked about these libraries a lot, rather than just taking my word about the value. I wanted to dive into real world deployment that you might have heard of, the Washington Post Progressive Web App. So let's see how they're using SW Precache and SW Toolbox. We're looking at a very lightly edited version of their entire SW Precache configuration. So passing this configuration in during their build process is all it takes to generate the service worker file that they have deployed to actual production use. And let's dig into some of those specific settings to see how they're making use of them. First, they're using this option, static file globs, to define a list of patterns that match files in their build directory. And this is that alternative to hard coding a list of URLs. Anything that matches this pattern is automatically pre-cached. And the cache entries are automatically versioned and kept up to date by the service worker that's generated. Next comes their runtime caching configuration. This is actually a way of using both SW Precache and SW Toolbox together very easily. And it tells SW Precache to automatically include SW Toolbox in the generated service worker file and to configure it based on the provided settings. So in this case, they define a URL pattern matching things that are going against their content API. And they apply a network-first strategy to those requests. They're also able to define that cache expiration that we talked about, which means that entries from a given period that I've not used anymore will be expired from the cache without just building up over time. And they're also pulling in some additional code that we haven't mentioned yet. And that's a library that automatically queues and retries Google Analytics hits that take place while their user is using the site offline. So they're using SW offline Google Analytics, which sets up fetch handlers that automatically queue any failed Google Analytics requests using index dv. And the failed requests are retried for up to a day, which is kind of an interval that makes sense for Google Analytics. And they're retried whenever the service worker starts up. So the library preserves the original event time automatically for you, meaning that assuming the request is able to make it to Google Analytics because the vice comes back online, the data has the correct timestamp attributed to it. So everything works as you would expect and you don't lose the nuance about when an event actually happened just because the site was offline. All right, so you've seen a real world example of using the libraries to generate a service worker file. But how do you confirm that your progressive web app is using the service worker effectively? So if you've been listening to any of the previous talks, this is probably not a surprise. We've got a tool for that called Lighthouse. And Lighthouse automatically tests for many of the things progressive web app should do, including whether the service worker is behaving as expected. So this screenshot shows a Lighthouse Chrome extension interface run against the Washington Post Progressive web app. You can see confirmation in the highlighted section that their PWA has a registered service worker and that it serves content even when the network is disabled. And Lighthouse will also generate useful performance metrics allowing you to judge other stats that are very relevant to any progressive web app. So Lighthouse is a very useful tool. I'm gonna hammer home a point that we've been making again and again. It's something to supplement testing on actual devices. So please don't use it just exclusively but also confirm behavior of your service worker on real world devices on real world networks. But while I've been talking about the Washington Post up to now, they're not alone when it comes to production SW Precache and SW Toolbox deployments. So here's just a subset of partners that are using these libraries to power their service worker in production. And you can feel confident knowing that these libraries are ready to use and battle tested. But the flip side of being tried and true is that the libraries were originally written back in 2014. So I'm sure there's some formula equivalent to dog years but for JavaScript libraries. I'm sure that by whatever metric these libraries kind of are in the distinguished elder statement, elder statesman phase. It's getting on a little bit. But I wanna reinforce that they're not deprecated. We're not deprecating everything. Everything is still supported. And if you're already using them or starting a new project today, they really do remain the right choice. But best practices are always changing. And we recently started thinking about what a modern service worker framework would look like. We're still very early on, but we wanted to give everyone a sneak preview of what we're thinking about. All right, so just wanna outline a few of our high level goals for this project. Developers who wanna use just a small bit of functionality like cache expiration should be able to import just the code that they want by bundling in ES 2015 modules with very little overhead. At the same time, developers who opt in to using all the functionality should feel like they're using a single coherent framework. Kind of wanted to get rid of that weird divide between SWP pre-cache and SWP toolbox where they feel like they're two separate projects. And most importantly, we have a strong set of features that we know developers need in production. And we wanna have parity with those features with our new offering. We don't want this to feel like a regression in any way. All right, so let's dive in a little bit about what we're thinking. Conceptually, we split the new framework into three layers, routing, runtime handlers, and request behaviors. So here's an overview of each of those. So first up is a routing layer, which is responsible for setting up fetch handlers that respond to specific types of requests. So we're envisioning built-in classes to handle like regular expression and express style routes similar to how SWP toolbox is currently configured for runtime caching. The router class also lays the groundwork for more complex routing in the future. And we're excited to see what we can build on top of that. But going down one layer from routing is our runtime handler layer. And this is a set of classes that implement common runtime caching strategies like stale while we're validated or network first. And by default, they won't modify the out-going requests and they'll just use an appropriate cache based on the service worker's registration scope. But we wanted to provide a flexible way of opting into different behaviors to customize those defaults in a way that makes sense for your application. And that's where we get to the request behaviors layer. So this is the innermost layer and it allows you to configure the runtime handlers and take specific actions in response to one or more custom callbacks that the runtime handlers know how to trigger. So to start with, we're thinking about three custom callbacks and those are request will fetch, fetch did fail and cached it update. So here's a quick look at how those callbacks fit into the request lifecycle. Prior to contacting the network, a runtime handler will trigger any registered request will fetch callbacks. And this allows the service worker to modify the request before it's made. So if that network request happens to fail, any fetch did callback handlers get triggered. And finally, if the handler was successful, you have a new response from the network and the cache gets updated. This is our opportunity to call any cached it update callbacks. So let's take a look at some of the behaviors we're planning to implement on top of this system of callbacks and triggers. So first we're exploring responsive image behavior that would be triggered during the request will fetch callback. And it could take current devices' capabilities into account and modify the outgoing image request URL accordingly and do some pretty smart things in terms of what it actually loads in terms of the URL. We're also thinking about a background sync queue and the idea is that this would be triggered by fetch did fail whenever there's a network request that fails. And this would be a more general version of what we have implemented when I talked about it a little bit earlier for Google Analytics. And it would just allow you to opt in to the same sort of behavior for your own types of requests. And additionally, it would probably make sense to use that new sync event that gets fired in the service worker for doing smart retries of those requests. So I'd also like to take the cache expiration logic that was currently deeply embedded in SW Toolbox and make it available via a reusable behavior. And this would be triggered by the cache did update. If something gets written to the cache, you'd be able to talk about how the cache would be modified and cleaning up old entries and things like that. And we also have plans for another behavior triggered by cache did update. And this one would use the new broadcast channel API, which is super cool. And it would let pages know when a previously cached resource has been updated. The client page could then take appropriate action like prompting users to reload the article that they're reading and see the latest updates based on the new cache entry. All right, so what does it look like when all of these pieces are used together as part of a new framework? Let's walk through the code sample. So first thing we're doing is setting up a request wrapper to configure our caching and also to configure the type of callbacks that are triggered. And in this particular case, we're using the broadcast cache update behavior. Next, we're configuring a routes to automatically apply a handler whenever a condition is met. So here we're just checking to see if the URL ends in JSON. And if there's a match, we'll apply the still while revalidate handler using the wrapper that we just configured for that cache behavior. So finally, we take our route and we use it to configure a new router. And this also lets us set up a default handler to use for other requests that aren't explicitly matched by a route. So you can see here the entirety of the code snippet and how everything hopefully fits together as a cohesive framework. But we know that not everybody wants to opt into using a full framework and we don't want to leave those developers behind. So here's an example of how you could write your own service worker code to manage caches, but just pulling the broadcast cache update behavior and manually use it independent of that automatic trigger cache update. So if you wanna mix it into your existing code, that should work too. We'd also like the request handlers to work in a standalone environment, allowing you to write your own fetch event handler while still taking advantage of a canonical implementation of a given strategy. And you can see that here. So we're still at the very early stages of implementing these new libraries. There are use cases we plan on addressing but don't have as much to share about it yet. And that includes like generating a manifest and doing a lot of things that you currently use SWE pre-cache for. And it also includes build time tooling and ways of automatically integrating into the builds that you have today. So we are definitely thinking about those. We just don't have as much to share quite yet. That being said, you know, if you're the adventurous type and you really wanna dip your toes into the water of these new libraries, we do have some very, very clearly alpha quality releases up on NBM right now. Expecting interfaces to change leading up to the official release. We're really just releasing this out there as a way of getting feedback from folks and getting the community to a chance to play around with these in a non-production environment and let us know what the developer ergonomics feels like. And, you know, we want feedback. So please reach out to us. We have this kind of big GitHub issue open that details some of what we're planning on doing. And let us know what you think and what areas you'd like to see us focus on or the areas that seem like they wouldn't work for you. And we're gonna definitely take that into account. So last but not least, there's a great new service worker push messaging library that was just released by my colleague, Matt Gauntz. And it provides a production ready approach to using Firebase Cloud Messaging, push notifications within your service worker. So we don't unfortunately have time to dive into that right now, but Matt will be at the service worker breakout session later today for folks here live and he'll be demonstrating a bit there. So thanks to everybody for the time, both in person and on video. And we hope that you'll take advantage of all these tools and build a production ready service worker for your progressive web app. So thank you.