 Hello, and welcome to yet another developer diary. So to this point, I've shown prototypes and explained a little bit of theory. But finally, finally, but finally, we actually get on to talking about what's been going on in the actual application code. And in this entry, I think I'm going to mostly concentrate on the server side. So firstly, I suppose I need to acknowledge that a lot of this code really came from Serma. If you've not seen our supercharged episode where he talked about server side rendering, definitely watch that. It was a live stream where he took about an hour or so and built a relatively straightforward handlebars based, express based, with caching headers, server side rendering thingy setup. And I guess, yeah, a lot of this is sort of the ideas anyway have been picked up from there about how to do some of the cachings and so on. And it was also Serma who told me about express sub apps or express apps that you can actually have lots of them. But more of that in a moment because, well, there's code to look at. So let's have a dive in and see what's there. So this is actually the server as it runs today, which largely involves getting a copy of Express, making an app to kind of wrap everything else. And I'm running all my stuff on the Flex containers in Google's App Engine. So what you can do there is you can boot up a container which runs Node. It's great. It's like that. And then it wraps it in the auto scaling, load balancing stuff. It's really, really quite handy for all of this. But it passes in the port as part of the environment variable. So we basically pick that up. And that's what we run on, whatever it tells us to run on. Beyond that, there's some middleware. And I'll come back to some of this in a moment. I have also got Passport enabled, which is a way to do a wharf if you need to do it. And I'm not sure if I'm going to or not, whether I'll have an admin area or whether I'll have a place where people can actually log in so they can see their own what they've rated or whatever. I'm not sure yet, but I've put it in here just for now in case I need it. But the interesting ones actually kick in below. So there is an app here for static. So anything that begins slash static, I hand off to this app, which is under apps statics. Let me have a quick look under there. And this is actually relatively straightforward, this one. It's basically going to call express dot static with a path and the ops. And the ops is that we want anything that comes from slash static to have an age of one year on it. So it will expire in one year, not a moment sooner, apparently. But that's the idea. We're going to say anything that begins slash static, grab it from there. In this case, it actually goes to the client folder, which is up here, and grabs it from there. Come back to that, I suspect, in a little bit. So anything that begins slash static, which is like images, the manifest, so on and so forth, go and grab those from there. The authentication one, I'm not going to get into that right now. That's the stuff that would use passport because I'm not sure if it's actually going to survive if I actually need it or not. There isn't a lot of point in me just showing that just yet. If I do do anything that requires it, I'll come back and explain that. It's mostly placeholder, which is the same with the admin. It's just me kind of testing the auth stuff. I'll tell you what, we'll jump over the service worker one and we'll come back to it in a bit. Most of the app is actually served through this dynamic one, this dynamic app. So let me show you around that a little bit. So this is not dissimilar to the static one, except it's way, way bigger. It's its own Express app, which I call dynamic. I'm using Adaro, Adaro. This is the problem with reading names online. You never know how to pronounce them and then you have to say them out loud and there's a good chance that you're going to look like an idiot. I don't need much help to look like an idiot, just so you know. Glad we had this chat. Anyway, I'm using, I'm going to say Adaro, I think. And if it's wrong, oh well. And what that does is it wraps DustJS. So DustJS is an alternative to handlebars or .js, any of those, really. I wanted to give it a go because it supports promises and streams, as I understand it. So that you can, in theory at least, if you want to make your templates build an async. So if you need to do something which requires a little bit of async work, then you're not blocking forever while that happens. All the same, it seemed like an interesting thing to go and play with, so that's what I'm doing. In order to make it work in Node though, you need a wrapper around DustJS, and that's what Adaro is. Then we have a bunch of kind of setup stuff, really, which gets me things that I need about reading my video library, information about the videos that I've got, information about the actual package itself because I use things like the version number in the package, Jason, to stamp certain files to make sure that that all works. I have a bunch of helpers, which again, we can come back to, which are, they're helpers to help me with the templates that DustJS is gonna create. Finally, we have a little bit of setup here for the actual default view, like what the title is gonna be the page, what scripts we need, and so on. Then we step into the actual config of the engine where we can say, right, create a DustEngine, set up the views to use the view path, and also anything that comes from the dynamic side is gonna be HTML, and therefore, I don't want it to cache at all. So if you remember the stuff in slash static had a one-year expiry, stuff from dynamic, I want it to expire immediately. I never want it to be cached, because what we're gonna do, I call it cache and hash. You could do caching, grab, hashing, grab, caching, hashing, grab, any of the above, whatever you like, but I call it caching and hashing, and this is something that I definitely got from Surma, so we'll talk about that more in a moment, but the idea is, first of all, anything that's HTML, don't cache that. Anything that is from slash static, definitely cache that and cache it for a year. Right, so anything that's, let's talk about, well, this is one of the roots in it, the home page. We grab the default view options, we add in the things that we need to add specifically for that view, which is the featured video, which are the newest video, any things that we want in lines, like the JavaScript and the CSS, any particular scripts that we want to add to that, and then we finally just call dot render against it with the template that we've got, which is home, and that's it, it will basically render that out and send that back to the client. Works just great. Okay, let's talk more about the cache and hash stuff. The idea is that if you have an HTML file with paths to say the manifest or the JavaScript or the CSS, and any of those change, you need to flag that to the browser, because you've said anything that comes from slash static like your JavaScript, like your CSS, like your manifest, they should be cached for a year. So what you need to do is you need to do something probably to the file name, that's what most of us do. We put a revision into the file name so that you can cache that revision for a year, but if I change the HTML, or if I change the files, the HTML will get a new revision in there for that particular file. So let me show you what I actually mean. Let me bring up the browser, wrong browser. Let me switch across to the correct browser. So I'm running the site on 8080 at the moment. Ta-da. And let me show you, here's a great one here. Yeah, this is ideal, the manifest here. You can see that we've got this manifest. And then this long string here.json. Well, how are we doing that? Let me show you here. This is one of the middlewares that I mentioned earlier. Or is it a helper? Or is it a helper? It's a helper. Sorry, it's one of the helpers, which we've registered up here. This one here, a hash helper. What it does is it gets handed a path. And what it does, it opens up that file. You can see here, load the file contents, and then it creates a hash from the file contents, by making a shell 256, writing the file data in there and asking for a hex dump out the other side, which is 64 hexadecimal digits long. And we use that, and we replace the file name. So if it was, you can see here, let me actually bring, let me grab, let me show you this. La, la, la. In the header, there we are. This is what it actually looks like. So I said, look, get the dist client manifest.json. And it will grab that file, look at the file contents, create the hash for that. And then it will spit back out an updated path that looks like this. Blah, all that, there we are. Now that's good and it's bad. It's good because that means this is unique. So when the manifest changes, this hash will also change, brilliant. But it's also on slash static, which means that it'll be cached for a year. So that's all good. The only thing now is when we actually make the request, this file doesn't actually exist in slash static. I mean slash static manifest.json exists, but manifest.blah, all that.json doesn't exist. So what we have on the other side is a little bit of middleware that just simply removes the hash. If it gets given a request that has 64 hexadecimal characters right next to one another A to F, 0 to 9, then it replaces those with an empty string and then passes straight through. So it's a completely silent bit of middleware that just says if you get a URL with that long hexadecimal string, remove it. And we'll now ask for slash static slash manifest.json, which means we come back to the server, we've asked the file, we're gonna get whatever the server has as the most recent value. So that's a way of keeping that all up to date. Last little bit that I'm gonna show you on the server side today is around what I've been thinking and what I've been doing to do with the service worker. There was a service worker app that was dedicated just to the service worker. Fairly similar in some ways to the dynamic one, but all it does is it totally controls the service worker only. That's the only thing that it's actually interested in. So not dissimilar in terms of setup, we've got all the kind of Adaro stuff and we've got default dust options here and so on. But what we do is you see that I've got this package reader.get version and all that's doing is it's opening up the package.json, which is, it's currently set to 1.0.0. And inside here, inside, oh, I lost it. There it is. Inside here, you can see that I render this service worker template and I pass through version. So when we look over here at, I believe it's over here, no, that's the built version, I think. Oh, no, it's here. You can see that we have the curly braces version. So that means that if I want to bump the version of the whole site and I want to invalidate my service worker, I can do that just fine, because what I'll do is I'll bump the version in the package.json and I'll deploy a new version and then on the server side, we'll generate a new, well, that version number will be passed through to the service worker. So when we next request the service worker, we'll get 1.0.1, for example, that'll be byte different to 1.0.0 and then we'll run the whole install activate process. My means, I've used it before a bunch of times now, did it in Chrome Dev Summit, done it in, I think it was voice memos I did it in, possibly even guitar tuner as well. A bunch of the stuff that I've built is really convenient to just go bump the package version and then send that out and that will cause your service worker stuff to be updated. And the other thing that it also does, or it should do, yes it does, is it makes sure that my service worker is never cached. This is a super important thing. Even though technically, I guess this might, no it doesn't live in static. But even if Express wanted to cache the service worker for a day or a week, we really don't want that. Service workers, you really want them to cache for no amount of time. And the reason is we want to be sure that if we update our service worker, that we definitely come back, the people who are connecting to us, definitely come back and get it. As it happens, even if you set the service worker to cache for more than a day, the browser will always come back after one day. I believe that's in the spec. It does mean though that if you set the caching headers to be like a year, you're gonna have to wait at least a day before any changes you make to the service worker get passed down to anybody who's already got it installed. So strong recommendation for you there. Make sure that your service worker has some kind of no caching headers, very much like the HTML. So if you make a change, it can get deployed instantly as soon as somebody hits your site, they'll go, oh, I need to get a new service worker. And if they can, they'll download, activate and install and all the rest of it, your new service worker. So there you go. All the code, as I mentioned previously, is up on GitHub. I will link to it in the notes below. So that's the server side of things. Next up, I think we should have a little bit of a chat about maybe more video stuff because that is what we're building. Don't forget you can subscribe to the channel. Don't forget you can leave comments below. Loving reading all the comments. Thank you so much for all of those. It really does make all this worthwhile because it's so nice to kind of see what you think and also to get your questions as well. So if you've got questions, definitely pop those in and I'll try and either respond to them in line or in the next video that I record. Toodle-oo! Hey, folks, thanks for watching. Don't forget that there is more content that you can find kind of over here-ish. And if you want to subscribe, there's probably a button, oh, maybe there, maybe somewhere around there. Click that if you've not done that. Brilliant!