 Are you saying you just die overnight and you wake up one morning? Isn't that what's like this? Yes. Let's say yes. Let's say that's what it is. So offline first is a good thing. It's something. Is it though? Is it though? Yes. I tend to agree, actually. And we talk about offline first as being distinct from online first, right? Offline first means it's just do you try getting offline content first, or do you try and get it later? Yeah. That's the rule. So if you were to build something online first, the idea is you go to the network. That's just how everybody builds websites most of the time, traditionally. Yes. Well, a lot of built online only. So the online first would be if that fails, then show some content. But offline first is best because it works in more situations. So if you're doing online first, it works great when you're offline. Ask the name kind of place. Yep, exactly. It fails quickly. And then it goes for the cash content. But there's another situation that is different. And it is this, which I have been desperately trying to make an industry term. You're clining this one, right? Over and over. Over and over. I want my Ajax. Where's my? I want to be famous like the guy who invented Ajax. Who I don't know his name. My plan is ruined. There's a real problem here. Remy invented Polyphobe, right? See? I'm jealous of that one. That's a good one. That is a good one. So this is a situation where your phone thinks it has a connection, but it doesn't. Which you have all the time. Which is all the time. Especially when you're on vacation or on airports in my experience. Yeah, when you need it most. Yeah. Essentially. And the phone doesn't think it's offline. So it sits there trying to make a connection for ages, and it never gets there. And that is the problem. Especially when you know the app has the content offline, but it shows you the spinner for like 30 seconds. Like, I think I'm online, so I'm rather going to try. That's online first. That's online first. And that's stupid. So offline first, we agree. It's better. It works in more situations. But that means you are serving content from your caches first. Then you go and go, is there anything new? And sometimes. And there might be something new. There might be something new. And then, what'd you do? Well, I mean, I think we all have seen the infamous snack bar, right? This is the solution in Scrooge. The page loads. It goes off. It finds an update. I mean, meanwhile, you could be like using the app and whatever, and a little thing pops up at the bottom there and says, it's a pinch-suming app. Right. Yeah, forgot about that. And yeah, it's saying here, update available. And now, do you want to reload and lose what you've already been working on? Or do you want to ignore the fancy new features? But that could be something really good. So you're like, I'm going to reload. And as you say, you just lost all your stuff now. So that's great. This is a very common pattern. Yeah, I see it a lot. It seems to be the standard pattern currently. It's the standard pattern, especially for Apple updates, where it's also updating not just the content, but also the underlying JavaScript and CSS. Because what you got there was a full page reload. It means the browser can start from scratch. Get all the new things from the cache. Yeah, it's not trying to mix the two. Yeah, because that's the problem, right? Especially in a world where what we advocate for is hash all your styles and use HVCache as well. Then do it suddenly loading new styles while having loaded the old app shell, for example, could get you in a really iffy spot. So the only safe way to do it is with a proper reload. And this is what native apps do, right? Like, fair. I mean, they actually get killed when the app store puts in a new update. The thing that native apps can do that the web can't do yet is do all the update in the background. Yeah. So you're usually coming to the latest version. And not always. Sometimes you still get the app kill experience. And so we're going to have a look at some ways that we can improve on this. Like, what other ways are there? What improvements can we make? But I always want to caveat that in, this is not a solved problem. It's not. And it's not, when I say it's not a solved problem, it's not just the web that hasn't caught up. Go into airplane mode or Wi-Fi mode if you can find a way to do that. And just try a few native apps. It's super hard to get it wrong. Pretty much all the apps get it wrong. Yeah, you'll see so many empty screens. And it also depends on the use case. Like, some apps cannot afford to show stale data. Like, there's use cases where that is actually unacceptable. Absolutely. So what could we do better here? If we ever think about some of the problems that we actually created here, the first one is that we lost all the state. Yeah. Which we could work around because we unco-tooled the button. We could use, put it into IDB or something, right? Exactly. So you want, when you click that reload button to essentially put the user back into the same state they were, but... That's hard. But with, well, in some apps it is, some apps it isn't. It depends. It comes down to how you can store that state. Yeah, also, you might have shipped a major upgrade to your app. What if you changed your state model or you even removed or added functionality that's just incompatible with what the user was doing before? Exactly. It gets very complicated very quickly. So the simplest thing you can do is, if you've got real URLs, you're along with that. Because you're going to reload that URL and you're going to send the user to a place roughly similar to where they were before. That's true. It's not what we did here. It's not. No. Well, we would have to encode the image somehow and it just gets iffy. And so our choice there is session storage. You keep talking about it and we've never used it yet. We've never used it yet. So this is a great tool for remembering state like this. So anything you put in session storage is essentially, sessionally, essentially, associated. I've now forgotten how to speak. That's great. Good thing it's paid for. You can associate data with the tab. Which is actually really useful because another thing that we didn't even mention, if you have a tab and you want to store some state so you can do the reload, what if two tabs do that at the same time? Exactly. Like they would just override each other. What would happen? Because on the web, the same app can be opened multiple times, another problem that native doesn't have. Yes. Yes. So if you were to use normal local storage or index DB or something like that, if you use it naively, two tabs store to the same place, blast in wins, they refresh and you get two tabs going to the same place. Not unsolvable but hard. Exactly. Session store sorts that out for free. You can only store text. Bad. So that was. And it's main thread and it's synchronous, isn't it? Yes. Yeah. I mean synchronous. You're only using it very quickly. What you do as soon as the user says, yes, I want this update. In this use case, it will be fine. You put the stuff into session storage. You then reload the page as you would. But then the first thing your app does when it wakes up is it's like, oh, do I have to turn the speaker off? Exactly that. And you have to turn your speakers off because it does make that noise every time. And then you can use that to put your app back into the state that it was, like JSON decode it or whatever and make that your state object. Which, for an image, would actually be quite cumbersome yet again. Yes, because you would hit the session storage limit very quickly. But it's these two little things that would really improve what we're doing with Squoosh. Another example, do you recognize this? Oh, Jake, this is one of the other apps that you build in your lifetime and you keep bringing up. Yep, that's it. I spent most of my career making websites that have checkered backgrounds. Probably the first one that, I mean, I guess, in a way, it still has a checkered. It's still very grid based, I suppose. I make grids, that's what I do. That's how I make my money. This site, I went for basically the same model as Squoosh. In that it has the banner and says, got an update for you there. Do you want it? But there's an exception to the rule. If it finds out about that update, while it is still on the screen and the user hasn't interacted yet, it just reloads. Because this is how the app starts. So it's basically a non-visual change. A non-visual change. So as far as the user sees the page reloads, I also added this sort of telling the user. Look at you, you're such a nice person. Well, I think this, I think I've done this the wrong way around. And this is something I've been thinking about recently is when the little banner comes up, especially if it ends up in a banner situation, and says, there's an update available, do you want it? I'm like, I don't know, what's in the box, right? Tell me what's in the box. Do I want it? Because if it's like, it's a bug fix to the feature you don't use. Fixes for the odd browser. Fixes for the odd browser that you're not on. Which would be a problem that would still be a service worker update. So it could be a fix that you literally will not benefit from at all. So letting, you know, I think there's an opportunity there to try and sell the user on like, yeah, you want to click this button. You want to click it. It's going to roll you through your life. In this case, you tell me about it after I clicked it. Yes, I'll go say, I got the wrong way around. Chill out. But it's actually not too bad in this situation because the user didn't have to click anything. True. I get away with this here because the long page here is quite boring. A lot of free space to just show a changelog. And also nothing moving. Yeah, any animation will basically disrupt the illusion of a transparent reload. Because you would see that reload. And because it all goes through a service worker, the reload is really fast. But yes, if there was an animation or something there, you would see that stop, start. Which takes us to another website. Once again, I'm going to purely just talk about things that I had some involvement on. But this is one that you had an involvement in. Yeah, I'm OK with this. You're fine with this? Yeah, I like this one a lot. So we built a game. We built a game. It's like Minesweeper, essentially. And this is it. But it came to the bit where it did the service work a bit. And it came to the bit to handle updates. And I was just- You went through a few iterations on this. We had different things we tried out. Well, I started bringing in the code to do the same thing as Squoosh. There's an update available. And I just found myself feeling really depressed about the whole thing. This is a horrible situation. And I knew I couldn't do the same thing with SVG OMG because you would- This lovely background that you made and this lovely intro that I made. Anyway, can't do the reload thing because the animations didn't want to do the banner thing because it's horrible. Right. So I actually went back to something that- Well, I've seen sites like Flipkart do this. And it was also something I did with Lanyard back in the day which is find an opportunity to reload when you- Yeah. Because the start page is just this. If you can't reload here because they might already be configuring, maybe it's something right on the line. And so when you press the start button, if there is an update available, rather than just launching into the game which you usually do, it does the session storage trick. But it doesn't put a lot of data in there. All it puts in is the type of game that's about to start. That's all neat because that's all the input has been given so far. The game hasn't been generated yet. So we don't need to store the entire field. We can just say, this user wants to play a game in easy mode. Yep. And then it reloads the page and- Which causes the new game logic if there is new game logic to be loaded. And it will find that, yeah, it'll go, oh, there's a thing in session storage. I'm just going to start a game. Yeah. And here's what that looks like. So you actually saw a reload there. It does a bit more loading up front because we're generating the sprites. Yes. And normally it would pull those out of a cache but it's a new version. So we need to build new ones. And it loads. And it's not too bad. No. It's not too bad. Look at that. You really, yeah. You did the animation work, well done. But it means that you can see, it kind of gives the game away a little bit when you see a URL box. We'll see this start to spin very briefly. But it's loading from a service work because it's really fast. It's really fast enough, yeah. But it's even less noticeable. Only when you know it, you actually notice it. I think- Yes. I don't think many players know what's happening. Well, they do now, if they're watching this. How do they do that? That's the whole point of this video. Jake, do you don't realize we have some viewers? Not many. Some, though. A few loyal ones. A few loyal viewers. Shout out. I really like this pattern, by the way. I think it's a really nice one, which probably doesn't apply to things like a blog, but every kind of app could probably have a situation where a click could be turned into a reload and then navigate to where you wanted to go. Yes. And as I say, I've seen content sites do this where you click a link. It's very possibly going to do a navigation anyway, but it makes the service worker update at the same time. You're right, though. Content site's slightly different. The Twitter model is something they will say, there's new content, do you want to see it? It's still a click away, but it's not a full page reload away. Something like a chat app. If you scroll to the bottom, you just add the new stuff and you scroll to it. Pretty much. That's easy. I've been thinking a little bit about what we would do for something that is a bit more contenty. So this is a blog post, essentially. Yeah. And so it's basically, now a user went to the site, started reading the blog post, but we just published a little typo fix or maybe add a whole paragraph of new important information. Yes. What do you do? What do you do? And this is where I think, well, you started mentioning it earlier, like this, you could do different things depending on the age of the content, the type of the content. And you could build something like smart or dumb. Like you could do something like, oh, if the content that I'm replacing is not on screen, you could go in and actually inject it. That is the dream, right? Like you're prepared to get to that much effort to realize that the user is off the screen and just sneakily update it. But I would say, with a blog post, I think a model I want to try, I haven't actually tried this, but I think it's a workable pattern, is go somewhere between online first and offline first. Where you would deliver straight away the shell of the page, so the bar across the top there and get ready to stream the rest of the content in. And then if that hasn't happened for a second and a half, if you haven't got any new data, then that's your cue to show something like, this is taking a while. Do you want to look at the cached data? And you could take that opportunity and say how old the cached data is so the user can make an informed decision. Then the last thing I built, I actually delivered from cache, but if the new content was completely done downloading within like 500 milliseconds of the page being on screen, I would just swap it out. Just swap it. Because I felt like the user wouldn't have engaged with the page enough to have settled into a scroll position. It's not a perfect experience. It would probably flicker because it might have already scrolled, maybe not. It's got the same problem as web fonts, right? That you have the possibility of content moving around. Like you say, if it's early enough, it might not be a problem. But if you give the user the opportunity to decide, yeah, that could be a model worth going for. And that way you're not just waiting until the content fails to load before you let the user at the content already on the device. You give them the option. The other way is to essentially go back to the banner thing. I'll have something across the top saying, this is outdated. This is outdated. This is the date of it. Which again, then always I wonder, oh, what's the change? I want to know what you messed up. Oh, yeah. I don't want to reload this. This is the wrong version. What was your mistake? Duplicate tab, update, and then put both side by side. Visual differences. What's the factual difference? But yeah, with a blog post, it's probably fine to let the user look at stale content. But yeah, if you're a new site, if you're displaying like life and death information, like that is when you're saying like, if I'm reading your blog post and it's 10 minutes old, not a problem. Probably fine. If you're reading one of my blog posts, it's 10 minutes old. You are missing out on some serious spelling corrections, which especially if I've just published, because I will go through and correct that a lot. But it's just spelling. Whereas if it's a new story that's 10 minutes old, that could be really serious. But the web, you know, you get the tools to look at that. You can get to make that decision. Yeah, if it's just been a quick refresh. We definitely have all the tools to build all these different patterns. It's just a matter of actually building them. So that's basically what I wanted to talk about. It's, as I said, there's no kind of like... That's the bottom line here really, is there? There's some real examples there. But it's something that I want to see the web exploring more and I want to explore on the web. Like, I feel that we've got some good patterns for apps. I would like to see it explored a bit more for content. Agreed, let's do that. I had this like big, long animation that we've been playing around. And I was really proud of it because I did it on a plane. And then when I presented to people, it was like, let's go from 11 to like 2. It's a bit, but I was really proud of it at the time. So my heart was ripped out.