 All righty, okay, again, my name is Brett Little. I am a software developer at a place called Beanstalk. It's a little startup. It's a great company. Come talk to me afterwards. If you are interested, we are hiring and I'd love to tell you more about it. Again, my Twitter handle, little Brett. Brett Little, yeah, never heard jokes about that when I was young. To start off though, I wanna focus a little bit about something I said in my abstract. I think there are a lot of reasons why native apps are chosen over a web application. But I think a core reason why a lot of times you would choose to build a native application is because the web really is kind of abysmal and providing a decent offline experience. It just really totally sucks in offering anything that's decent. You may ask yourself, what about AppCache? AppCache has been around since marketing people have been talking about HTML5. Who here has used AppCache? Anybody? Okay, five-ish people. Who still is using AppCache on an actual app? Okay, maybe like half of that, so like three or four people. So AppCache is just that. If you go check out this article, it's a pretty exhaustive list on why AppCache sucks. And I don't really wanna go into the details really about AppCache, but it's really a pain to use. And we have something better. We have something better with JavaScript 2015, as it's now called, called service workers. Who here has even heard of a service worker? Knows what these are a little bit? Okay, some people know what this is. It's talking to a co-worker of mine about service workers and his initial idea, I don't know, a service worker. Something like a web worker. Not that, give you a hint. So a service worker is an independent but a shared execution thread for all pages on your domain. That's really important. So it's independent, an independent execution thread. But all pages on your domain, so if you have multiple tabs, multiple windows, all of those windows or tabs will share this external execution thread. Kind of like a shared worker. Some specifics about it. Like a web worker, like a shared worker, a service worker cannot access the DOM. It's totally independent, it's isolated, it cannot touch the DOM, which is a good thing. To communicate with this worker thread, you do so with events. And all events that you send to this thread, all data that go through those events is essentially serialized and copied. So any data that is in your main application and any data that's in the service worker thread is copied, you can't have shared data. Which is a good thing as well, so you don't run into concurrency problems by sharing data. The last thing on here is service workers require SSL. They have to be hosted on HTTPS domain. May ask you, so why do I have to host this on HTTPS? And the reason is, because you can do some really awesome things with service workers. Specifically, you can intercept and you can hijack any request from the main primary thread inside your service worker thread. So if I had this bit of code inside a service worker, every HTTP request would get funneled through the service worker and would get a response of hello world. Whether it's an image request, whether it's a CSS request, load style sheets, HTML, JavaScript, everything. I am successfully hijacking and providing my own response for. You can rewrite headers, you can rewrite response bodies, you can do whatever you want really, which is like ultimate power and which is why you have to do that over HTTPS, some level of security over this. Also, the service worker API includes a caching API. A caching API for you to actually cache resources inside a new caching mechanism that is not index DB, it's not local storage, this is a new API altogether, where I can cast these blobs of data inside of it, which is really cool. And you'll notice here, there's a dot then method. So this is promises, but this isn't like some sort of promise library. This is native promises inside the browser, APIs that are returning promises, which is really cool. These new APIs were actually using some of this JavaScript 2015 stuff. We've already heard a lot about promises, this is just a little bit of an example of promise, a promise, how it works. So we're talking about promises, we're talking about JavaScript 2015. Is this stuff ready? Can you use this stuff right now? Like these examples I'm gonna show you, these links I'm gonna give you, you can load up in your browser and if you're on Chrome version 40, which is the current stable version of Chrome, you can be running on service workers right now. Inside Firefox, it works, but it's disabled by default. You have to go find a flag and turn it on. Opera, it also works. Internet Explorer, they're considering it. There's a big little list of commentary on it, whereas Safari, there is no comment at all. So I guess that's the Apple way. I don't know, maybe it will be supported, who knows? So I wanna talk a little bit about the life cycle of service workers. So we have our main thread right here and then we have the worker thread. Inside our main thread, we will register a new service worker. When you're registering a new service worker, you'll pass in the path to the actual service worker JavaScript file that will be executed. So once it's registered, we're now in this worker thread land where there's a series of events or things that may happen. The first thing that there's an event that's fired that's called the install event. When the service worker is successfully installed, it's been booted up. It's successfully, you're on an HTTPS domain. There are no errors. You have a valid certificate. If you have an invalid SSL certificate, it will throw an error. It will not allow the service worker to be installed. But assuming that it does successfully install, then it moves on to this activate state. And this is kind of confusing why there's this install state and there's this activate state. When you first load your page and you're installing this service worker, you will have the install event, but the service worker will not immediately be in control of the main thread. As I keep talking, I'm gonna use that terminology in control. When the service worker is in control of the main thread, then we are successfully hijacking all HTTP requests. We are actually in control of that page. And the activate event will only fire when you are actually in control over all pages currently loaded on your machine. Like it could be multiple tabs, multiple windows. Again, that install event will only fire once we are controlling all of those pages. And then we proceed to this idle state. Once you're idle, it's really doing nothing. Like it can listen to events from the main thread to do some sort of work, or it can listen for actual HTTP requests. When it gets an HTTP request of some sort, we can do whatever we want. We can send whatever we want back to the main thread. Another key thing though is this terminated state. The browser will automatically shut down and restart this thread at will on its own. That could happen in a number of ways. You could have the service worker booted up and it could be running. Then you could switch over to a new tab on a new different site. And then five seconds later, it's gonna shut down this thread in the background automatically. Then when you switch back to the tab, it'll automatically start it up again. And the important thing about that is that any state that exists inside that service worker, you need to persist that somehow. Again, because it may shut down or boot up without you really being able to control when or how that happens, which is really important. But overall, this is the life cycle of a service worker. So I wanna show you a couple examples. So this is the code that would exist inside your main index HTML page with some sort of app.js inside here. So this is inside the main thread itself, where we are registering a service worker. Register it to a particular path of a JavaScript file. If it succeeds, we'll find out. If it fails, we'll find out and print out the error message. The error messages are not always that helpful. Sometimes your service worker will just not boot up. It will not install and you have no idea why. And it's kind of hard to debug by default. So when I say it's hard to debug, if you have some sort of syntax error or you do something just that throws an error when your service worker boots up, it'll just totally die. And you'll get an error message right here that doesn't tell you anything about how or why it died. So a little bit later on, I'm gonna show you how you can debug those sorts of issues. So again, you'll recall from back here, so there's the registering of the service worker, installing it, and then activating it. So installing the service worker, so this code exists inside the actual service worker file where we are listening for the actual install event. When the install event fires, generally what you'll do here, like you can do whatever you want, this is just JavaScript, but commonly what's done is where you'll actually prefetch resources. So you can prefetch images, JavaScript, HTML, whatever you want and toss it in the cache. So these are sorts of files that you always know that you'll probably want in your application or even maybe some sort of offline pages that we can display to the user if they ever lose a connection. That's all styled nicely with CSS and HTML or whatever you want. And then again, here's the activate event. This is post install once the service worker has successfully taken control over all pages in your browser. And this is used for cache management usually. And this is kind of confusing because usually you can only ever have one service worker running at one time for your domain. But you can kind of get into a weird state where you can have two running at one time. If you can imagine I install a service worker, I cache a ton of stuff, I have it running. But now I wanna update that service worker. I wanna update it to cache new data or I have new logic inside of it. When the application loads, when you register your service worker with this slash SW.js, the browser will actually do a bit comparison of SW.js and see if it's changed. If it's changed, it will immediately install a brand new service worker which will exist at the same time as the old service worker. But the new one will not have its activate event ever fire until the old one is destroyed. And the old one will never be destroyed until all pages that are using it are closed. And so you can kind of be in this weird state where you're trying to upgrade the version of your service worker with new logic, new code or whatever it may be. And you'll do your cache management in here because if you're creating a new cache, you don't want to, if I destroyed an old cache in the install event on this new service worker, I could interfere with the same cache that's currently on the old service worker. So you manage the cache, delete cache inside the activate event so you don't step on the feet of the old service worker, if that makes sense. It's kind of complicated, but really cache management inside the activate step. So I want to show you a demo now and the demo is this very page. I am not connected to the internet. I can hit refresh a couple of times. Everything here is cached inside a service worker and this is on GitHub pages. So it's hosted with an HTTPS. So if I pull up the sources inside here, if I open up index.html, I look inside here, there's a script tag that says if service worker is a navigator, we're going to register a service worker. Oh, cool, that's awesome. If we look at the network tab inside here and I refresh the page, you'll notice all of the images and the content for this presentation. If you look at the size, it is being served, oops, it's being served from a service worker. So even though I refresh inside here, everything's loading, but it's all coming from a service worker and one of them failed the favicon, which is not cached apparently. So if I open up sw.js, which is the service worker, oh wait, it doesn't exist because it doesn't exist in this execution environment. It exists in an entirely new thread. So to inspect that, if we can go to chrome colon slash slash inspect and come to service workers, refresh inside here, we can see, actually let's come back over here. There it is. So I have a service worker on belittle.github.io. So let's inspect it and pull this up and here is sw.js right in here. And so we can see the actual logic of what makes this caching mechanism work. At the very top of the page, we are importing a script. Again, this is JavaScript 2015 sort of stuff. We are importing a script for a cache polyfill. The current stable version of Chrome does not include a couple methods for, it just doesn't include the full implementation of the cache API. And so this poly fills a couple portions of that. I'm gonna give a name to the cache and then I'm gonna list a ton of URLs that I want to cache. So I've got HTML in here, I've got images, I've got JavaScript, I've got a font in here, all sorts of different stuff. Here we have the install event. So once the service worker is installed, we are gonna open up the cache and inside the cache we're gonna add all of these URLs. That's all it is. To add a ton of data to this cache, all we do, open it up, cache.addall and array of URLs. It's that simple. And then on activate event, we're gonna open up the cache, we're gonna loop through the cache keys and if any cache keys exist that do not equal this one up here, then we will delete them. So this again is cache management where I could update the version of the cache and automatically delete old versions of the cache. And that happens inside the activate event. And inside the fetch event. So this is where the real magic happens inside a service worker. This is where we are actually listening to all fetch events from primary thread and we are going to really hijack the response and do whatever we want with them. Now inside here, we are matching, we're opening up our cache and we are matching anything inside the cache that matches this current request. If it matches the request, we'll immediately turn the response. Whereas if the request does not exist inside our cache, then we'll move downwards. An important thing here is, and this is kind of fundamental in the way service workers, web workers, these sort of things work, is we're cloning the request before we go and actually make the actual HTTP request for the data. The reason we clone it is because it can only ever be used once. The actual request and including the response down here once we make the request and we put the response into cache, we have to clone it because we want the response to go to cache but we also want the response to go back to the main thread. And like I said, any data that goes between the main thread and the actual worker thread cannot be shared. And so we're cloning it, one goes into the cache, one goes back to the main thread. But really all this code right here is really what does that makes this entire page available offline. And you may, I don't know, when I first looked at this, when I was reading about service workers and playing with them, this is a lot more complex than AppCache. And it really is. It is definitely a lot more complex but it's a lot more exciting. But can you think about all of the different things that you could write? Imagine all the libraries that could be written to abstract all sorts of different caching mechanisms. Like, and I think that's part of the problem with AppCache in general, is AppCache is one particular way to cache applications offline. With service workers, you can come up with any arbitrary way like that your application may need to work offline and you can make it work, which is really cool. You have ultimate power inside here. So I really wanted to kind of push service workers to the max and see like, at least from the caching perspective, see what I could do with it. And I wanted something that was very image heavy, a fair amount of code in it, but really I wanted to push a lot of data into the cache and see what happened. I wanted to try to break it. So I wanna ask you, who here has heard of the astronomy picture of the day? Like, a few people, not many people. The astronomy picture of the day has been around since 1995 where NASA has published an official astronomy picture of the day every day since 1995. And as you can see the website itself looks like probably what it did in 1995. So there's thousands of images on here and a lot of them are very fascinating. It's just really difficult to explore them. And so I thought it might be fun to A, mine all the data out of here and provide a different user experience and cache all this massive amount of images and stuch inside a service worker and see what happens. So if you go to, if you want to, go to apod.io. So apod.io, astronomy picture of the day.io. And here is just an interactive mosaic of astronomy picture of the day images cached offline. So I can refresh this page, I can click on images, read images, I can share them, download them, et cetera, and read about it. Just a lot of cool stuff in here. Makes a little bit more fun to just explore what's out there. Oops. But, so if I open up the code for this, so I have a service worker for this particular domain. So I want to show you inside here as well how you can explore what's inside the cache too. This is only available on like the latest version of Chrome. So like if you're on Canary or something like just a less stable version of Chrome, I think it's 42 and up. You can actually see the service worker cache. And I can come inside here and see all sorts of data that is currently residing in the cache. I can see, you know, I've got Font Awesome inside here. I've got these Ajax requests inside here. I've got some JavaScript. If I come to images, I've got images in here too. And look, I've got 649 images inside here. I've successfully put over 800 megabytes inside the service worker cache. And I don't know if that's a good thing or a bad thing. It's there, but I'm like kind of unsure about, well it's there. Because everything I'm showing you also works on your phone. So you can hit these slides in this page on your phone, pre-cache stuff, and then hit it offline as well. And so I assume there's some sort of mechanism for automatically clearing some of this data out, especially on a mobile phone where it's not actually gonna cache 700 megabytes. But it didn't break when I went through and tried it. But I wanna show you the code for this as well. So if I go inside sw.js, I wanted to write, like as I was thinking about this, I was thinking, well there's kind of a limited, I don't know, maybe a subset of caching mechanisms that by default a lot of people might wanna use. And so I thought, well maybe I can write a really simple app cache like manifest inside a service worker for caching data. And so this entire astronomy picture of the day application is cached using this service composer library that I wrote. You can go check it out if you'd like. But really the way it works is you compose your cache manifest by passing in a series of objects. Every HTTP request that comes to the page will be matched against a matcher, which could be a regular expression or a string. And if it matches, then it's gonna cache it with a particular mechanism. For all images, these images are never gonna change. Once I download them, I always want them to come out of cache. Whereas everything else, I only want it to come out of cache if I'm offline. Else I always want it to get an ever ready, ever green, I guess I should say, copy from the server. So you can kinda check this out if you're interested in, like, so essentially 20 lines of code that defines that much. I can also attach an event listener for when a success succeeds. I can test if it's a particular type of request, like it includes page, which happens to be an Ajax request, and I'm gonna prefetch all the images inside that request, which just includes a big list of image paths. But really, I think the beauty of service workers again is I think this opens like a Pandora's box of opportunities for developing applications. I was just speaking to Ryan Shaw just 20 minutes ago, 30 minutes, I guess maybe like 45 minutes ago, hearing about ideas he has about pushing JavaScript like a hot JavaScript loader through a service worker. Like there are so many different things that we can start doing with service workers that have never been possible. And I'm really excited. And the API itself is changing. There's new things coming in the API too. There is a push API for actually pushing data from the server directly to the service worker. There's a background sync API, and there's a geofencing API. There is some really cool stuff coming, all enabled through these service workers. I would highly recommend you guys check out service workers. You can very easily add some level of offline capability to your app right now. The very least you can add in like some page that's nicely designed branded for you that says, hey, you're offline. I don't know. You can do that very simply and very easily. I'd recommend you check it out. Here are some references and additional information. You can learn more about these. It's an exciting technology and doesn't even have any questions. So anyway, thank you.