 Yeah, but there's really no other way to do that. Like, because that's where it was very intimidating. You're activated, man. So a little bit different. So, so, so a little bit different. I built a thing. That's our faces. That's our faces. I built the HTTP 2.0.3 Progressive Web App. And this is for our podcast, because I don't know. Do you know? We do a podcast as well. Yeah, it turns out that most of the videos are actually podcasts just during the video. Don't care about the video. Don't actually, podcasts are where our hearts are. All right, we don't give or take this really. We just do this because we have to. But this is the podcast. Oh, you built a little podcast. Little podcast app, yeah. So it works offline, because it does. And you can download the episodes to work offline, right? Oh, that's neat. So what I'm going to do is, well, I'm going to go on to a slower network, because I think that's an interesting thing to do. So people can have a look at all the interesting networks we have here at Google. One of them, we have a 3G network. So this is basically our proper interconnection, but the access point just makes it bad. So we have a quick way of testing how things behave on a bad network, because that's usually quite interesting to look at. It is, yes. So, right, I'm going to download one of these episodes. Take that one. And so, it's downloading now. You'll see now. Oh, there's a mini progress bar. Look how cute. A mini, tiny progress bar. So let's set this one off as well as a shorter one. Now, this is kind of how things work on the web today, right? Yeah. It's slow, whatever, but that's fine. But here's the problem, is if this app gets closed, which if I put the phone, this is a big phone, if I put the phone in my massive pockets, then at some point, this is going to be collected from memory, because you'll be using other apps. These devices don't have as much memory as other things. So we can sort of emulate that by doing this. Yeah, this is basically a phone in a pocket, and at some point, the network goes, nope. And it might not be the whole browser, it might just be that tab's gone, and we go back in, and, eh, wait, I downloaded this. Why is it not downloaded, Jake? What did you do? Write it back to our app. And because it's the tab was in charge of doing that download. And the tab closed, and it stopped. Yeah, but there's really no other way to do that. Like, whoa, whoa, whoa, whoa, whoa, whoa, whoa. That's where. That was very intimidating. You activated it. Things have changed. So this is the progressive web app based in Canary. It looks the same. It looks the same. So there's little differences. Whoa, whoa, whoa. Look at parallax. Parallax scrolling. This is an animation worklets. I'm using all the modern things. We should link to that article that someone wrote about animation worklets in case people don't know what it's about. Yes, we should. Is that one of your articles, is it? It might be. Who knows? Excellent, brilliant. People should go and find out. It is a good article, actually. I mean, it's what I used to figure this stuff out. So I'm going to do the same thing again. Let's download, let's download these two. Brilliant. Now, some things are different. Oh, look, it's integrated, like, notifications. Integrated into notification. And we've got progress here. We've got the icon there. That's neat. I'm going to do something magic. So that's the Chrome beta one. That's the old way. And this is the Chrome Canary one. So they've gone out. Close them all. Close them. Look, it's still up there. It's still up there. And we can go back. That's neat. OK, it's still there. What is this? What are you using? This is background fetch. That's a good name. It's a fetch in the background, isn't it? Yes, it is. And so as you say, yeah, it will not just battle through things like the app closing. It will go through connection changes as well. So I'm actually going to switch networks. So that was going to cut the download. That's going to stop. And then it's going to, once it connects onto this other network, it's essentially going to resume. But it'll be able to resume from the same point it was at before. It's not lost. Provided the server supports it. Provided the server supports range requests. Good catch. Now it's going to start downloading a whole lot faster. There it goes. So we've just got one through and the next one through, because this is fast network. And those are fast networks. That's amazing. Who would have thought they're now available offline? So is it still a fetch? Like is it still just a response object for me on the code side? Well, I'm sorry. Have a look at this. So this is how you would kickstart one of those things happening. OK. And like I said, I designed this API, so be nice. No, no, be brutal. Be brutal and ask questions. All right, so this is actually main thread code. This is not service worker code yet. So you're just getting the service worker register. You're waiting for the service worker to be ready because I guess a service worker has something to do with it. Yes, it does. But you're kicking off it from the normal JavaScript. So it's hooked off a service worker registration. Now you could still do this within a service worker or a worker. This is an example from a page. But yeah, it can be done elsewhere. So you get sRU edge background fetch, fetch. Oh, it's just a new fetch call, which seems to have the same parameters just with a name at the start? It's slightly different parameters. So you're right, it's a name at the start, and then it's URLs or response request objects. And an array of these, even. An array of them, yes. And that's important because we felt like if it's a podcast, could have artwork with it, movies could be spread across thousands of files. It's true. And you want to have one semantic group of downloads. But you can cancel one. You want to cancel all the other ones. And that's something a developer shouldn't have to re-implement, I guess. Exactly. OK, that makes sense. And then the options objects, where you can give it a title. That's for the notification. Icons for the notification. And the download total is for the notification. Kinda, as well. Because if you've got. I can't figure it out. If you've got 1,000 downloads, we don't want to block on starting all 1,000 of those. I guess the notification is mandatory. Like, you're not allowed to do a background fetch without the user knowing about it. Yes. And that's why, so you can do, if you're fetching one thing, you don't need permission. The idea is it's super visible. It's in the notification tray. You can cancel it from there. So if it's multiple thing grouped into one notification, it's a bit. OK, I see that. It's the same pattern as proper downloads from a website. You can start one of those without any permission. If you try and do multiple at once, it will ask for permission. So will the download total get automatically corrected in case I provide a wrong value? No. It will be enforced. So this is one of the things we wanted with the API. If you say this is 10 megabytes and you go beyond 10 megabytes, then you get canceled. OK, what if I do give too much? If you provide a download total that's higher than what it turns out to be, the progress bar will get to 80% and then it's done and you're fine. So it's not an error. Interesting. So if you're unsure about the download total going? Be conservative in. Yes. But the idea behind this is we want to show the user, because if they look at that notification, it says this website is downloading 10 megabytes. You think I'm fine with that? You don't want them to end up actually using 500 megabytes. Yeah, because they might be on their mobile plan and not on the Wi-Fi, right? Yeah. All of these are optional. If you don't provide a download total, you get an indeterminate thing. And our idea is. Oh, but that's OK? It is OK, but the idea is like if the site's not going to tell you how much it's going to download, the user's more likely to cancel it because they're like, well, I don't know what this is doing. I'm not getting any promises. So what's the name for? For getting it later on. So you get a background fetch registration object. I don't actually have the, they didn't do a code slide for this, but you can do sw-backgroundfetch.get. You pass an ID, you get the registration back. And once you have the registration, you can start doing things like this. So wait, what is bgfetch? So that is bgfetch, this is the registration object. So it's the same deal. That is the registration. So a new fetch returns your registration object. Not like a normal fetch will return a response. This one gives you a registration object because progress is probably much more important in a long-running fetch scenario. Yes, it is. And this is like a grouped progress as well. It's for the whole thing. So you get these, it's very similar to how XHR works. But this will also give you things like .id, which is the ID you've already provided. Yeah. Things like .abort, that you can cancel it from code. Oh, that's good. Exactly, I might want to build your own UI for cancelling it. Which you have in your thing. Exactly. Can it also do upload? That's a good question. Not in Chrome right now. Because one of the biggest issues in a long-running issue is that fetch upload still doesn't have progress and you always have to go back via either XHR or do a weird second channel to the server that reports back how much has been uploaded. So I feel like this would be a good fit. Chrome's current implementation doesn't support requests with a body. But the spec does, because one of our use cases is uploading a gallery of photos. Yeah, or something like a bigger profile picture. Hit send, put the phone in your pocket, don't care. And you can set all that up when you're in airplane mode or offline and it will just figure stuff out. That's going to be interesting because I think resumable uploads are tricky. Resumable uploads are not in the spec and it's one of the things that me and a couple of engineers might look at next year. 2019, the year of resumable uploads. Yeah, maybe. So as well as progress, it's on the same registration object. You can match things. This is very simple. Meaning I can look into the record of an individual file of a group download thing. Yes, so this is me getting the podcast. It will resolve if undefined if it's not there. Then you get the response ready, which is another promise for the response, because you might not have the response yet. No, true. And the response might even fail. If you queue up 1,000 files and you match on the last one. Exactly, exactly. But this will give you an in progress response as well. Oh, neat. So the idea is as you're downloading the MP3, you could start playing it. That's not supported in Chrome, yeah. Can I add access to the streams as well? Well, the response will be the response object. So the response ready says the same as in fetch. The headers have arrived, but the body might still be in progress. Exactly. OK, that's cool. Exactly, exactly that. So this is all stuff you can do on the page. But this is what happens in a service worker. You get top level events, background fetch success. So I get to blame you for this event name. Yes, you do. I originally called it background fetched just to try and be shorter, but people said that's weird. And I can see where they're coming from. Why not bgfetch success? Oh, we've shipped now, mate. Not changing it. I've been told that as long as only one browser has it, you can still change stuff. And it's not instable yet. So this doesn't minify. It's a string. Well, it'll gzip with the other ones. Actually, they'll only be one of them. Actually, you'll have background fetch failed and background fetch abort as well as the free events you get in your service worker. I'll open an issue on the spec. Thank you for that. Thank you. So this is, you get the registration object. And it's the same that we saw before. Oh, no, that's the same. OK, cool. And this is where background fetch success, after this event, those requests and responses are gone. So it's your responsibility to put them in the cache. Exactly. So this is what I'm essentially doing here. And this is one of the things we're thinking about making a helper method for, like, put these in that cache. Yeah, I mean, we already have cache.addall. Yes, but that takes just requests. I know, but I feel it's similar helper method on a cache. Put all. Put, yeah, something. Or some kind of transfer. Yes, that is what we're thinking. That seems reasonable. Because we also think it might be difficult for browsers to do this without copying and so it transfers. So if we think along videos, we say like they can be split into multiple files and they're probably quite big. Yes. What's the story there with cache API? Because I feel like I would get worried about quotas and things. Well, if you've got it here, you're taking quota anyway. OK. So as long as we can implement this without copying, you're not doubling the quota. That's why we're thinking about introducing a transfer method to make it easier for browsers to do that shift rather than it be a copy operation. I mean, this is something you probably don't want to just easily lose because the browser needs to claim space. It'll probably be a good case to also look at persistent storage API, whatever it's called. That is what I'm using in the HTTP203 app as well. Cool. So if you add it to the home screen or bookmarked or there's been a strong signal of usage, you can ask for persistent storage and you'll get it. The thing worth just asking for and you don't get it, fine. So another part of it, and this is the last bit. Background fetch click, background fetch click. This is a bit. Oh, let me guess. When you tap on the notification? When you tap on the notification. And so again, you get the registration and you can decide what to do based on maybe how the background fetch is doing. I have never used the clients.thing to open something. I need to look into this. But this is really cool. So you get to decide how you react to a click. And apparently you're deciding what to do depending on whether the download is done or not, which is cool. Exactly. Because if it's successful, we can go to the latest podcast. If it's not successful, so this would be, if it's in progress or if it's failed, just go to the download screen. And presumably you would have an error there or something. Maybe I don't know. Oh, cool. I was just kind of making this up. But yeah. And so as a result, this is what you get for that. This kind of download system where you can just click a load of stuff. And it will just happen. And if the tab closes, if you're offline when you press these things, it will still work. You said in Canary behind a flag? It is in Canary behind a flag. And we are going to move to an origin trial for it. So the details will be different. Do you have an article on this by any chance? I have it ready to land at some point. It might have landed by the time this video comes out. You'll find out by looking in the notes. In which case there'll be a link down the, what's that bit, below the below our faces. Yeah. Also can be appreciated in this nice parallax. Oh. Yes, we'll link to an article of how to do that as well. Brilliant. We can cut out how long this is taking to connect. Oh, look. It's blazingly fast to connect. I mean, it's just an authentic experience. Is it kicking you out? There we go. Connecting to the internet. Come on. Figure it out. Figure it out. Figure it out. Come on. Hey. That's good. Right.