 MediaTemple sponsors the event. They've provided the pizza and beer, so everyone put your hands together for MediaTemple. MediaTemple is not actually here in the room, so they're not like monitoring the applause, but it's just a vlog just here. They do a lot of cool stuff for us, and for like J4, they're like sponsoring these events, which is awesome. So, yeah, I guess one last thing, we are hiring, so we have a section on the website about that. I don't remember the exact URL. Work app? Work app. Yeah, something like one app.woku.com, whatever. So if you know someone who's interested in it, or you want to do some kick-ass open-source, JavaScript, Python, stuff like that. So anyways, Tim is going to talk now about some cool templating stuff, and so I'll let him get to it, and just know that we've got another one scheduled for a month now, not even a month now, March 2nd, on the choir, JS, and script loading and stuff, so sign up for that. It'll be really awesome. More pizza and beer. So, take it away, Tim. Before I get started, I see a lot of people on laptops here. If you click this away, you may want to bring it back because it's going to be a wild ride. If you go to this web address right here, tops.tabvilker.com, and actually you can just get this part. I made this beautiful website here. It's very functional, but it has the source for my demos, which will go to the demo where I just push all of this content. But if you click Slides, it'll bring you to exactly what I'll be talking about. And you'll notice this button right here, which just turns things off. It's on by default, but I'll be synchronizing all slides as I present using Node.js. So, kind of a fun little... What is the URL? Oh, I'm sorry. Yeah, tops.tabvilker.com. Okay, the developer. I'll just leave it there. Is that BrowserTab or SodaTab? Sorry? Is that BrowserTab or SodaTab? SodaTab. BrowserTab. No, that's just my initials. That's not a good reason. That was obvious to me, but it's not their fault. So, like I mentioned, it's on GitHub, so all the source code. If there's some parts I would like to get it to that may or may not get it to, so just feel free to browse GitHub. Awesome. Browsing my phone, I'll be using my phone as the control panel for my... This is the first time I think anybody has ever done this, so we'll see if this even is a good idea. So, basically, what I do is I swipe my finger, and this will adjust the slides. Cool. So, yeah, I'm Tim Branden. I work at Boku. I'm a software engineer. I went to school at RIT in Manchester, New York. I graduated in 2009. And, yeah, I think I've never worked here. I do client-side development with jQuery, but I also am very adamant about the progression of JavaScript. So, what you'll see here is some stuff that's pure JavaScript in Node.js, and some stuff that's jQuery. This is my favorite library. And I do service-side development here in Django, and I've been running some stuff with Python, and I've been focusing my native development with Lua, which is very similar to Python and JavaScript, so if you haven't heard of it, check out. And L-O-V-M is a low-level virtual machine, which just makes it very, very fast. So, my motivation for this talk, as you can tell, is probably very big on speed. So, what's interesting is slow, especially on older devices, and part of that reason is that you're downloading a lot of resources. You're getting a server. Every time you make and request with a link or a form, it's pulling a new page. If you're using a single-page app, it's a pain in the butt to make it act like a real website. You can't often bookmark URLs, and when you click around with links, you're often updating an hashtag, updating a symmetric URL, and if you bookmark and you go back to it again, it just doesn't work correctly. So, if you want to do search and optimization, you're not getting the real page. You're getting a landing page that has some JavaScript, and then it checks the hashtag, and then it reacts. Caching, that's another primary focus of mine, because that deals very much with performance, not downloading something you've already downloaded. And one of the biggest issues currently with servers in caching is that you cache a full page. We don't have any notion of content versus a layout. So, if your content changes with your layout, it stays the same, which most likely it will. Why are you re-downloading the layout again? So, templating really is the only thing that you can use that separates both the layout from your content and allows you to conditionally cache. So, I'll be talking about that later on. And lastly, I think it's really cool that you can use the same templates and the exact same context objects, your data on the server and the client. I've heard a lot of people talking about this. In theory, it's very easy. And people talk about it, but nobody really shows how you can do it. So, what I'm going to go through is the very complicated and complicated process of actually getting this to work. But what you see is it's kind of cool to actually see it work. To get started, I'll talk about the terminology and concepts of how people can start to talk. I may miss a few things, but just raise your hand if you don't understand something I'm talking about. And I'll go over the pros and cons of this. There were a lot of cons, whether it's also a lot of pros. And the availability at the end is just the different template engines. We're going to be focusing on jQuery templates, but that's not the only one out there, so I just want to make it useful. Okay, so the first three template terminology are template context and render. These are universal between basically every single template engine. So a template is basically a way that you can enhance your data in some meaningful way. There are place folders that you would set up in your template that then get mapped to your context object, which is your data. So the easiest way to think about that is context is your data, template is your presentation layer. And then render what's the two together and makes magic for HTML or whatever. Because your template does not have to be marco, that can be script, that can be anything. It's just rendered to my text and then evaluated at some point. Progressive enhancement is a common term that's used. And in this instance, it means that we're using raw web pages that just have no functionality out of and no job script. We're adding job script to them when applicable to enhance them and make them just more pleasant to use. And headers and conditional caching are two huge terms that I'll be using because unfortunately there's no way to cache specific context without using additional caching in headers. I'll talk about some HTML5 something. Almost sounds like it could work, but it doesn't. So you see where I'm going. Headers, if you're not familiar with them, percent before your web page content, you can add whatever you want in there. As long as you don't overwrite something on the server's expected, that's free for you to put whatever you want. So you can actually send down to the server. And this is how entity tags work. This is built into virtually every major server that I'm encountering that doesn't accept any tags off the bat are engine apps. But I believe that you can get that working as well. But what entity tags are, and you'll see they're very easy to implement if you do raw code, like they're ridiculously easy. They're basically a unique identifier. So I'm using what's called a CRC. It basically goes to the data and decides a random representation. That's not random. A mathematical representation of that data tends to be unique towards it. I'm going to start talking about it. There are collisions that can happen. It's like 1 in 3 billion, so I want to say that it's not an issue. So just be aware that you could have a collision, but quite not going to happen. All right, this is what headers look like. The first line is the only one that's not a key-value pair, and that just tells you the status code, which in this case is 200k. That's also what you see here, 200 or 200k. Four forwards and then a popular one. And there you go. You have your key-value pairs. And this is all invisible to you. Normally, you can see them. I can pull up enough browsers for it, but I guess it's kind of important just how you actually see them. So on this page right here. So this will show you all the request headers which you sent to the server, and then all the headers that come back from the server. And it's interesting to note that in an ETag, you sent an ETag to the server, but when the server actually gets it, it's not ETag anymore. It's if none matches itself. But it is interesting to note that what you sent may not be able to server actually sees. That's what you do with the server. With an example, just so that you can see what exactly a... Does that header do built-in commands or is that a plugin? That's actually Chromium Tools. You can control-shift-I, bring that up. Yeah, it's very, very useful. Can everybody see that? Is that legible, or actually, I don't see it. And is that yieldable today? Yeah. So the script type here, this is just a convention that jQuery templates has. This illustrates the point that type is irrelevant as long as it's not JavaScript or just a term for it. So long as it's not something that the browser can interpret as a client-side script, this will not be an element of it. This right here is just my placeholder. It's a variable that when I said you would enhance your data with, I can put anything around it. That's like an ETag. Your context here. This is where I actually have the value for that. And the context can come from anywhere. It can come from a database. So it just needs to be in an adjacent format or anything on your server that can actually parse it as a key value. We have the template getting pulled in right here. jQuery templates actually maps one to one to IDs. So we have an ID, hello, we're actually like I'm just pulling a jQuery thing right here. And then applying it into the template, but this is where jQuery templates is special. We'll just take out a jQuery object. If it's a template, it will render it with the context. So this is what we did. And something here. Right here. And from that, this is one of the little programs here. Okay, so the possibilities. Is that good? So the pros of this are we're opening up new possibilities for performing web pages. We can now cache things individually using templates that we can fetch by Ajax and context objects that we fetch by Ajax. So since we're making separate requests for these, we can cache them separately. So the first time we make these requests, we're making multiple requests. If you go back to these pages, they serve 304s, which is the non-plotified status. When we saw the 200, that was okay. That means that, oh, we're sending a whole bunch of data. It's a content length that knows what to expect. Let's say our web browser has a little farmer's mark. So we sent back a 304, which I'm going to show on the server side. It's just a simple int statement. If these entity tags match, what does that change? And if they haven't, if they don't match, then we send back the full content. So, and that's actually what the Mule's cache is. And then the techniques that I'm going to show, they're generic amounts of work including Mule's applications. And I'm hoping that what I show afterwards with how to implement Node, you'll be able to start implementing this into your own websites if you want to experiment with it without having to take down your whole implementation and mess with a whole bunch of stuff. It's just, it's much simpler when you don't have to take down your existing implementation. It gradually works something in. And there's no cons. So, I mean, this is fantastic. You can actually get something that just has no issues. But, of course, they always have issues. So, browsers are limited with what they can do. They don't have house system access. They have a lot of things that just, you just cannot do. They're just, their client side, that server side. So when you have a template implementation that relies on a lot of functionality and you're bringing down to the client side, stuff works. It just doesn't work. Luckily with jQuery templates, it's built for the client side, so we may not experience any of those issues. But, for whatever reason, you cannot use jQuery templates on your server side. You're looking at other implementations. This may be a big deal. And that's basically what the next one is as well. You need to stick with what's available. Frameworks can complicate things. So here's just like WordPress, Django. If you're using a third-party framework on your server side, it may make it a pain in the butt to be able to get at the templates that you created. Django especially does not allow any sort of mechanism for getting at a raw template. In order to get that raw template, you have to render a blank context object and then get that resulting markup from it and then send that to the server. Luckily I was able to find a way around that being able to actually get at that template. But a lot of times frameworks don't need you stepping out of the bounds. And really what I'm going to be showing is stepping out of the bounds of an average web application. And the last bit, unfortunately, is that the techniques don't work in every single browser. So we have to take a choose with our progressive enhancement. And unfortunately, the two big ones are Firefox 3.6, which is currently stable, and IE8, which is stable, do not support session statement. So you have, if you want to use that in these browsers, you have to upgrade to Firefox 4 and IE9. Okay, these are the various template engines that I have found that work in JavaScript. And the results that I have found for whether or not they work on the server. EJS was created by the junior consulting group that did JavaScript MBC. That's within JavaScript MBC. And that both has a JavaScript server counterpart and a, obviously, client side. Sam will close your templates with Google, which advertises the whole unification of their templating code that can run on the server as well as the client. JQuery templates. I put notes in there that it's still in beta because it's still in beta, so you're using beta software when you bring this in. So it may not serve the production ready. Certainly, probably not that battle-tested. Closure templates are battle-tested. They're actually used to power Gmail. Mustache, I had to bring this up because it runs on Amazon. So if you want a templating engine that will work with your server-side language and JavaScript, Mustache is just, that's it. Jade is another templating engine that replaced, I believe, Hamel.js. And they have client-side engines that was running and it worked, I guess, fairly well enough that they listed it in GitHub. But recently I put a link in here and pulled it from there to develop because Jade does stuff on the server that can't be reproduced on the client-side. So there's no point in actually running this thing. And the same is with Django. My website, TapDeveloper, would be bitchingly fast if it wasn't for the fact that it uses Django templates on the server. And the only implementation is in Dojo for the client and it's for a .96 release, which is a major version, several minor versions behind. So I wouldn't be able to use a lot of the cool stuff that I have to pull in a ton of Dojo templates. So jQuery templates is really awesome with Node because you don't have to do all that stuff. It's just there's an implementation in Node and there's an implementation on the client-side and you're working. And what I'm going to be calling what I'm talking about is a hybrid experience because we're using the client-side and the server-side together in a synergistic harmony. If I had a synergistic harmony with each other. But yeah, there's benefits. There's negatives for the client and the server. But when we put them together, they kind of, they work really well. And I'll talk about implementing those features. So the client-side. The client-side is extremely fast. It can pull things with AJAX, it can cache things beautifully. And it can now alter the browser session state, which is an incredible win for us because when you're using, and I can actually pull an example of a website, I'm using push state. If you watch the URL, this is all using push state, and it changes the URL up top. So I can bookmark this, and presumably the rendering and the server when I go back to this, because I can cancel this URL as the end to enter. And I'm on the page, and it worked. What browsers support that? Push state is currently in Firefox 4. I'm not only the latest WebKit. So Safari, Chrome, Opera, actually supports this one. It's an experience because it's lightning-quick. It's just fetching what needs to, what changed. It's not fetching the page, and then rendering that small part. It's only taking what it needs, putting it into the page, updating the URL to work like that. And I'm going to go into a little bit more detail on how push state works. So yeah, the only fetch we can do with AJAX on the client-side, and alter the URL, and you can render things incredibly fast. It doesn't need to actually send that data to you. And I need to stress, because you may try something and find why doesn't this work. It's just ruined my whole implementation. I had this working perfectly on the server. You just can't do certain things. And it's not going to work all right. The two things, two elements and events that I can think of on the client-side that will move you to another page are forms and anchor tags. So these are the two things that are the most important to hijack. And I've created a hijack.js file, which I'll be showing. I'm storing forms for the demo just to make things a little bit easier to understand. And yeah, this is for some enhancement. We will look for links that when push state is available, we'll be attaching ourselves to the links. When you click them, it'll figure out where you're trying to go, trying to do. Fetch the template, the context, and then render it on the client-side. I think we're near enough. Okay, so the push state. My favorite part of this implementation right now is that I'm going to change the URL. So this now makes my dream come true. We can render stuff on the server, set it down, use the same URL, and render it on the client-side. And the way this works is there's a session state, so you can think of it as there's one point in time of the browser. This is where we currently are. There's a replace state that will replace what's currently going on. You can think of it as just an object and a path that represent it, and both are more optional. There's a path that represents your state that you're currently on on the page. They're both optional, but you need one or the other to really make any use of this. And one of the major reasons why you would want to use state is that there's no way to know what URL you've just pushed into the state unless you save that in the object. And I'll explain, actually, right now how a push state works, so you can see what I'm talking about. So we have a history object and I'm passing into a immediately invoked function closure, whatever function expression. And we have an event here on pop state which I'll get into. But really what's important is push state here. First parameter is an accession object. You're familiar with the JavaScript object, so you just key that up there inside. And I have hwrap, which is what I'm actually pushing to the address bar which I will show you. And text right here is just some text that is inside of these anchor tags so I can actually change stuff. Now when you hit back or when you first visit a page, pop state is triggered, so I check first to see if the state object is on the event and the state object directly corresponds to this object right down here. And if it doesn't exist then I know that we haven't pushed anything in and I just want to make the text the, I'm going to store a copy of the text of the current page. And this is one major limitation of using push state. When you first visit a page, it's just rendering on market. There's nothing dynamic that you've done. There's no way to, when you get back to this page you know what that state was at that point in time. So you really have to keep, take careful note of stuff that you might be changing with push state and save a copy of the very first page that you go to. And I'll show that again when we go that we first hit a page, if you're using push state you need to save the initial state. And then once you have the state you can start making changes. This is a link that I'm finding to click to, overriding it, pushing it to save the and then the second parameter is title. It's not really used in any browsers. I haven't seen it do anything yet. And then the last one is href. This is what actually makes the magic happen. If the title work it would be like when you go back to the next button and see the drop down and show them that. Does anything show there? We'll take a look. So we're on current page A and this is what I have to say. I have to say, oh we are on page A when we first come to this page. That way when we actually get back to it there's something to replace. Like here I'm now setting an object I hope this makes sense. But now I'm doing something dynamic and I have something to set into the history push state. I'm changing the URL at the top there. That's really great. And we have back button support. But this is very kind of complicated. It does work in the main example. So if anybody wants to look at that, figure out why that's not working. You can tell that that's why this part is kind of complicated. So that's push state, but you can see how you can push something into it by just calling this push state at the down there and that's on the history object which lies on the global object. That's just any kind of data that you want to represent for that current point in time. And push state will actually add a new entry into your browser. Replace state will replace the current one. I haven't really seen a use for that yet but I'm sure there will be. So you watch what on-cop states when you first go to the page and put somebody to the back for a follow-up. Hash change to local storage are kind of interesting because they both do things not ideally. So you have a hash and Google search does this. So when you search for something in Google it actually saves your full state in a hash. You copy it and go back to it. Server doesn't know the client side of this. The client side has to have jobs that picks up that hash and then finds the right information to show to. And local storage has the opposite problem. It has no idea what's going on in the server. So if you start storing your context objects in your templates in local storage you have to make a request to the server anyway to figure out what the data is and the HTTP is caching that's already built in. Which I believe I'm getting to once we get to the server. Great, server side stuff. Okay, server side is awesome because any device that influence HTTP and HTML will get the content from it. It doesn't need JavaScript, it doesn't need anything like that. So if you have a very static phone that doesn't have any kind of cool functionality you still get to see something and you see exactly what you should be seeing. So one thing I want to stress is that if you have not heard to build your website on the ground using progressive enhancement making sure it works without any JavaScript functionally. You get the right content and it works. It doesn't have to look great but it does what it needs to do. And then from there you can now enhance it and make it faster and faster. And conditional caching can only happen on server if you need to have a server side. So I'm sorry if you're not a server guru you can't figure this stuff out maybe you can look at my example code and try and get a demo working and there's no other way. And it provides instant automatic semantic URLs. That's really nice so if someone bookmarks your page and they go back to it they're getting your page because that's what the server is doing. It's outputting the HTML to work on. Everything is working. And one thing I've noticed while doing this is it enforces good coding practice. Let's say you want to go to a third party service well your context object never comes from anywhere but your server. So your server is going out making that request. So let's say Twitter goes down and you're caching all the Twitter requests coming in and Twitter goes down and you're supposed to have your tweet shown. Everything is going to work fine. You're not relying on a third party you're relying on your server. That's a great side of the project. The drawbacks are without JavaScript changing pages make a full page refresh every single time and unless you have small content you're going to see a noticeable redraw. I've seen a few pages now where I can't even tell the difference so that's really great. It's not for everybody to be using these techniques and everything is working perfectly already. Maybe you don't need this. Your pages are small and fast enough. My tab developer is already under 20, 30 milliseconds for most requests. So the actual the total is 150 milliseconds to load my page. I really don't need to have any more performance benefits. It would be nice, but you won't really notice the difference. Unless you're on mobile device, mobile device is made worse. And you can only cache at a server level unless you have a hindsight component. Especially separate components that can now be separately cached. You're always pulling down one page from the server. And that's the only thing you can do to cache. So if your template changes, the whole thing's coming back down. Putting it out. Your data changes, the whole thing's coming down. Even your template, even though you haven't changed. So that's kind of a bummer. And, of course, server calculation. And this is one little note that I put. It's interesting that you can only do conditional caching on the server. And yet, without the client all you can do is pull page. This is where that whole harmony comes in. You just need both of them to make something that works right. Okay, so I'm NodeJS and I only have one word for you and that is, you know, they are all over the place and NodeJS is just fantastic. So, I'm using NodeJS right now and I can just control everybody who's watching this right now. I should have just seen corner five and it's distributed. So NodeJS is awesome. It's fast, it can handle a ton of stuff. It's Jumbo script. So everybody here who goes jQuery should probably be able to read what I'm ready and not have any kind of confusion. It's not probably a thumbs up review, it's what you already have. It already has a jQuery template again. So if you're familiar with jQuery templates if you're getting used to it and you know how these actually work it'll be easy for you to look at code that's written in NodeJS. Setting up the environment is incredibly easy. So in NodeJS you run .slash configure type in make then you type in make install very very simple there's plenty of instructions online on how to do that and PM is even easier for those who have trouble with three steps or four steps it's one step it's one line of code you paste in your terminal it's done install and then as you can see the rest of the three that I'm using in my example are all one line installs. The last two are optional and I would recommend grap them anyway It's been fantastic for me to work with. I'm using it mainly for routing, but there's a ton of the wear and coolness that can be looked at. And CRC is what I mentioned before. Anyone that's familiar with MD5? It's just a hashing algorithm. In this case, it's just going through the data and it's running it through some maths and it comes up with a number up there, and that represents that. And running a basic node app, I believe I have a demo for that if I don't, I have... I pulled this right off of the node website. I forget it's the easiest for people to be able to see how to actually run the Hello World. So this is the Hello World folder right between node.js. Boom. Alright, we're done. Okay, we have a web server that can scale and it's fantastic. But really, it's awesome that... It's awesome to say Hello World. So that's what it's all about. So, fantastic, right? But yeah, the code is awesome. The code that we saw is just, you know, it's a few lines. Create HTTP, create server, write headers. And actually Express normalizes a lot of this for us, so it's almost a kicker anyway. It makes dealing with nodes already easy implementation even easier. So that was basic coding. So the goals for the server implementation that I'm doing here is that we can fetch templates and context based on a URL. I'm going to go into depth a little bit on using headers to be able to fetch what you want, whether it's a context or a template based on a URL. And I'm going to tell you now that that was the worst idea I've ever had. It sounded good in theory, but there are some major problems with that, which I'll get into. I want to be able to render templates with the context, and I want to be able to cache based on the current version of the data. Okay, so the fetch header is what I was just talking about. This was some crazy idea that I had. I don't know what I was going on in my head, but I thought this would be awesome to be able to make one of those custom headers and make my own called x-patch, where when I click on the link, so let's take some link to some arbitrary page in your setup that you have a template associated with and a context associated with. When you click it, it would custom set it using jQuery, using the before send in Ajax, so you can set an actual header. And I would just set, okay, while I'm clicking it, I need to fetch a template and a context. So set those in there and x-patch would just have that being the key and then the value being whether or not it's a context or a template. And the problem with this is the way that web browsers cache, they cache based on the full URL. So I'm still making that actual URL request to the server. So if I'm going to page 1.html, there's no query string, there's nothing to differentiate it. Only the headers that are invisible. So the browser was caching the same, only one thing. And there's three versions of that file. There's the full version rendered by the server. There's the context, and there's the template. So while this sounded great, it was just today while I was going through it and I'm like, why is nothing setting back in 304? I realized that nothing was working as that's why. It was making a new empty tag for each part of this. And I was all excited when I first got off of this because I was like, oh, wow, so it was an implement jQuery, it wasn't setting it so impressed. And then you realize that there's a problem. But there's also a solution, which also has problems. So what? It's definitely a lot better. You don't care about caching. If you don't care about caching at all, if you don't care about entity tags, you can still use this approach. And I think I might not have to report so, but it's probably going to help. So just a question about the X-Fesh tag. The point is you were actually telling, you were saying to the server like, hey, I want different content based on and using that header. Yeah, using the same URL, but you were telling the server, instead of using a query string, using the header, what content to return. Yeah, I figured that would be easiest because when you get into the server and you didn't have to parse out what the right URL is, I'm already parsing the correct URL and having the correct routing in place. It would just be a simple if statement, whether or not this request has this header. But unfortunately, that would happen. I see that there are custom headers that start with X. Is that just a command? Yeah, it's like an extension, basically. Just like, in my mind, it's probably safe to just use X that looks cool, it reminds me of like X files and stuff. But you can call whatever, it just, I think it makes minimal risk of like conflicting with something that's already on the server. Like I mentioned, I wrote my own web server as well. I could make my own headers that my server responds to. And if somebody overrides that, it might get some unintended function. Unintended consequences. Yeah, X says, we do the same thing with templating. So in the script tag, X is just a command. Okay, so the other method of caching. This is one that I have not implemented the bottom part, but I did implement the top part. So the bottom part would be keeping an object hash of every URL and then the latest CRC. Node is not like PHP and .NET and all these other things. Node will always run. It is a server. So you can actually keep state within that. You can have somebody who comes to your page and have a list of the hashes and the CRCs that correspond with the absolute latest data. So if somebody comes to your page and they have old content, they're going to be sending back old, old entity tags and you can compare those. So what I did instead, I'm still comparing, but I don't have a hash that maintains that state which I really would like because I think that would solve the wrong problems. I have a route that I fetch. So there's one that's now slash, fetch, slash, template, slash, and then I encode a URL with the full, like, path to that bottom. Not the full URL, just the path. And there's slashes in it, so you have to encode another bunch of problems. Okay, implementing conditional caching. This is now the big one. This is one where I'll start pulling out the big demo that I've been working on. And if we have time at the very end, I would like to do some kind of live coding with it if possible. Okay, so the concept is that every request has a unique idea associated with it. I've talked about that. There are any tags that are all with me on that. They come down into the invisible headers that are magical and awesome. They're key value pairs. And when you make a request, and you don't even have to do it. This is the browser. When you use Ajax, it will automatically tag on that entity tag that you've already set on your server. You can set the cache. And when you send it, you're now setting it if not matched. So that's where you're comparing on the server. You're not going to be comparing an entity tag. And the response will send back an entity tag, and that's what you have to manually do. So I'm just going to show that real quickly. If anybody has questions, please ask. This is going to be no JS, you know. As I mentioned in my comments, as I'm receiving the entity tag, it receives the if not matched. And just so people know, what I'm dealing with in Node here with Express, it normalizes the request and response objects. So you get this, like, this is perfect for, like, the presentation, because I can just say right now, this is the request, this is the response, and then the content at the end here in this function are just, this will be a template or will be a stringified object in JavaScript, which I'll show where I'm actually calling that to determine whether or not the cache is valid. So we have the entity tag, I'm pulling in the headers from the request, and now it's getting unmatched, it's not at ETag. And then we want to adequately identify that content. So what I do is I take the content that's currently on my server, like, so I made a change. This number's going to be now different. And CRC32 can make a negative number, so I just do absolute on it, so I always have a positive number going through it. So CRC32, in that sense, no matter what happens, we're always going to want to send that latest entity tag back. And I just set it up here. So this is now on the response object, and it's ETag, so that's perfect. And now I'm doing my check. This is the magic right here. So if the entity tag equals the CRC32 that we calculated, well, the browser already has it. So we'll just return false here, the cache, it's going to satisfy. And if it isn't, then sure, we want to send back the latest content to the piece. So let's see. This is where one of the functions happens. This is one right that a lot of labs do get a lot of messy content. So process page runs every time I get a URL. And down here, I have my simple statement checks. So we can say that I have my cache, my request, my response, and then I have the full rendered template. This is when the server is sending back the full page rendered on the actual server. So this is the full content. And now I'm going to be running down to the cache, and that's going to get its unique ID. And then I'm going to send that rendered template if the cache is not satisfied. If it is, then we send it 304. And it's that easy. It's just a response, so that's not 304. I think comma, you can send it some other stuff too, but 304 will just give you that status code that you need. Terminate it, send it to the client. That's possible. So is there any, the speed win here just has to do with the amount of stuff that's sent over the wire. I mean, it seems like you still have, the server still has to do all the database queries or whatever it needs, get the context, and all of that stuff. So it's just about how many bits are sent. Right. And when we look into how long it takes to actually calculate one of these CRC32s, you can see it might be toward disadvantage to use this. If you're doing something like an image, it's best to have something like engine X or whatever server that you have set up. Do that. Node running its implementation of CRC32. Like a four megabyte file is like, I can't remember saying 300 milliseconds or something, so it's actually quite a long time. But for a small file, it's down to like a millisecond, so it's hardly noticeable. But yeah, this would be perfect for a mobile device that really suffers for these assets being sent across the wire. You could also do your caching on the server side, you know, when you're pulling from the database, you could then cache, generate the CRC on the back end and then just clear those caches when the database changes as necessary. So you could do more caching on the server. Yeah, you could minimize this risk of the CRC calculated on a fly on every request. So like that said, you could actually keep that value. And you could probably do that right in Node with like an object, just keep that cache right in there. Then you just check one-to-one. That would be even faster. Okay. So, is everybody with me on like what this thing does and like some of those falls that just been applied? This is really like, this is the part that I care about stuff. And let me show you where the individual comes from. A get object that gets three different things. Template context, and then I have a JSON which I'll get into later. But template, we read in the file, and the file is based off of the path. I'll get into this stuff later too. All we really need to know is, so down at this level where we are in the fetch, remember I mentioned that I had to change my whole approach with x fetch to now using a URL. So now I'm fetching in template. And then this right here is kind of a variable that we can say whatever page it is. And then we fetch that based off of request.params.page. That's a one-to-one map that would hold whatever you give it and express. This is an express, not no jas. And then when I get the template here, I have that jump back up to that function that I was just going through where I thought the cache was. The caches down here, we actually are in the fetch templates. And this is me sending down the template, running through all that. And then fetch context, context. Same thing right here. So if I have to string a file, you don't want to be running a CRC on an actual object of every instance. So that's that. Okay, so yeah, like I mentioned, it's not for everything. One millisecond template, four kilobyte file. Three milliseconds to couple eight eight. That's supposed to be a four megabyte file, not a 300 kilobyte file. And this is something else that I come up with which is slightly different than what Ben Alvin had brought up, which is CRC-ing the modified date for the UNIX timestamp. Not as accurate, but that's something a lot quicker than you could just from CRC. And that increases your chance of collisions. Okay, a cache manifest was something that I was going to go into, but just in a sense of time. This is offline cache. This is another thing that's great for mobile devices. You could actually make an offline version of your template and your context object. If I have time, I'll come back to it. Because this involves editing in GenX configuration file and other stuff. This is something else I want to try was adding get up repos to my demo. Instead of I'll just go into the demo and actually show it working so you guys can see the templates working on the server and the client. It's something I've been building up and I actually haven't written, so I've been lying this whole time. So that's it. So we'll see what's working. So part of what I'm going to talk about later is how you can integrate into your own application. And every major web server out there has the ability to, right here, proxy paths. Make a proxy. So whatever port you're currently on, which I'm going to be running on port, I can leave a link on this. I can actually map a new path inside of here, slash whatever. This could be slash in your application, slash node, and then your rest of your application is up here. So it doesn't, if nothing else hits in here, you can have your slash node, or you could even do like a subdomain, node, dot, something. I won't be getting back into this now since I just explained it, but this is how you do it in a server configuration. You would just make a separate location. And like HTTPD and Nginx, the one I'm most familiar with, it's incredibly easy to do this. A patch is a little bit more robust in my opinion, but it's definitely so possible. And IIS has proxying as well. All these servers have it. If you have a custom back end, you're just starting to make this a little bit more complicated on me, and you're going to have to figure that out if you're in a server. But it should be as easy as this. You set up a proxy. This port right here maps to the node.js port, which I will show you in my handler code. That's very involved when I run node. You can see right here, AdList in 3,000. And app is Express. So if you just think about it and Express is like getting started, you'll see the code is very simple. It's like you define these routes, AdList in it, and then you have some code at the top right here. These are like just two lines. And that's really all you need to keep going. So basically why I'm showing you this right here is that you can use node to serve up all your static files. But I don't recommend that, because that's not really what it's... It's a single thread. So when you start serving files, it blocks the processes where it could be doing other logic. So it's good to have a real web server, even though IngenX is also not necessarily a single thread, but it's an evented server. It's going to act like a separate thread because it's not running on the same thread as Node.js. So you can start... You can send everything on this one and you're processing on this one. So it just makes much more sense in my mind. So I'm going to get here and I've had a good GZip, and this will actually do all the entity tags for me, which is great. So now entity tags will be on all my assets as well. And I have two locations here, because I was lazy, but I could just have all these assets and then just have one and then point it to that. So it's nice to have one directory that holds all your assets. It makes this up a lot easier. IngenX has, like, some weird environmental variables so that if you try and just give it the one that's in this tab, it actually thinks it's in where IngenX is installed. One other thing, IngenX is running, but Node is not running right now. So to run that, I have a handler.js, so if you're performing along or if you're going along and you want to test this out, just get IngenX running, install that with whatever you're using. SIG 1 has it built in in Windows. OS 10 uses RU install IngenX. And your flavor of Linux just find your package manager and you can install that if you don't mind. And then you can just do what I just did right here. If you have any questions, you can always, you know me, but it's pretty easy to figure out how to feed in a custom configuration bug where you can just copy mine and put it into the default. And then just run Node, and now Node's running on 3,000. So I can actually go to VDA, you know, go for it. Great. So, see my demo page that I created. This, what we just hit, rendered it on the server. It rendered both the template and the context together. When I click Twitter here, GitHub hasn't been implemented and Flickr hasn't. I was hoping to do that, but it warned not to do a live demo on this because they may have issues. So if it does have issues, I apologize. Now, these are rendered on the client's side. So, all right, just refresh so I can get these. This is actually, this is a different version of Chromium. DevTools and what I'm used to. So I'm not, oh, wait, it's just now. So if I click on Twitter, you see that we now made two requests and we got the 304 modified awesome. So we didn't actually just download the content. This is our 304 that we sent from the server. Here we see entity tags. Beautiful entity tags. And if you read Steve Saunders' book on performance, he has some breaks with entity tags that he talked about. But, okay, so here's my template. And this is something else that I'm going to get into, which is really quickly, is what the templates actually look like since there's a few queries to see templates. And then the context, which actually has Twitter's response built right into here. So this is a massive thing. Which is cache. And which doesn't also allow paging. It's such a, I have not controlled that to this example. But yeah, these are all my tweets. It's right here. So if you want to follow me on Twitter. Let me know if this is too hard. It's too hard to read. It's just easier to show stuff. Is this visible? Yeah. It's good? Okay. So I'm storing my pages for simplicity right here in a hash and an object literal. You would not want to do this. You would probably want to pull your pages from a dashboard, some sort. Touch TV, any kind of natural-nose SQL that Jason built in. This is me including all that cool stuff that I told you guys to install for us, jQuery, templates. Here it is. So now we've got all that complicated stuff out of it. See how templates get pulled in. So get template, read the file from a path, and I list which template is associated with this particular file right here. You can also write your own logic that based off of whatever this path is, loads it automatically. This is just proposed just to make sure that people know what it's talking about. We have an empty object that contains the tweets. So we're fetching the context. And the context is purely just that object right here. This is the context. That tweet is not here yet, but we will fill it before we send that back. And Jason is this convoluted function that is just the pain of the butt to get Jason and no JS. I really wish they had the helper function. I'm sure there's some library out there that makes it easier. But as you can see here, I'm creating client, used to be client, making a request to sub-arbitrary host with sub-arbitrary path. And when I get data, I add the chunks. So this is not like you're used to where you get a full response. You actually get the chunks and you have to add it together. And then when the request is done, you get the full one. And this is the full Twitter, and I'm parsing it to the object that Jason actually made that request. And this runs whatever event anything that's related to Twitter. So you go to slash Twitter. It hits process page. And this is the paging that I started in Splinter here. So we start page zero. If you don't supply it, if you just supply the page, then it would provide that and request a France page. And then this goes to the Twitter function. Up here. And then in order to actually get everything to render properly, I always call the process page function that I wrote. So get Jason. This looks a lot nicer. Now that I've rendered all that, so I have API.Twitter.com. And then this little long string that just gets a page of my tweets. I'm just getting the first one. And then I find the context. I augment it. So this is me now sending the tweets specifically from the response object. And this is all callback based. So I'm making a request out to the API. And then once it's decided that it's done doing what it's doing and it's ready to use the data, now I'm calling it here. So we're probably also going with these callbacks within jQuery. And we provide them for all the events and DOM writing and all that kind of stuff. And the same thing with Node. Node is like full of these callbacks. So I have my hash here. I'm setting my tweets. I have my page incremented here. So I actually list. It's zero based. So this is me casting this. Because it's ten cores. And the page is actually a string when we're going through the URL matching I messed up. So I have an issue where it's actually making a lot. And they'll always show up instead of one. Yeah. I was showing a lot when I was on page one. So, and then we just call callback. You'll notice a lot that I'm using this kind of syntax. I hope everybody's familiar with this. It's not necessarily the best way to read stuff. It's not the most readable. But for little things like this, whether or not a callback exists, this just checks to make sure that a callback really exists. This is a truthy value. And if it's true, do this. And another option is using an import here. And then this would say if this is false, do this. But we want it, if it's true, to do this. So if we have a callback, now we can run it. And this fixes a lot of errors where callbacks are optional. So if you don't want to provide a callback, why should you be getting an error? You should just do not that. So, there's a lot of extra code here too that just makes this app run. And the big one at the bottom is the catch-all. So if you don't have anything custom per page, you just have a template you need to render, which is good. So you can mess around with that and see what the header tags are. And I was going to do some statistics for payloads and such, but I think it's pretty exciting that this will make pages much quicker, faster refresh, especially on mobile devices. I think that's the sound on your mobile devices as well. I was actually going to take that. That's in your GitHub account? This is all in the GitHub. What's the equivalent of that? It's t-ranking slash tops. So it's going to show how to add GitHub repos into this. And I'm kind of feeling a little agonomic, you guys, but I think we're going to start wrapping this up a little bit. Using No with your existing implementations, I showed how some web servers have support for proxy on your own custom URL. And then you can start using Hijack. I do not show hijack.js. That is a crucial one because this is what runs on the client to make this work. And this is also in my code repo. So fetch before had a pre-send where I set a custom header. And now instead for fetch, I have fetch the type and then encode your icon on the href. And then on success, you can call back with that data. And that data gets used down here. So I have fetch template, gives the href from the link that I'm hijacking. But when you put it here, I'm hijacking every single anchor. So that would mean if you haven't yet implemented it, then stuff would start breaking. But you can make your own custom class and just be like experimental. And now you have when somebody clicks that, it's going out to your nodes instead. And then for that content to show up. It's still riddled with problems. You probably would not want to do this for a progressive enhancement. Your links, if you were to click up and do a full page refresh, just stops it by going to this render function. And then render takes the template in the context. Okay, so we have this is another negative. You have to do a lot of this stuff by hand now. You have to set your own title for the page. You have to set any parts that get rendered by the server need to be done manually. You have to update those. You can't replace the whole page with like you can't have placeholders for now. Placeholders for section. And then render this whole page and then slap it on. You'll just break it horribly. You want to do little pieces, not the entire page. It's just not how it would work. So really figure out what stuff needs to change. Keep it consistent. Right here I keep the original. Parts from my demo, the header of the section is the title. And when I actually replace these on pop state I'm actually replacing what the current ones are with those and that's why you see over here I'm using other stores for these because they're no longer these are or at least not mine. The only thing I would say with your example is that I would recommend using event delegation to handle the click events instead of binding them to the A's. It's not really about rebinding or anything. You just use delegation on the body and check whatever you'd actually look at the check the class in there or whatever. And what that's going to add is like in my example the links never change so when we click around the content that I'm replacing will have any links to them so nothing's going to be broken. But I believe in one of the slides and it may be one that got deleted but I brought up using event delegation for any kind of links. All right let's bring up some things if you're interested in Googling. Range headers are cool if you don't have the ability to do any cool server stuff you can actually request a certain white range from a file that you know might be constant. You don't request a bold one. There was some work with using X pointers with XHGML where you can get like a selector and of course you can pass it whatever you want right on the server so if you pass the selector right in the center you can have your server there's just a little hack you can do with NoScript where it doesn't met a refresh to like a slash HGML which can do an HGML version. So are there any questions? I kind of went fast and there was a lot of material and not all about not yeah this is just an example. Do you consider writing things to a local storage so that you can run this entirely really where the online storage stuff will come in handy creating a manifest and just a cache manifest that's where you would just list yeah your files that you want to save I think that might be a little bit better than using local storage local storage is so common so you think all these cool things you can do with that until you realize that it's really not going to do what you want yeah it's a lot of size limitations but yeah I hope somebody like take a look at this there's just there's a lot of it and maybe it's easy for me to understand it's commented it's easy for me to understand but it's all hard to show this kind of advanced stuff being used but I hope that it wasn't used have you looked at kind of a substance like it's a it's a little tier stuff you've been working on yeah I think yeah I think that's changed it's basically like a server you can it will be terminating for you to render as a client you can get a rendering for a server it sounds pretty similar to what you're saying yeah I'm wondering how who knows what the right content is to do and how he sets it down make sure that you don't re-invest the same stuff over and over I'll be interested to do that is it on the blog he did a talk and whatever in the small room about I was actually in the talk he was really talking about it at that point it was this awesome thing that I'm thinking about and I've got some ideas so I don't know what he's implemented but he was talking about a lot of this stuff he didn't talk specifically about caching or about server side client side jobs here at templates you know here it was like your JavaScript would either instead of requesting the template the render the render partial basically switch place it would it would actually either would request the template itself like like the actually jQuery template in all form of it and go into service like right right this is actually exactly what this does so this is your context this is what it was like URL so templates are right here with that this is what it's running the CRC on to get a unique identity