Streaming Service Workers: Live Code Session - Supercharged
Skills:
JavaScript Fundamentals90%
Key Takeaways
Implementing a streaming Service Worker using live coding with Jake and Surma
Full Transcript
foreign pm and that means it is time for supercharged hi I'm surma oh you want me to say my name look I've never done this before looking have you not noticed different person standing here today that is a very long name hi I'm Jake and today we're going to do some streaming service worker cue the Jazz [Music] so Jake welcome I'm actually really excited about this because to me it feels a little bit like like an upgrade because not only do you know Social Circle you actually kind of designed them and you have hair that's true well a little bit it's a slight are you just easing into someone with more and more hair and eventually yeah like eventually I'm gonna have I'm gonna have a fro and it's it's going to get really interesting so we already said in the teaser that we are going to do or you are going to do a Blog with a streaming service worker yes so what I mean I know streams I know service worker but when you say streaming service worker what exactly like I mean okay so service workers are streaming by default like if you if you do like an idea a Fetch and you pass the response back to the page or like if you get something from the cache that all streams like you know it means that the page can start receiving bits of the response while the service worker's still busy so something put the end of the page doesn't need to arrive for the first parts to appear on screen yeah absolutely and this is like really useful like if you've got a long page like yeah even something like a news article it means that you only have to receive the the top and you can start reading it even though they're still downloading the rest of the article so but when you say software streaming by default then why is what you're doing in any kind difficult or worth putting on a live stream well okay so what we're going to do is we're going to make a single stream that's built up of different streams like so we're going to take some stuff from the cache and some stuff from the network and we're going to merge it together in one stream and serve that up and that will mean that we can get on screen really quickly with the cash stuff and that's important because usually we want to we're telling people over and over like the time time to First paint or the first meaningful paint is super important like if you're on screen quickly and keep the user busy with just consuming most on the Block especially with the content while the rest spins up in the background that is a super good user experience yeah and it improves the perception of performance as well and also gives you an opportunity to kind of you know so if the stuff from the cache arrives and the network stuff's taking a while it gives you the opportunity to kind of put messages up there going yeah we're still trying okay yeah that sort of thing which again it's better ux right yeah so I mean with you being here it makes sense that you do the coding today yeah and that means that I will be as one person usually does on the supercharge live stream I only want to hang in the chat so everybody hi welcome if you have questions anytime just put them in the chat I'll try to keep up with whatever you say and incorporate it and distract Jake whenever I can make him stumble make him do mistakes because that's what you want to see right so um I'd say let's just get into it and see where are we starting off because I think I know are we gonna do from scratch are we gonna take like a starting point well so a lot of service worker articles I've seen they do start from scratch but I think like most of us we have sites already uh so that's a good point actually yeah so I wanted to kind of start with something and show how you could add a service worker to it without detecting how the site already works yeah why don't you walk us through it I guess right okay so on my screen right now is what looks like my blog although I recreated it hashtag Shameless self plug yeah it's a self plug it's also my personal brand uh but it's it's an existing site it's this is how it works um and we're going to be able to add a service worker to it and I wanted it to be something that was kind of more site-like than the app and also something that would benefit from streaming so something with articles as well you know it doesn't have any of the kind of legal problems of showing an actual News website or something as well um so yeah so this this is it um you can sort of Click into articles and go around uh but I guess the important bit is how it's implemented yeah so if we dive into the code here this is a a node.js project built on top of Express which we have used before like I think whenever we did any kind of backend work with node I think we have used node in the Express in the past so it shouldn't be everybody should at least like know roughly what the API is I'm just going to make that assumption here well but yeah my blog in real life is actually built on top of Django and python but I thought like oh let's let's stick to JavaScript yeah that's probably good cool yeah also my python is a lot worse than my JavaScript and we're about to find out how bad my JavaScript actually is um so most of the interesting details uh so I've got this post folder which is a directory for each post I see it there uh and so we have like a meta Json with like sort of title okay summary description so basically it reminds me a little bit of um GitHub pages and Jackal but they have the metadata in the top on the top of the file while you put them in a separate file here which yeah I actually kind of prefer well so and this is all server generated um but it could be done as a static build as well yeah um having a server here means it's kind of easier to see quick changes it's not gonna that makes sense so we can see where our post is is built uh so I've got this Roots JavaScript and this is where all the roots are uh the important one that we're going to look at is this one so this is the roots for an article uh so you can see here it's it's built of like we get the your number now the typical block and path thing exactly where the weird regex or whatever that's not even the proper is it it is regex isn't it oh well it's the one that Express uses oh it's the way thing where you can capture parts of the thing and put them in a variable yeah so that's so that's the name of the thing we're capturing and then that's the the regex forest so a number four times um and then the slug is a slugger word that's used outside of like Django I uh yes I definitely love it it's it's in Jekyll as well Hugo uses it as well maybe they started it but it's by now it's a de facto technical term even though I still think it it's fun to say um so yeah and then it's just going and picking up those files uh if it doesn't find them it'll throw a 404. okay cool picked up later on um and then it's going to pass all of the details it finds into a templating engine uh the content is password marked which is a markdown processor and and that will appear on the page um the templating system I'm using is nunchucks that is an implementation of an originally Python templating language isn't it so you can see where I'm going so I think they're called nunchucks oh well in Python it's uh Ninja uh so I'm coming from Django templating languages just meant I could copy and paste what I already because you're really really lazy aren't you oh that's the best kind of developers are supposed to be like it is actually true like if you're lazy you're gonna automate whatever you can automate so and that's what we can see here it says this is a post and it's just all of the stuff coming out there and yeah and that works so in in its current state you're doing the the app shell stuff on the server you probably have like a header footer yes and that is being stitched together on the server side in an entire page is being shipped yeah so this is the base here and like the buttery biscuit base but the biscuit base look you need a new set of uh catchphrases now you've got someone else here um so yeah you've got these blocks here and you can replace those blocks into the templates I see them okay and that's how it works um so if we're going to add a service worker to this project oh well indeed any project step one has to be get your caching fixed get it all correct um and I tried to skip that for this I thought oh I'm not gonna I don't have to talk about lots of like normal HTTP caching yeah I'll just hack around it and then I kind of realized that I'm writing so much code working around bad caching I should follow my own advice let's we'll get get it actually really good advice because we keep seeing websites that use caching trying to work around caching rather than fixing it yeah and try to do is like cash busting whenever you have to do cash busting that is a smell that you probably just need to adjust your caching headers in the first place absolutely yeah and so that's what I did I know that's kind of pre-prepared uh because a lot of sites have this sorted already so we can see that the the CSS there the picture of me all has a version number there in the in the URL so you know that that's all taken care of the CSS uh well anything with a version number in the URL is cache control for a year uh whereas everything else with static URLs like the actual HTML itself uh is cache control no cash that makes sense so actually I think we have a microchip coming up on this on this topic as well so keep your eyes on the trend which also means you should totally subscribe to this channel so that you know when these videos come out so what's professional I know right pretty good it's not the first time I'm doing this like And subscribe excellent in case you're wondering the code is also is the code going to be on GitHub later can we do put it in our uh on GitHub now so yeah we're going to put it the the bits we are writing today or the Jake is writing today you're going to put it in the typical UI element samples repository that we have for supercharged episodes I'm going to link to it in the description so you can find that later and follow along if you want to like reiterate what we've been doing so shall we add a service worker to this project yes yes let's do it I give you 20 seconds good can I encode uh while on camera that's a question because I can't code in real life so maybe the camera will help so I'm going to create a uh directory here we have the first question actually and it's something that has the most mistake whenever I watch you work it's something's been driving me mad does Jake know that you can press command alt I to open devtools no I never do that I I always go for the right click driven mad by this as well before but he always clicks and I type with one thing all right so we're going to start with the soil so I go yes yes so and I'm just going to do that apparently it's actually going to be written from scratch which is cool I already can't type look at this it's like well to be fair you still have a lot more typos in your quote until you're actually worse than Paul oh okay fair enough so it's not that I'm bad at spelling it's that I have uh race conditions in my fingers from my brain so uh there we go let's just do console excellent isn't it called console.log oh my God before never this is this is new for me excellent okay so uh now I know this isn't going to work right because I haven't created a route for it yet so I'm going to do that now oh so you don't have like you have noticed the static middleware is not involved at all so I do use the static middleware but the static all the static files are the ones that are getting the uh the version number added automatically yeah so I've got a static folder here um and then the build sorry build system that there is uh is kind of going and sort of renaming and that allows you to sort like an expiration date of like a year on it because if the file changes the name will change and that means it will never clash and an important detail is that you don't want to do that with a service worker you generally want your service worker to be no cache uh because like the the browser is going to go to that same URL where it previously got the service worker to look for updates so you don't want to be revisioning it every browser has like will recheck after 24 hours this no matter what the caching header is but sometimes that is already too long because sometimes a person might be stuck on the old version of the cell Circle for 24 hours yeah if you break your site you don't want it to be broken for a day right so yeah I so I always use no cash um so I'm going to set up a route here uh JS and there we go see I'm already getting loads of things wrong right so I want to serve up that file so I'm going to create an input uh I'm going to use stream straight away we're going to oh look at that effect so uh and I'm going to get the directory name go up one level because we're currently in This Server directory are you going to do any processing on the cell cycle file to do things the only reason I'm asking is I always do uh response dot send file ah yes which is a lazy way but I feel like if you're gonna do this and you probably want to do some processing at some point that is true so I am uh yes so I'm doing sort of streaming stuff now because that will that will become useful later on as well so I should just be able to pipe like that uh and just to be clear I don't know what he's doing today I have not seen whatever he's going to do only he knows well I wouldn't even go that far so maybe yes uh so yeah we now have like our uh you know service worker all connected up so cool we should get it to actually do something oh yeah I guess you would actually have to include it uh yes we will do that as well um but yeah should we do that should we do that first why not I mean it's interesting because at when I first learned service worker I was like can I do console logs will I see them it's a different thread right it's like completely independent but it turns out as we will probably see in a couple of seconds that you can do console logs and see them in devtools spoilers I mean it it imagine how developers feel if they couldn't console log exactly yeah personally I don't ever use a debugger but I use console logs and I actually have a lot of beef with the name debugger because it doesn't actually debug the only thing it does it makes it slows everything down so you can watch a creation fall apart over a long time so you can find out what the call who the culprit is and it turns out the culprit is always yourself absolutely you might as well just replace the window with it's you you made a mistake so what I've done here is just in the uh the base template which is used by all of the pages I've just put a little script to the bottom that's what's called Progressive enhancement I think yes also with the if statement for browsers that don't support service worker that's that's there to catch those so yeah we should now uh be able to uh see in the console ah interesting yes okay so uh scripts don't have strict mime type checking Yeah by default module scripts do and service workers do as well uh and I haven't actually set up a a mime type for that so back in the old routes I am going to set the content type header so basically a service worker file will be just straight up declined if it doesn't have application slash JavaScript as its content type header absolutely oh well it needs to be one of the valid JavaScript mine types as well so um but yeah so the idea is it's a security measure because we don't want like if you have an xss we don't want someone to be able to admit yeah take one of the things they made like a text or a post or something and sort of be able to register that as a service worker so yeah we can see now we have we got a console log a console log excellent uh I suppose you probably want something more than that does it work offline yeah uh the console log will amazing but so far that's it uh okay you want something working offline okay let's let's do that um so web service worker you get a fetch event for every request uh for one of your pages but also for every request from those pages as well so um I'm going to I've recently read some of your code and I I for some reason it is totally ingrained in my muscle memory always type self dot add event listener and self dot skip waiting whatever there is that is not necessary itself is basically the equivalent of window on the main thread everything that is defined on South or window will just be available without typing out self or window and I find that developers myself including are entirely inconsistent on when they put like the window at the start and when they don't so so what I'm doing here is I'm just going to respond with uh fetching the thing that the browsers asked for so yeah that will be just kind of transparent sort of do the normal thing but I'm going to catch it in case it doesn't work okay offline would be one of those cases and I'm going to create a new response and just say like you is offline ah so when it fails the cat channel will trigger yes and we'll instead just return with your offline exactly so now we have basically we just made the blog work offline yes kind of well there's one thing that we need to sort of watch out for so we can see uh so this is the service worker that failed uh because of the the mime type so yeah I'll just get rid of that this is the service worker that we're they're using now um now if I refresh the page what's going to happen is that new service worker that we just added is going to come in yeah it's going to be waiting to activate um so service workers by default they don't get rid of the old version while while it's still in use yeah and it's still in use by this page why is that though like Why Can't This take over so another thing that as developers we don't really like handle very often is the idea that we can have like three different versions of our app running at once just imagine multiple Taps I guess right yeah multiple tabs where one's been open for a while you open a new one that's kind of using any stuff people who have opened so many tabs so that you can can't even see the favicons anymore and then you just open a new version because you forgot it's already open somewhere else well yeah when I get to the point where it starts looking like a table of elements yeah that's that's when I abandon I just need to just close them all if I don't know what they are well I really miss them no not really well the answer is usually yes but um so I'm going to skip the waiting phase on here and we'll be doing that with code uh shortly uh but now we should have a site that works offline uh so if I click offline on there and refresh the page it says he was offline there you go perfect ship it are we done do we do you want you want more well they're not streaming yet I mean it's kinda streaming but not really streaming not really streaming that is first we have to hold up that promise at least call this episode done so yeah um I guess we should do an offline page that's like within the style of designs maybe that has some design to it something like that sounds good um so I'm going to create that I'm going to create a page uh let's have a look so just in the templates here I'm going to create offline uh I'm just gonna copy and paste one of the things I've already got this is the the template for the post that I'm stealing um the title of the page is going to be offline um all of this header stuff like The Meta properties we don't need that who hates that um the title just like yeah you are offline excellent um and the content we can just say like uh please go online please how do we want the user to solve this like uh try refreshing while waving your phone around there we go which is going to be especially amusing if they're actually on desktop when they do this because they're hitting refresh and waving their phone around oh they're in a captive portal yeah so this is um I'm not going to create a route for this because this doesn't need to sit at a constant URL this can be a static asset as well yeah so I'm going to go along to the terrible build system I ended up making for this project which almost certainly should have been Gulp or webpack or something instead but I thought it would be simpler to build it myself that's probably the most Jake thing you could have done oh it so much of my time I shouldn't have done it so yes I'm going to add uh offline dot HTML I'm going to send it into the static rev path with all of the other remote assets and I'm going to render out templates and it's the offline one so when I save that well hopefully because the server is going to restart when it sees that code changing and if everything has worked we should see yes so we've got like ah offline HTML there so and you can see that it's good they've got all the nice markup and everything cool excellent so I'm gonna uh so we can see it in the browser oh you're lazy why well you would remember that now go on what is it six right okay so uh let's see so oh look in my history I've clearly done this before um right and and that is a much better offline page than but we can currently only access it online which doesn't feel quite right defeats the purpose just a tiny bit so uh what I'm gonna do is uh we need to take this page offline music yeah but not just the page itself we've got these other assets as well so we've got the page we've got the CSS we've got this picture of me that should be available offline I guess and these social icons as well I personally would be very happy if I could look at your face while offline well you can you know me that's something that's something we can just do in the same room together um okay so I'm going to we need to Cache this page um so just gonna go back into the the old service world yeah so I just gonna straight up hard code the assets that you're going to Cache or are you going to like analyze the markup or hmm keep going I guess no you're right because you this is the problem we're going to have because if I hard code all of those assets yeah then I'm gonna have to change them every time we make a small change true because the revisions change as well right yes exactly um so what I'm doing here is event.weight until which is so the install event this runs the the first time the browser sees this version of the the service worker okay and it's our opportunity to get everything sort of ready before this service worker starts actually controlling pages so uh because I'm from the future I'm going to use an async function here uh so what we want to do here is get a hold of a cache so we have a question are we going to use any tools like SW precache or uh workbox no no and the reason it's pretty simple because this is not about how to use a library this is about we want to show how these libraries actually work what they're actually doing under the hood so you understand the concepts more and then it actually is easier to use these libraries because you understand what they're doing and how you can debug the things they're supposed to be doing versus what they're actually doing yes um and also as I said Jake actually is one of the spec authors of service workers so it would be a waste opportunity to not actually talk about the low level the actual API of server itself and using a library instead but these libraries definitely do have a place so I encourage you to check them out and make the decision for yourself if you want to for production go this way and write yourself or rely on a library that is up for you to decide yeah absolutely yeah as I I just wanted to go you know as low level as possible with your stuff but yeah we now hit the point that you were talking about like how do I get those URLs and when I originally was playing with this kind of deciding how to do it and actually how I did it on my blog is I just used the templating engine that I had sitting there oh so basically the search worker itself is the product of running through a template and you can add the revisions dynamically yeah but what happened was it messes with all of the syntax highlighting the linters like yeah I've been there this is bad I saw actually you were writing in JavaScript with PHP yes I just did that yesterday and I'm generating JavaScript with PHP and that is also just in terms of syntax highlighting and like templating and template strings in JavaScript it just gets weird to keep track of what is a JavaScript variable what is a PHP variable can get really really confusing so a kind of solution around oh my notes have fallen on the floor how could I possibly continue without these oh fine quickly I didn't notice no one noticed so I'm going to use uh static module I heard a static module before uh no so this is a module by sub stack uh I also did browserify I believe yeah oh okay so browserify was basically I think one of the first projects to make to convert packages for the node ecosystem to run in the browser yes because node would use require and it doesn't exist on the web platform and so it would need to like somehow handle that and that was the project browser if I I think yes and static module kind of has has parts of that going on uh because you can you can pipe a JavaScript thing through it yeah and you can sort of modify parts of the of the JavaScript in quite a well I think it's quite a nice usable way so if I do uh static to cache and I just just for uh demo sake I'm just going to Output hello now once I do that these modules are available inside my JavaScript okay right so because I don't like typing very much I'm going to copy that so and up at the top here I'm going to do const to cache and I can use good old require statements uh so if I've not messed it up what I should be able to do here right and we can see that whole require statement has been replaced with also it just basically inlines absolutely that is nice okay I love it it's like if you're doing something more involved and I think like webpack and things sort of do this better but if you're just wanting to make small changes to uh you know you don't want to bring in the whole of where pack in uh I think this is a really nice small way of doing it and that reminds me something we've preached probably every time and haven't done yet is this is not production ready code oh yeah we are gonna write something that works we're gonna write something that is hopefully understandable and I shouldn't say we it's Jake this time something that you can read and understand Concepts or probably that shouldn't be pushed straight to production there's lots of Polish lots lots of um safety measures that we're probably going to skip on to keep the code third and readable yeah and I'd say one of the the things I'm doing here is like going processing this JavaScript on every request as part of Express is one of the things that I would not do in production you would uh if you did that on the server you would at least cache it so you're not doing it every time or it would be part of your build script and static modules compatible with all of that sort of stuff you can use or whatever to approaches um but right we don't want to just output hello we want to Output like all of the stuff we want to Cache uh so let's do that then uh so I'm just going to create an array of the things I want to Cache so okay uh let's go for so these are going to be the the file names without the revision right because what I can do then is map it across so I've got like a the thing which did all of the revisioning keeps a a hash of all of those things that it did uh so I should just be able to do if you're looking for the ref package that Jake is using you can't find it because he wrote it because why wouldn't he it's going to be in the repository later if you're wondering how he did it's probably just tedious to write not necessarily very complex I imagine it was yeah it was one of those things that I thought like when I was halfway through writing it I was like I should not have done this I should have just used difficult or because it sounds deceptively simple just you know hash the contents and put it put it in the name but I've been there when you have like cycling inclusions or whatever it gets really weird and um and I didn't solve those problems so like yeah if you want to to solve it properly I would say definitely use webpack did I sign a production ready code yeah yeah there's also gulp rev gulprev replace uh yeah that's probably one of the most the older project has been doing it for a while where I just add these kind of provision hashes to the name and Django has their own and I think rails has their own as well for doing the same sort of stuff so we can see that that sort of stuff being output um so you know I gotta gotta do the same for the rest um so basically just gonna add a list of assets that you know we are going to need anyway to be offline probably the very minimal set yeah it's just that just the stuff that appeared in the network panel when we looked at that offline page okay um then the revision's gonna be added then we can just use the vanilla add all cache command or just have them all be cached and be available offline absolutely so we can see that now like all of those and I say I agree I like it you actually called the picture me.jpg well you know it's not jake.jpg it's not Avatar it's me no one else is going to work on the code base of my site so it felt no it's not going to confuse anyone um okay so yeah we now have that uh that variable there and as you can see I can just like yeah off we go that is actually pretty cool I did not know about this module I like it I love it but we need to use it like we've sort of we've cached all of these assets but we've not told uh the browser yeah we've installed straight to fetch and therefore straight to network when the request comes in absolutely so I'm going to do another racing function because I all love them so yeah respond with and wait until they take a promise uh and with install if the promise rejects then it will throw that service work away it's like oh this failed um and we've respond to if we want to eventually return a response object so async functions are a nice way of being able to do that and and functions it's just so much easier to think about these things so I'm going to do cash response here uh let's go for event dot request so here I'm just saying hey do you have anything in the cache for this thing that's being requested so uh and and if something because it'll it'll be null if it doesn't find anything uh so which is which is something that I always have to remind myself of because sometimes I expect it to throw or to to reject the promise but that is probably just for an actual error and there's something not being cached it's not an error is like kind of like an expected outcome which is why it's returning null instead of throwing but I tell you what it does throw and that's fetch fetchable throw yeah yes because if it is a complete failure to fetch so it's yeah it will it will throw away it's a promise sort of reject in async functions that that becomes a throw so so somebody asked how does that pipe code actually work I have not used pipes before those are as far as I know the the old stream implementations of note so note had streams before the web platform did yeah and they had this concept of streams that you could pipe into each other I mean the web platform now has a similar stream but the API is a little bit different in terms of piping yes but if you want to know more about those look up the note documentation on their streams just Google for node and streams and you should probably be good to go yeah readable stream right will stream and transform stream that's all in the uh in the node docs okay um so yeah it's just kind of it's piping those things together but rather than passing the whole thing it can pass little chunks of it along and sort of process it in little Parts it's kind of really nice and memory efficient um so I've kind of hit a little stumbling block because here so I'm trying to fetch the thing and if that fails I want to return with that offline HTML yeah that makes sense uh but the best I know of the URL is offline.ht oh you don't have the hash once again don't have the revision name so this is where like the static module stuff is even more useful so uh what I'm going to do here is create uh static so you're just using as a glorif you're basically using this so you can keep it syntax hiding while just using it more or less as a templating engine yeah it's great isn't it I mean this is where Paul would say it works so yeah we don't speak about him anymore no so here uh yeah I've created a function uh rev get which is just going to sort of pass into that thing of like you know uh give me the revisioned version so I can just do here arrivegat equals required you don't have to call all of these modules static at first I just do to kind of so when I look at the code I kind of know which stuff is coming from like uh the static build system rather than stuff that's going to be left there interesting question um why return a weight Fetch and not just return fetch that is a good point it's a very small Nuance yes uh because if we return fetch then what it's going to do is it's going to pass the promise back uh even if the promise rejects we wouldn't know if fetch had thrown or not it would just be a promise that rejects but we want to be aware of a rejection because we want to catch it with a try catch so we can handle it so that's why it's return the weight which looks a little bit odd but you get used to it fairly quickly yes um so now if I refresh the page right we can see the sort of static revision there the offline thing is there that's that's I'm both amazed and disgusted by your use of static module well it's better than PHP templating isn't it so so let's have a look now so the the service worker should have updated because I've reloaded the page ah okay so we're it's still waiting to activate here yeah um like I said that if you've got multiple versions of your app running especially if you're dealing with data you can end up with the old version a new version clashing and creating problems we don't actually have that here because it's just a simple site yeah so what I'm just going to say here is skip over waiting and just call that as a function see I I would want to write self skip waiting but it's totally unnecessary you can just skip waiting saving those bytes so now we can see the installing one sort of takes over instantly uh and what should happen if I go offline hit the refresh button right I mean kinda so we're we're halfway there so what has gone wrong um interpreted style sheets uh but transferred with uh my type text HTML or do we actually block style sheets uh when they don't have the right mime type I thought we'd I think it could be a yeah I mean let's look at the network panel if the files are I mean yeah so there is an all.css being successfully received that is a sales like we're trying to to fetch it right yes yes so oh that's interesting so it's it's trying to do that it's not finding it and it's falling back to the offline page even for the CSS so everything is returning that that valuable yeah we don't quite want that so if we go online with this what happens here let's get to work so the URL is correct so it suggests that something is going on either with the caching or with the matching so [Laughter] so we got a cash response but we just threw it away oh yeah I found it didn't return it that's fine oh oh okay I was getting nervous like you're still online so it doesn't count yeah so I'm still still online everything's fine if I go offline now it should work that is much better oh and so like we're panicking I was a little bit panicking I got a see he has a cheat sheet but even then got like error throwing uh sweats going on okay so we've got this this whole offline thing working now so that's that's pretty good how many browsers support the async operator I think we're actually in a really good State I think all the current stable versions supported of the major browsers yes let me I'll quickly check can I use on the side but I feel like if you don't have to go too far back async no is it a weight async functions so it's everything except uh Internet Explorer yeah so Edge it does 15 since since the most recent version 15 uh IE 11 which is the last version version of it Explorer does not and all the other browsers with the current version actually do yes so I would encourage you all to embrace it and use it makes all especially with Star Circle it makes the code much more easy to think about and to juggle the things in your head right okay so uh let's let's have a look at how we're doing with this stuff because one of the things that I'm I'm not happy with right now is that we're we're opening this uh static cache right uh and that means like when we're updating the version of that it we're just going to be writing into the same cache which is not so great yeah um and so that means that the newer thing is going it's going might be overwriting things it might be messing with stuff um so what we normally do let's show you something I sometimes struggle to I I always keep Reinventing in my head if you install a new service worker do you want to redownload do you want to see what's in the Old cache and manually carry over and all these questions that you get do you create a new cache or just reuse the old one I mean it can get weird in between states so let's see what what you're doing this time in this version right so you can see on the screen here I am uh I've made a version one yeah so and I'm going to uh like sort of add static versions so and that's going to be my cache name don't you want to require the versions in because you want to change it yeah that is exactly the concept of Jake's code so uh so what I'm going to do here is say yeah so updating this version number time and time again that's going to be like it's going to be a real pain to do right so yes uh we want some we want to automate that somehow so over in the The Roots file I'm going to generate a version number automatically so what I'm going to do is like I need a version number that's kind of all of the um it represents what's unique about that service worker and it just so happens that we have a way of doing that and that's with the URLs yeah okay so this is what I'm going to do now so you can talk a bit while you can describe what I'm doing and no he's typing a constant variable at the beginning so um all the crypto one that's actually a standard node module which is I'm always scared of touching because it says crypto and crypto is basically you never want to roll your own so always rely on available implementations for these especially if it's actually security relevant which I guess in this case it is not really but yes so let's let's have a look this it's it's not really on crypto it's all there already exactly so what I'm going to do now is create a hash question on the side what is the maximum size in kilobytes or whatever that a Social Circle can cache and that's actually uh it's a very hand wavy answer I'm afraid um it depends on I think the and maybe you have to correct me here but I think the most recent answer I have is that is a fraction of your available space on your hard disk yes yes it is uh so it the the what the service working in cash is part of like the sort of general what can the browser cache yeah uh so you get a kind of shared space for index DB the cache API local storage all these sorts of stuff so um right what I'm going to do here is so I've created a hash now it's md5 uh let's not be too scared of that you know it's it's just this is not for security reasons it's not Security even though md5 is being discouraged for hashing the contents and having a somewhat unique identifier is perfectly fine yes and so what I'm going to do here is uh go through all of the URLs that I'm caching uh so for each uh and let's go for sort of URL and then sort of hash dot update so this is going to add all of those things uh into there URL uh so this is you know adding each URL into the hash okay and now I'm going to create a version number from that which is the hash dot digest and I take in the uh hex of that and that can be the version number for this service worker also creating a version number depends on your on the static files that you're hashing and since they contain a hash that means that your version number will change even if only the version of all the dependencies change yes okay I'm sweating quite a lot it's warm in here isn't it it's it's it always is you have to imagine we have some lights because otherwise it would be fairly dark in here but I guess I've gotten used to it at this point we can we can keep the the camera on the screen so you can't see how much I'm kind of actually dying here right uh so I'm going to do static version here uh and what I'm going to pass through here is so the reason you're doing this just to reiterate that I get it right is you want the version of your service worker to change whenever one of your select files change because you want the service worker to re-download all the files in that case absolutely absolutely okay so the problem would be if we didn't change the service worker file I think they always still do the byte equivalence check it is by equivalent yes and that's what what it's like I've always been and that's kind of why that's where things will stay in terms of that so so this is a nice way of making sure that all of that by itself installed it's gonna try to redownload it the next time you visit I guess and compare the code of the service worker file the main server file and if they are byte equivalent namely the exact same file nothing is going to happen and if the dependencies have changed your search worker wouldn't know about it all right so that's why we want to make sure that our service worker code changes at some point if our dependencies change and that's why this we basically use the hashes of our dependencies in the version number so we can make sure every change not only of the software file but all the dependencies will trigger a re-download of all the necessary data absolutely so now we can see here in inside the service worker file there we've got that version ID there and that's going to be used in in the the uh the cache name and that's going to carry forward into the into the service worker itself so now if we load the page that new service worker is going to come in and I'm going to refresh the caches here I did see yes I did not know that we had a right click refresh because I always reopen Dev tools oh you actually close and reopen it yeah I didn't know that there was wow I learned something today right amazing but you can see there's a problem here right like we've got the uh the static cache name has got this sort of long hash at the end of it which is what we want but the old cache is still there so I'm going to go over into the service worker code again and we're going to fix that so uh I had event listener so we're going to use the activate event so install is basically the search worker file has just been downloaded and you can hook into this event and run some code to make yourself so set yourself up and activate is once you're done installing and the search worker is actually about to take over responsibility for all the requests of your site that is where activate comes in right yeah so at this point we know that the old service worker is gone so we're in a good position where we can actually start deleting all of its stuff that it needs I see so let's have a look I'm going to do uh uh keys so what I want to do is look through all of the caches that are there delete the ones that we don't need so uh if I do awaits caches.keys here we go um so that's all of those now so I just wanted to get a list of all the caches that are currently yes available in your caches API absolutely so I'm going to go through each one uh iterate over them and if I find one that is so if key doesn't equal the cache name that we're going for so basically you're cleaning up after the old service worker you're the new one you know what name your cash has and that means all the other old caches can be removed because you are already done installing yourself absolutely that's exactly what we're doing okay I understand uh okay so yeah you can see that initiative if it's what I'm not expecting I'm just gonna get rid of it uh and so hopefully now if we reload the page we should have a new one and the two other ones should be gone that's what we're expecting right yes so if we go into here and that is what's happened excellent so yeah things things are looking correct in the right shape it does look correct yes so that means that you know when we add a file to the cache it's going to create a new cache for that like static with a sort of new hash at the end uh and then it's going to sort of it will delete the old one once this once this okay we got two questions one of them why use await on Cache Keys is that async yes it is yes it is because the keys is part that's still on disk right yeah so anything that's stored on disk we want to to make sure it's not going to be blocking anything because I O operations on the disk are 10 to be very slow and at least in in terms of web time budgets that we have so we base I think actually almost all service record apis are async just so we can have the opportunity to to defer work a little bit until the browser has time to actually get to it absolutely absolutely so we kind of we've got a nice uh sort of streaming well it's you know it's not streaming yet but we've got this nice offline page and we're controlling our caches now um but this is the point where we want to start thinking about the streaming stuff right yeah because right now it's still just entire Pages being cached Yes actually not even cache but yeah yes but if we think about the the pages that we've got we can see sort of the so you know this column here is always the same yeah so we could cache that and we've also got the header along the top here this is static as well it's a very complex Black Block that that tiny bit there well you know there's also the Jack Archibald roads you know that's uh somewhere absolutely so um it would be nice to deliver that before then Network so that's something that I want to try and do here so we can you know deliver that bit and then start streaming the network stuff through a pattern that you might have heard of um to do this is called app shell yeah um so app shell I'm gonna try to explain it and you tell me if I'm right all right all right um basically in the most primitive form you have your header bits and you have your footer bit and then you have your content in the middle but that means that you never have to actually re-download the header and the photo back and just get the con in the middle and and swap that out for the new content yes and if you do that on the server side it's app shell if you do on the client side then it's basically Spa single page app kind of routing thing absolutely so if you take a look at this example here we can see that the like it's got the sort of Gap of where the content would be yeah and the typical way to do app shell would be to like to to Cache this display this and then let JavaScript go and sort of fetch all the content so while the fetch is still going on we're on like a very slow Network or a network with very long delays the user would already see this and be reassured actually something is happening that the network is working and something is being loaded but it just takes a little bit longer and that's why this why the streaming service worker is such a good user experience because you can see something happening on screen for free right and and yeah and the actual model the problem with it is that people like if JavaScript just handling that fetch it needs to download that whole article and then have JavaScript put it in and that's that's where things get slow and I have a demo of that it if we get to a position where we can do this one like kind of correctly we can compare it to the traditional app shell model um okay so uh the first thing I I guess I need to do this is I need an end point that gets me just this Center bit in the middle bit of the answer because if we want to do app shell we don't want to redownload the header that's the whole point so we need a way to get just the middle bit absolutely so I'm going to create a template for that so down in my template system here I'm going to create a new file and that's going to be uh post Inc that'll do uh NG okay I'm not very good at naming things I don't know why I design API well it's one of the hardest problem in computer so I'm just going to copy what we have for the the post template here and the things we don't need is we don't need this extends bit we don't need any of this header stuff uh in fact we don't really need the the main content here uh I'm just going to move that out so this this is the only bit we need uh so now we just need to kind of come up with roots for that so if you render that template there's basically the entire header is missing we have no header footer it's just going to be the markup by itself it's going to probably going to look really weird because there's not going to be Styles there's going to be you know no layout whatsoever but once put into the context of our header and footer it is going to look great yes or like just as it's supposed to be well we'll see let's not say great we'll see if we can get there that's uh so here in the in the routing system again what I'm going to do is I'm going to I could create a whole separate route for these includes but I'm going to cheat a little bit uh and what I'm going to do is uh put a little include bit at the end there uh and the regex for this is going to be the word include so it's literally can only be that and it is optional uh and check out these hacks so uh I love it already the template name is going to be a request Dot params.include and if that's there we're going to use post Inc otherwise I'm going to use okay that's pretty neat I mean so you switch depending on whether the input or the include option is present in the request URL or not you switch all the templates being rendered absolutely so okay I mean assuming it works right that's uh so the good news is no errors on the server so far uh this this is the normal pages I can find and if I go to include there's no styling if we look at can you do command alt U for me so let's say command alt and U gotta teach you some shortcuts so we can actually view the source and you can see it goes start straight with the diff like this all the other stuff smithing and now we if we put that in between the header and the footer we will be back at the original page yes so uh yeah so now we just need to to kind of do the rest we need that the the kind of start and end that we want to uh you know the thing to wrap it all over around so we need to create a template also for the shell the kind of the inverse of that the this page but with that bit missing uh so let's do that as well uh and it's very similar to before I'm just going to call it let's call it shell or even spell it right uh and let's have a look now so I'm going to take the post again it's a nice thing to copy from report everything else except you exactly uh we're going to come up with the title of uh loading because this is going to be sort of displayed initially I see um we don't need all of this header stuff and this main content um we can get rid of it because that's the post we don't we don't have that to display yet and this is where we're going to put all of the stuff okay there we go for the people tune a little bit later hi this is a supercharged live stream and we are doing streaming service driver which basically allow you to stream your responses to the client meaning you will be on screen much faster and give your users a way better experience without having to do any sort of triggering because usually the network does it for free but once you have a search worker in the middle it is easy to to fall back to easy habits and remove that feature off the web which is streaming yes so with the like what we did with the offline page we need to put this shell into uh the static cache so uh so you know here we are in that little build system again I've copied the line and I can just like even with multicuzer I like multi-cursor I do I do as well um but the problem is it's like it's not actually what we want because I what I want to do is I want to start and I want the end right now it's both right and right now it's both so I love this so I'm already afraid of what you're gonna do uh this is so let's let's take the actual content of the shell okay uh so it's there and the slice points is going to be content go here because that's oh my because if we could because it's look look it's there look look so we're gonna split on that that's fine so this is web development that I thought was just like you know to to guide you is actually now going to become a programmatic instruction of where to split the shell into header and footer bits because why not why wouldn't you do that so here we go we've got shell start uh and so what I'm going to do is uh let's see shell oh shell dot us lice and I'm going to take the uh shell Dot uh index of and it's going to be of that slice point so that's actually going to give us the end uh so I want zero there as well and I should just be able to copy that and I see end and just remove that there and if everything works um then we can see that we've got the Shelf shouldn't you add the length of slice point so what SIM is talking about is like in the end there it's got this this comment sitting there so let's get rid of that uh there we go plus slice oh yeah slice Point Dot length and now I feel much better are you happy now yes and we can see that I saw that update and there you go perfect let's do perfect okay uh so now we just need to start we need to Cache these so now yeah so we need to catch them then we have in the cell cycle and then we can actually start stitching things together absolutely cool so um if we want to add extra things to cash in the service worker we're doing that in our routes right now so I'm going to continue to do that so let's go to shall start and shall end there we go I always like to just double check that this is actually working so sw.js and we can see yeah so we can see those things there cool that's all working so that means now because they're in that list they're gonna get downloaded on Social Circle install we have them available in the cache and we can use them to Now do and it's gonna be a weird sentence we can do the server side rendering in the server yes yes it's kind of the service worker service worker side rendering that's the thing that's that's a thing there um okay so this is going to require a little bit more code in over in our service worker the first thing we want to do is kind of identify those pages that we're actually going to do yes this streaming thing with because we don't want to put like images in between our headers and Footers right right so and the easiest way to and this is one of the things where things like uh the service worker toolbox and all of that sort of stuff come in really handy uh but we're not using them so we are purposely Reinventing the wheel a little bit because you can't appreciate what these Pro the amount of work these projects do for you until you have done it yourself absolutely um so I've passed the URL out here using uh the URL uh Constructor which is kind of part of the web platform and has has been for ages and that will give us access to all of the different parts of the URL so what I'm going to do here is before we're going to treat the rest of this code here as is our sort of like General case yeah that's how we're going to handle everything I always want because I see when I write Silver Circle I do the same thing I often do a new URL to get an actual parsed version yes why why is that not part of the API um because Anna vanquestrin said no I I think it's more of a I mean it it is work it can be safe we don't need to do it and then it should can be a developer so I kind of can see that I just I see myself doing it so often that I was wondering so Anna van kestron wrote the the fetch spec um and so but he has a good point actually that all everywhere else through the web platform we only give the URLs a string set for window.location well self.location okay which is a little bit of a special case to be honest yeah I think so it's it's consistency and you always have the opportunity to do it yourself anyway so yes so the first thing I'm going to do is like I said the the service worker gets fetch events for uh request the page makes yeah and that includes requests to other Origins as well that's actually super interesting because you can cache requests and responses to another origin you just can't inspect them right correct yes uh I mean if the unless you've made a calls request yeah you don't get extroversible to be honest who uses course everyone uses course it's brilliant it's have a security if the web Works uh so I'm doing An Origin check here so I'm like so everything that is your origin yes I can just compare it straight to location.org okay but then I'm going to have a look at the path name so URL Dot half name there we go uh I want to see if this looks like one of our the Articles uh I'm going to use regex because that I mean because you already had somewhat of a regex in your back end whereas like we want four digits for the year and then some title yes so I'm going to do that uh I can never remember with regex which way around the symbols are is it and then yes let's start and end excellent because you don't want those the other way around else it never matches um so it starts with a slash and then it is as you said um well we could we could say we'd be specific it's four digits exactly four digits I don't expect my blog to be around once we take over to five digits on the earth or have blog posts from pre-year thousand What will what will the world be like then uh and then the rest of it is just anything that is not a slash uh okay I love regex I mean that's totally readable right that's that's yeah yeah look at this and be like I get it I got it yeah so if that happens uh I'm going to defer to another function like that's the whole stream article there we go I'm going to pass in the event and the URL so and this is the function we're going to write basically that's the stitching of the app shell is the word yes absolutely that uh but let's I mean we've been writing a bit of code we haven't tested it for a while so let's return new as a side note uh Andrew bats hi he has a question um event dot wait until when to use it any rules of thumb and yeah what is your take on that so you use event.weight until whenever you're doing asynchronous work and this is this tells uh in some cases it's the the return value is Meaningful so like in install uh if the the promise rejects then that tells the service worker this install failed right something went bad uh either we failed to Cache some things or like there was a an error thrown or something and the browser will see that as an indication of like I'm not going to use the service word which is probably good because if you have to work on like a broken basis to to bootstrap your page your installation should go flawlessly otherwise it's better to be like absolutely but it's not yeah and that's another good reason to use like unique cache names when you're updating because you don't want to kind of do half an install or botch it and you've already messed around with some of the stuff that the current version is using so uh whereas with activate wait until it's just a signal that you're doing work yeah um and then it will the browser will prevent fetch events coming through until you've done that work um fetch also has event.weight until which is a way to say look I've I've sent the response but hey I'm doing some extra work as well and that's actually really interesting because you can say event respond with and already have your response ready and then have to do more work after the response is already given out so try to get to correspond with as fast and as early as possible to have to get that out of the way so the client the actual browser can continue working and then continue with updating the cache or whatever you want to do in the background absolutely absolutely and we are going to use that in a minute as well oh cool but first I just want to make sure that all of the uh the stuff is working so starts there um so I'm going to use a feature of service worker here of our Dev tools called update on reload and this is one of my favorites it means like because currently we refresh the page and then it looks for an update to the service worker yeah it finds it it installs it and then you have to hit refresh again to actually get code running through that new service worker this here means it it shortcuts that it just takes one refresh it finds a new service so you would have to reload it checks the sales record downloads installs it but he has real another time to work to actually activate well this just throws away the Old Source worker before the reload downloads the new one and if that one gets installed absolutely so now we should be able to hit refresh and that new service worker comes in that's fine this is what we expect but if I go to this article it says this is an article excellent I mean it's it's something of an overstatement it's an I mean how much text do you want in your article but that what that does is it confirms that we're uh correctly identifying that you're the root regex the cryptic one is actually correct and we can see that the includes it's not capturing those it is just the the overall uh article page so right this is where we want to start doing the actual magic of tying all of these streams together so uh what I'm going to do is gather all of the parts that we're going to join together so I'm going to do caches dot match um get and static so the first thing is the shell start I'm also using rev get the first thing we want to send back is the header because we know it's always going to be the same and we know we have it in Cache yes you don't even need to worry about the actual content right now we can already start streaming that bit because that's the the sort of generic part so that's all working fine and we're going to do the end as well but in between those two bits we want to send the actual content down yeah so I want to fetch and I can't just fetch the URL here because that would be for the the full article page what I want to fetch is the that include part right so and and that is probably where it comes in that you just put something on the end because you can just take the request URL and add slash include well I'm going to be a little bit safer than that um we'll get to you yeah well because for instance if there was a query string at the end like a search string as the web platform calls it just adding include to the end of there that could start breaking things so you can see here I've done uh new url url that kind of clones it so I've got a copy and what I can do here is do uh path name plus equals include so now that is going to add it to the end of that that URL there so I can just uh fetch that and that should work but now this is the part we want to sort of tie all of those together uh so each of these responses from the cache from and from the network are by themselves individually streaming but usually I remember when I did first when I first wrote this kind of Social Circle I would just turn them into a text block concatenate right send them back and that is not streaming because that would mean I would have to wait for the fetch to finish before I would start sending the header right and if you do that you're going to have that whole problem where you're having to buffer the entire response before anything comes through and that's that's no good so uh what I'm going to do is uh so we want a writable endpoint um that we can sort of feed all three of these two uh that will turn it into one readable point so because you know with a response you can give it a readable stream so what I'm going to do now is uh I'm going to create a for Loop where we can sort of go around each of those parts but first I need to create this this readable and this writable object and there's going to be a great feature in the web platform that can do this for us so I can do a readable writable and that equals new transform stream now a transform stream is something that's going to take like Parts uh things in and Chuck something else out uh so changing transforming the response in some way but if you don't provide any of those details it just takes stuff into the writable and pipes it out of the readable bad news is we don't have that on the platform yet so we're going to have to sort of hack our way around it um and I'm not going to write that now I have a hack prepared thank you just uh this is an identity stream so why didn't I just do this for the whole thing it says I have a project here I'm just going to stitch together see you learned a lot today copy paste so the thing I think it is absolutely legit to copy paste in that bit because it is part of the part of the specified platform just browsers haven't gotten around to implement or actually the spec is not completely finished as far as I'm aware yeah they're still working on that but we think it's going to be landed in Chrome uh in the next few months so like okay sometime sometime before the end of the year which we'll wait and see but what this polyfill is doing here it's creating a readable stream and a writable stream and we can see here sort of inside the writable when it receives some data it's just passing it to the bridge so it's literally just like whatever you receive put it out on the other side it's literally a pipe yes yes and that makes our code like so much easier to write because now we're responding with our readable stream um but we're not putting anything into it yet okay um so this is where we need to actually start creating that and so we want to do a little bit of asynchronous work so do events dot wait until oh I see I was wondering if you forgot to make this function async but you're actually doing an anonymous async function inside yes and so while we're doing all of the streaming work this is instructing the browser like hey don't close the service worker we've still got important things going on uh you need to let us handle this so what I'm going to do uh is go through that array that we've made all of those parts okay cool let's call it Parts because that would be a better name um so now I'm I've got each of those each of those and I'm going to get a response object from each uh couldn't you use 408 yeah so that's interesting so there's a new thing appear in the platform which I don't think we have in Chrome yet oh we don't oh then then never mind me I thought but yeah you're right we could we could do um with that and that will process the the promise we are iterating over an array of promises because both caches.match and fetch we're trying to promise and with four weights you wouldn't forward iterates over the array and give you the promises for a weight would give you whatever the promise resolves to and yes wait with a looping until that problem is currently that is the next one has resolved yes so yeah and I'll I'll check if we have it uh well we definitely don't have it in stable and that's what I'm using uh I wanted to use Canary but it turns out that this morning all of the network throttling and offline stuff is broken in Canary well that's cool so like like a peasant I've had to go back to Chrome stable I know it's terrible what a nuisance So Okay so we've got this this response now for each of these parts uh and what I'm going to do is response dot a body which is the stream uh of the response and I'm going to uh pipe it to uh the writable and so there's your pipe call that we have seen earlier in the node environment it's similar yes it's not the same but it's very similar yeah so it's a it's differentiated in in web streams we have pipe through and pipe two yeah which is kind of whether you're dealing with a transform stream or whether you're dealing with a writable and I need to await that because it's we're going to let that happen and now by default when you pipe uh something like a readable stream to rival stream once it's complete it closes the writable it says I'm done now you are done as well we can all go home it's fine um but we don't want that to happen here because we want to to write to all three all three parts so there's an option here uh called prevent close to prevent clothing yep it's a very well named option lovely nicely named but once we're here we actually do want to close it um I mean you could do fancy things with the loop where you detect if it's the last one I think that's it is arguably more explicit I think it's fine so uh yeah so here I'm going to do a writer and get thank you I knew that didn't sound right uh it's a writable get writer and this is holding a lock on the the stream so we can do stuff with it after all the piping is done uh and then I'm just going to call close and tell it it's done so that means yeah okay so we now that would mean that the response no the writable should consist of the header then the content then the footer yes to the browser it would look like it is one document yeah as far as the browser's parser is concerned it is just receiving one response like the whole thing about it being three parts that is entirely inside the service worker okay now aha I just spotted bug I've still got transform stream there so let's uh change that for identity stream I'm going to copy yeah transform streams can actually transform you can hook and code and do some transformation identity stream is what we said like just whatever you get just don't do anything pipe it back out yes and the default for a transform string will behave like an identity stream okay so so just to recap we are taking the header what you have in the cache yes we are taking the content which we are fetching live from the network which could be a little delayed or not and we are taking the footer from the cache again which are three individual responses and these responses are now being stitched together so that to the browser it is one document but even if the actual content is delayed we still starting to send the header straight from the cache and the good thing about that is that we would actually see something on screen even if our network is being weird about sending uh or has problems with actually getting it fast enough to have like a fluent delivery for the whole thing so I guess at this point we can actually try and see if this works or not yeah that's the Moment of Truth eh so uh let's let's have a look so we've got uh identity stream we've got all of our parts here it's all looking correct um I mean if you can just look at JavaScript and say it's correct it is actually hugely impressive well I can't so we should find out I'll tell you what we should do we need a way to sort of know that if this is working so in the Shell uh where it normally says check out wrote I'm going to put streamed uh so we're gonna know that that's that's working so it means if we reload the page with other Social Circle we'll say road if the Social Circle is actually doing its job in between the road at the top and the green box should turn into a streamed and it did amazing look at that that's amazing I'm so glad that worked um so yeah so what this is uh now ah okay there's a problem is your Eagle Eye spotted I have seen the problem the problem uh well so what we can see here is like what you to be Unicode what use the Unicode is now not um yeah okay so this is a problem sounds like you stripped a little too many of the meta headers maybe that is exactly it there's uh the response here there's no response headers at all uh being sent uh what we really want is uh something so what I just did there is a shift uh reload command shift reload yeah that's that passes the service records bypasses not just passes it bypasses the sales worker uh so what I can do here is have a look at this so this is the content type header I'm normally sending um so I'm going to like I mean you could also put it in your header and say meta charts at utf-8 right yes I could do that but you know what to do it on the server side yeah why wouldn't I wouldn't Find Jake um but it's it it seems good to have some proper headers uh yeah right now we're not even telling it it's HTML it's just coincidence that's what the browser will interpret it as so here I'm just going to do content type and there we go and what should happen so if I I'm going to keep the uh update on reward so we're gonna get the new sales worker straight away so we should see it straight away I'm streaming we have the right content encoding so we just built it's shooting star soccer didn't we yes or you did yes we did uh it's yeah it's and I I think that's all we oh there's one thing that we need to fix um and this is a a problem that I I think we need a better solution for in the web platform okay um and that's that we've got this it still says loading up here uh that's the title for the page um true oh changing titles that used to be all the rage and the 90s people have like little animations going on so and that is the solution that we're going to use here so it's just here in the article include I'm just going to do a script oh it's horrible and hacky it would be nice if we could have multiple title elements uh and that one would replace the other and it would sort of update you know with whatever the last title elements it sees is but ah what I can do here is just uh let's let's go for meta dot titles this is coming from the scripting the templating engine and Jake answerable.com and so now that it's updating nice we just got a question is there anything like incremental cash update like diffing or something like that there is not uh but it's something that you could build yourself inside the service worker so you could be sort of fetching stuff yeah that you could uh you know it's a tell the server I have this version of this asset or it has this hash or whatever and then the server can go oh yeah I know the history of all of this stuff here is just a diff to apply um whether that's something that's going to be useful in a long time yeah I I yeah I don't know so just as the final proof of this can you do this with network spot links we can see that the shell appears right away but the content gets streamed in I thought you'd never ask and I think that's that's kind of what we should end on and have a look at what the app show uh compares to this this the idea of working it with with JavaScript so um let's let's put the throttling all the way down to GPRS because you know it makes it look the slowest off the slowest well well it's offline slower or is that just broken it's nothing still something now we're getting too philosophical in here I think so I've turned update on reload off so it's not going to try this worker yep uh and I should just be able to reload the page so you can see that was actually really cool to see and if you didn't because did you have screenshots enabled screenshots can revisit what we just saw namely that I think in a matter of a fraction of a second we had something on screen namely the shell yes like straight away from the southern Circle here's the header so we can have a look here and you can see that so here's the sort of paint time um if I just shifting like so kind of 65 milliseconds we got that first paint uh of that that top bit of content and if we move along to uh where is the next paint sort of around here so yeah that is uh at one second that's when we actually start getting the article content and that's coming from the network and that's the bit that's being throttled okay and so that's you know uh so yeah I'm going to rely on you to remember those numbers so it's about one second I have an entire audience to remember this one oh excellent okay so if everyone can remember that stuff um what I'm going to do is I'm going to see if I can remember git because you see I've done a lot of code now so let's get stash git add uh would that work would that be also files that haven't been added to the index let's let's do this um I think you might be right uh so and I'm just going to call this uh attempt commit because why wouldn't you why not um oh yeah I haven't added my name already that's fine so uh so now I'm going to do checkout and app shell excellent right that's work now the server's restarted um so let's refresh the page so so this is now just um I should turn the throttling off because it's it's let it update that service worker um so we should see that there that's fine okay so if I refresh the page it says I app showed some content excellent so that's the proof there that it's that it's actually changed so now we can compare this and this is the so the difference here is it's loading in the Shell all at once yeah and then it's going to that JavaScript is going to pick up all the content from the same include uh and then it's going to insert it into the page so we should compare this obviously to this over the same network speed otherwise it wouldn't be a fair comparison absolutely so we've got GPRS on again all the same sort of cache settings and we can load it now so yeah you can already see the difference there was enough time bars to look up to the camera and look confused why we're looking at an empty app shell and it's still going so if you have some kind of single page app this kind of um streaming soil circles worker can make the experience of opening and loading inside so much better yeah um so we see we got the first renders yeah that was still quick yeah um but the the final render there um was kind of like three seconds four three four seconds in which is and this is obviously not a full blog post I think it's just some text if you have a longer blog post with some media assets or whatever it can it can get worse absolutely some of the longer articles I've got on this it goes up to like eight seconds whereas the streaming one is always there kind of pretty much straight away and it's also slower because because you dump all of that HTML like right at the end that's the point it discovers all of the images and stuff it needs so those downloads start already laid so it is basically a win all around so I mean that is how you do I guess a streaming service worker and just to be clear it's actually kind of cool you just did that in stable usually we are very prone to being on Canary with a web platform flag enabled and doing all the Leading Edge stuff but this works in Chrome sale and actually works in Firefox as well unfortunately not they don't have streams yet they don't have streams so that's the that's their blocking thing um Safari doesn't have service worker yes uh it's very different they have streams yes so if they could just you know exchange some code yes can we just soon I hope we will be on a platform where everybody has service worker and streams and we can do these kind of performance tricks much more often so as I said we're going to put this piece of code that Jake wrote gonna put it up on our GitHub repository yeah um thank you so much everyone who came by and talked to us in the chat and asked questions I hope you learned something and thank you Jake for taking on the challenge I think you did amazing thank you and with that have a good Thursday and see you next time bye [Music]
Original Description
In this Supercharged Live Code Session, Jake & Surma implement a streaming Service Worker, coding in real time, bugs and all!
Whether you are watching live or not, please send in your questions and comments to the guys as they will read them and if they can, answer them for you.
Code for this live stream session: https://github.com/GoogleChrome/ui-element-samples/tree/gh-pages/streaming-service-worker
Playlist
Uploads from Chrome for Developers · Chrome for Developers · 0 of 60
← Previous
Next →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Polymer Performance Patterns (The Polymer Summit 2015)
Chrome for Developers
Polymer Power Tools (The Polymer Summit 2015)
Chrome for Developers
Chrome Dev Summit 2014 – Chrome Case Studies
Chrome for Developers
Web Directions Code 2015 round up
Chrome for Developers
Maintainable Code - HTTP203
Chrome for Developers
iron-ajax… wat?! -- Polycasts #26
Chrome for Developers
The Guardian - Supercharged
Chrome for Developers
ES2015 (next version of JavaScript), Totally Tooling Tips (S2 Ep1)
Chrome for Developers
#AskPolymer: Rob answers all the questions ever -- Polycasts #27
Chrome for Developers
The Future of JavaScript - HTTP203
Chrome for Developers
Data Binding 101 -- Polycasts #28
Chrome for Developers
The Guardian part 2 - Supercharged
Chrome for Developers
The Future of Web Audio: with Chris Wilson and Chris Lowis
Chrome for Developers
Chrome 46: New motion-path animations, client hints and service worker improvements
Chrome for Developers
Sublime Snippets, Totally Tooling Tips (S2 Ep2)
Chrome for Developers
#AskPolymer: How do you make the show? -- Polycasts #29
Chrome for Developers
Critical Path CSS, Totally Tooling Tips (S2 Mini Tip #1)
Chrome for Developers
Binding to Objects -- Polycasts #30
Chrome for Developers
Player FM - Supercharged
Chrome for Developers
Where’s the Designer? #AskPolymer -- Polycasts #31
Chrome for Developers
Jake Beats Wikipedia - HTTP203
Chrome for Developers
Supercharged Observers! -- Polycasts #32
Chrome for Developers
Jai's Web blog - Supercharged
Chrome for Developers
Windows Command-line Tooling, Totally Tooling Tips (S2, Ep4)
Chrome for Developers
What about internationalization? #AskPolymer -- Polycasts #33
Chrome for Developers
Developing for Billions (Chrome Dev Summit 2015)
Chrome for Developers
Google+ Performance Improvement Comparison
Chrome for Developers
Deploying HTTPS: The Green Lock and Beyond (Chrome Dev Summit 2015)
Chrome for Developers
Progressive Web Apps (Chrome Dev Summit 2015)
Chrome for Developers
Instant Loading with Service Workers (Chrome Dev Summit 2015)
Chrome for Developers
Increase Engagement with Web Push Notifications (Chrome Dev Summit 2015)
Chrome for Developers
Engaging with the Real World: Web Bluetooth and Physical Web (Chrome Dev Summit 2015)
Chrome for Developers
Asking for Permission: respectful, opinionated UI (Chrome Dev Summit 2015)
Chrome for Developers
Polymer - State of the Union (Chrome Dev Summit 2015)
Chrome for Developers
Building Progressive Web Apps with Polymer (Chrome Dev Summit 2015)
Chrome for Developers
Introduction to RAIL (Chrome Dev Summit 2015)
Chrome for Developers
DevTools in 2015: Authoring to the max (Chrome Dev Summit 2015)
Chrome for Developers
RAIL in the real world (Chrome Dev Summit 2015)
Chrome for Developers
#ChromeDevSummit talks are up - W00T! -- Polycast #34
Chrome for Developers
V8 Performance from the Driver's Seat (Chrome Dev Summit 2015)
Chrome for Developers
Quantify and improve real-world RAIL (Chrome Dev Summit 2015)
Chrome for Developers
Owning your performance: RAIL (Chrome Dev Summit 2015)
Chrome for Developers
HTTP/2 101 (Chrome Dev Summit 2015)
Chrome for Developers
Leadership Panel (Chrome Dev Summit 2015)
Chrome for Developers
Build Processes, Totally Tooling Tips (S2, Ep 5)
Chrome for Developers
Accessibility (Chrome Dev Summit 2015)
Chrome for Developers
Binding to Arrays -- Polycasts #35
Chrome for Developers
HTTP2 - HTTP203
Chrome for Developers
Chrome 47: Splash Screens, requestIdleCallback and better desktop notifications (New in Chrome)
Chrome for Developers
Call For Submissions - Supercharged
Chrome for Developers
Cross Device Testing, Totally Tooling Tips (S2 Ep6)
Chrome for Developers
Testing AJAX with Web Component Tester -- Polycasts #37
Chrome for Developers
Slack: Extended Xmas Special - Supercharged
Chrome for Developers
Browser testing with Travis & Sauce Labs -- Polycasts #38
Chrome for Developers
Optimize for production with Vulcanize -- Polycasts #39
Chrome for Developers
Highlights from Chrome Dev Summit 2015
Chrome for Developers
Chrome 48: Custom buttons in notifications, DevTools Security panel, and Presentation mode
Chrome for Developers
Crisper: Protecting your Polymer app with CSP -- Polycasts #40
Chrome for Developers
How do I use Sass with Polymer? #AskPolymer -- Polycasts #41
Chrome for Developers
Colors – DevTools Tonight #0 (Pilot)
Chrome for Developers
More on: JavaScript Fundamentals
View skill →Related Reads
📰
📰
📰
📰
What AI Skills on a CV Are Actually Worth, According to the Research
Medium · AI
Why the AI Slop Backlash Is Turning Platforms Into Content Guardians
Dev.to AI
Why AI Hedge Fund Placed $400M Bet on Chip Startup Source Foundry
Dev.to AI
Brain Science: Friday, August 21
Dev.to · Thulnitha De Silva
🎓
Tutor Explanation
DeepCamp AI