 So obliging, clapping a second time. But I guess if you're watching this on YouTube, you don't know that I just did a talk. And speaking of which, I should do this bit, where I explain rail just very quickly. These are the goals of rail, responding in a 10th per second, animating at 60 frames a second, being idle at 50 millisecond chunks, and loading it in under a second. So my job is to talk about rail in the real world, to apply rail. And I guess are any tips and tricks. And to know about that, or to answer that, you have to kind of start with life in DevRel. Because the thing about being in DevRel is that we do get to test technologies just as APIs are landing. We're working very hard with the engineers who are working on those. And that's part and parcel of what we do. We're sort of like the crash test dummies of the web, which explains my gorgeous good looks. And we also get to test ideas. Some ideas are good. Some ideas are not so good. But all the same, we try and test them out anyway. In the last year, I have been testing rail amongst the other things I've been trying out. And I've been building web apps to do just that. Progressive ones, no less. Progressive web apps. Awesome. This is the first one. I've seen it a couple of times over the last couple of days. It's called Voice Memos. The idea is it lets you record Voice Memos. And you can save them to the device. And it works offline. And it uses index DB and ES20, 50, and stuff. But you can see there's all these transitions. And it's got to load quickly and so on. Then there's this one, which is a guitar tuner, which actually will tune your guitar. And this was a slightly different bet. I was trying to get Polymer to load it under a second and get itself bootstrapped. And the dial's going around. And that's 60 frames a second, as well as processing the audio. So that was a different challenge altogether. And then the last one, which I'm still working on, is a podcast player. What a handsome pair of gentlemen there with a podcast that you might want to subscribe to. Again, these big hero transitions, scrolling, and all that sort of stuff. So the question then becomes, does this rail work? And the immediate answer I can give you is, yes, it does. That's the good news. But like anything of this nature, I think it needs a couple of tweaks. And the reason I think it needs tweaks is just because it's a model. It's a way of thinking, but reality often just diverges a little bit. I'm going to give you the first example. When you hear about rail, the first thing you might think is that everything's equally important, like everything. I've got these four numbers that I have to meet. And it's not necessarily like that in my experience. So I'm going to give you an example. If you're building a content site, your profile, your rail profile, I guess, might look more like this. It's more like the classic performance profile, where load is super important, getting that first content on screen. We don't necessarily think somebody's going to add it to the home screen or anything. We just want to get something up on screen. Animations are important here because the user's going to scroll, almost certainly. And we don't want janky scroll. Idle. Yeah, you could use a bit of that if you're going to beacon analytics type stuff back. But responses doesn't really rank that high because probably it's link to link, sort of page refresh, bounce around from different URLs. You know, it's not so heavy duty there. However, an app will have a different profile altogether, in my view. An app is more like this because you've got these gestures, you've probably got big transitions, hero transitions, that kind of thing going on. Idle is quite important here because you're probably going to pull data from something like index DB. And you're going to want to sort it, search it, do that kind of stuff. And you don't really want to do that in a way that gets in the users or bothers the user, sorry. And then load, yeah, it's there. But hopefully you're using things like a service worker to really make these things fast and snappy. Now, you could argue that it should be this way or the chart should look that way. And if you're up, it might look different. I think the only thing I'm saying is for me, they're not always just sort of four equal players. The other thing that I think that kind of caught me out, actually, as I was trying out Rails, I thought, goodness, there's these four independent things. Responses, and they're not going to play with animations or whatever. The reality is sometimes they group together. Let me show you what I mean. Let's say we're going from a list view to a details view. So I tap on my item in the list. That's a response. That is followed by a load. And then we do the animation to the final state. So we actually have three Rails actions going on here. And that forces us into asking a question. What is the primary action in that situation? We throw it to you. What would you say is the primary action? Hands up for response. Hands up for load. Hands up for the animation. OK, it's an interesting one. I think the response is the most important one. The reason I think the response is the most important one is because it's the user-driven one. It's the way the thing where they tapped on something and they expect an answer back. So for me, that 100 milliseconds becomes the upper limit. Interestingly enough, in that case, the animation was the implicit response. And I always go in sometimes grouped together in a funny way, I suppose. That's what happens. Rail headlines then. Don't assume the four will be equally important. Figure out the rail actions for your app. It's actually really good to sit down and go, yeah, that looks like a response. That looks like they're going to group together. When they do group together, figure out which one is your primary and go from there. So with that, what I want to do is I want to step into each of these four areas and show you how I try and get within those thresholds. Responses is up first. Target is 100 milliseconds. And for me, I try and sort of break them out into two categories. The first is what I like to call simple responses, which is sort of like a state change, I suppose, like bloop. Most of the time, these ones are very straightforward to kind of get inside that 100 millisecond battery, like tapping on a button or something like that. The more complex ones, and you can see in another example here, the response load and animation ones, which really is a response, I think, those become more difficult. Those complex ones, those combination ones. What I do in those situations is I take this approach. First of all, I will set up a timeout. The idea being, one of two things is going to happen. I'm either going to get inside that 100 milliseconds or I'm not. Now, if I, in this case, fail to meet the 100 millisecond window, I'm going to show a spinner. They're like, for whatever reason, this is taking a long time. I'm sorry. Maybe the disk is slow. Maybe I'm going to the network, something like that. At the same time, I'm going to request the data. Then when the data comes back in, I'm going to clear the timeout. So if it's fired in under 100 milliseconds, we just clear it. Don't worry about it. It was an easy thing to do. And I'll hide the spinner. So if it has shown, it now goes away. One of those two is unnecessary, but they're both needed in this situation. And then I can do my transition to the details view. When it comes to measuring the responses, say, for example, we're going to tap on the hamburger button here to bring out the side nav. The way I tend to approach measuring this is with DevTools and console.time. So for example, in the button listener, I start here with console.time, which is me saying, right, start tracking this one thing, please. And then I'll do my toggle side nav, and then I'll wait for the next frame. So when my JavaScript is finished, there'll still be styles, layout, paint, composite, and all that kind of work that needs to happen. And at the start of the next frame, it's a pretty decent marker that says, OK, previous frame has shipped, we've responded to the user. And so I'll just do time end. If you do take that approach, and you've got, say, you can do this on desktop, but you can also do it on a mobile device, and here I have my Android plugged in, and I go to Chrome Inspect, and I can click on the Inspect button, and you see I get my little device for you there, which is great. Go to the timeline, and I take a recording. Bring out that side nav, and I get my details. Now, two things here. Firstly, in my console, I see this, which tells me how long it took for that to finish, which was 13 milliseconds. But I also get this extra row in the timeline, and now I can start correlating that piece of work with what was going on on the main thread and what was going on the compositor thread. All of a sudden it becomes very easy to kind of see when things are overlapping, and, you know, oh, goodness, I didn't mean that marker, because there's loads of layout, OK, I need to figure something out. So it's a very quick and easy way to start getting this data. So responses differentiate between the simple and the complex ones. The complex ones should normally be raced with that sort of timeout, and then you can just go crazy with time and time end to track your response times, and then you can do what you need to do with those. You can also use the window.performance, the user timing API as well here if you want to kind of beacon some of that back, I think. Next up, animations. Now I'm going to go straight to the how to win animations bit, because the reality is we have eight milliseconds here. Most people go, I thought you said 16, and I did. But that's what everybody's got. I want to say everybody. I mean, us and the browser. But the browser has overhead, and it has housekeeping to do. And so we get left with a window of about eight milliseconds in which to do our work, and that's not a lot of time. And so the way to win is to work with the compositor. And the way to win and to work with the compositor is to limit yourselves to things that can be done just with the compositor. For example, you can use transforms or opacity here. So I built this site, csstriggers.com, a while ago. And it will tell you for every CSS property what it's going to trigger in the rendering pipeline. Give you the heads up. There's only two that don't trigger, paint, or layout and paint. And those are transform and opacity for elements that have their own layer. Now, there we go. There's the transform one. The way I do my animations, particularly these kind of big hero ones, is I use a process I call flip, which I mentioned last year when I was talking about building the Chrome Dev Summit site for the 2014. Yes, that one. And I've since given it a name. First last, invert and play. It helps you remap your expensive animations to cheaper ones like this. Let's say I want to get this purple box from the top left to the bottom right. Most of us, I think, would probably go well-transitioned on width, height, left, and top. The downside of those is that they trigger layout and paint. And they're not something you're going to be able to do at 60 frames a second, typically. Typically. You might get away with it, but probably not. It's definitely more challenging to build, but what you do is we start by calling something like get bounding client rect on the start position. This is the F of flip. So we say, where are you on screen and what are your dimensions? Next, and this is without any animations on whatsoever, we add a class that puts it in the final position, the L of flip. Like so. We call get bounding client rect. It's a nice roll off the tongue kind of API. We call that again to find out where it's moved to on screen. Now what we can do is we can apply a transform. And we just move it back to the starting position. As far as the user's concerned, nothing changed. But we know we just did it with cheap to animate properties like transform. And the same is true for opacity. Now what we can do is we can switch on our animations and just let it play forward. We just remove that transform and it goes back. What we're doing here is we're most likely taking advantage of this setup where the user tapped and then we do some kind of animation. And what we can do is we can take that window of opportunity because, like you saw before, it was like 13 milliseconds to do my response work. Well, that left me about 90 to do other things. So what we're going to do is we do the first, last, and invert part of flip there. And then we can play out nice and cheaply. It works. We've used it on the Google I.O. website. Used it last year on the Chrome Dev Summit site. It's used on all three of my apps that I built this year. It's great. It works. There are caveats. And so if you are interested in reading more about it, I do have a blog post that you can grab there, bit.ly slash flip dash animes. So genuinely applied to the podcast one. Let's say you're tapping on the podcast. It goes like that, just backwards. Goes to the final bit and then squish it back in. And then you play it forward and you get close to 60 frames a second. Well, yes, you get 60 frames a second if it goes well. Similarly to the responses when you want to measure things like this, you can call console.time, do all the flip stuff. In this case, I'm using transition so I can wait for a transition end. And then on the end of the transition, I'm just going to call console.timeend. And in DevTools, I'm going to see this kind of thing. And again, I can see a couple of red triangles just above the main thread activity, which tells me that my frame rate did drop a little bit. But I don't think there was anything I was doing. I think that was just one of those things. If you don't do a flip-like animation, it will probably be very difficult to get 60 frames a second. But it's a big cheat, and I love it. So animate with transforms and opacity where you can, flip your expensive properties over to cheap ones, and be super cautious and avoid work during scrolls, in particular, if you can. Big shout out to the parallax massive. Yeah, my favorite crew. Next up, idle. Now, our target here, as we discussed before, is 50 milliseconds. And the reason being that we want to be able to respond to the user quickly. So if they're in the middle of something, and we're doing some idle time, they tap, we want to respond. So we can finish our idle time up to 50 milliseconds. And we can still probably get something to screen quickly enough that the user feels OK about it. Now, up to not so very long ago, there wasn't a great answer here as to how do I actually do this? Because you'd be in a situation where you would have to kind of add event listeners to everything on your page, and be like, well, the user doesn't seem to be doing anything, because there's no events firing. And I don't know how long I've got, but I'm going to guess, so I'm going to maybe try and do it. It wasn't something that we could realistically do. Chrome, currently, as of Chrome 47, has request idle callback, which is an extremely useful API when you want to do idle work. Here's how it works. Let's say I've got some tasks at the top there. And it's an empty array, and let's say it gets populated. And I know how long my tasks should take. Maybe I've got 100 of them, and I'm saying that each one's going to take maybe one millisecond. What I do is I call request idle callback with my callback, and when my callback fires, it gets this deadline object. And the deadline object has stuff in it, one of which is that time remaining function. And I can basically say this, like, while I have time remaining, and I have enough time to do a task, and I have tasks to do, do the task. If I run out of time, and I still have tasks to go, I can request another idle callback. The browser's in the unique position of knowing what the user's doing, what's going on in the system, whether the main thread is free, and how much time it thinks you've got the schedulers inside of Chrome and Blinker very good at this. So it can tell you, look, you've got this amount of time. This would be good. I wrote a post on Google Web Developers, Web Fundamentals, yes, the updates, yes, it is, about using request idle callback. So if you want to read more about it, head over there. The thing about idle time, though, is it is a bit different, because most of the time we used to be like, well, I've got an event. I'm just going to do my stuff. Off we go. But you have to think differently when it's idle time. You have to think defensively, because you're kind of running against the clock. It goes, you've got six milliseconds, go. And you're like, hi, don't know. OK, great. And it's a different way of working. It spins it on its head. But it's fine. You won't get preempted, by the way, if you go over that time. It's just that the reason the browser gave you that time is because it knows what's going on. If you're looking for things that you could do with idle time, the basic answer is non-essential work, like beaconing your analytics. It's a good time to just kind of say, you tapped on that button to bring out the side nav. I'm not going to send the analytics right now. I'll just request an idle callback. And maybe when the animation's finished or something like that, the user's just looking at the menu. That's a good time to kind of process that work. You have to think in small deterministic operations rather than, right, I'm going to make all my DOM changes now. Great. Now what you need to do, say for example, if you were trying to do DOM work, I'd suggest you either use something like a VDOM or you do something on a document fragment. So you're working kind of off DOM and then in some future request animation frame or something, then drop it onto the page. And as I said before, you want to think a bit more defensively. You're kind of running against the clock a little bit. Load is the last of the rail. And our target here is one second or 1,000 milliseconds. And I've added my own little caveat there for the 75th percentile, which is to say, most people. Because most of the time, on 3G or 2G, you're not going to achieve it straight up because the radio might be off or the user device is just busy doing other things. Makes it very, very difficult. But if you say something like, for the 75th percentile, it becomes a lot more achievable. However, it doesn't upset us from making good decisions in the architecture of our apps. This is how I try and approach it for something that's built with vanilla. So in the case of voice memos, inlining that initial view is super critical. Rob, Bob Dodd. I nearly messed up there. Bob Dodd showed this yesterday, where you have a skeleton. And you say, this is the initial view that you need. And I'm going to inline my styles for that. In this case, I inline an SVG. So the user gets something pretty quickly on screen. Then we do an async, the first I'll load on some JavaScript, so it's not blocking. And that's going to start the request for the views that we're going to need, hopefully in the order that we're going to need them. In the case of the app, it's actually quite straightforward for me, because I know the user flow. You're going to record something. You're going to see its details. You're probably going to go back to the list, like that. And I do the list later, because I don't need it upfront. And then I can go back into the details and play it, and so on, if I need to. There's a variant on this, which is how I work with Polymer. And the way I do, so the guitar tuner uses Polymer, but it's all custom elements that I did. And the way I do it, again, is very similar. Inline the styles, even for the custom elements that I've got on the page, I basically make it look like that. So it's like everything's roughly in the right place. In fact, it's very much in the right place. Then with my JavaScript in place, I'm going to lazy load my various imports like that. And they are all going to request Polymer independently. But the way that HTML imports works is that you can request the same URL 30 times, and it'll actually only get loaded once. And then all 30 would be satisfied. So it's kind of like they're all having a race to get Polymer. And when Polymer comes back in, they can all bootstrap. And the app is complete. And it works really well. When you're doing your testing for load, I cannot recommend WebPaceTest highly enough. It's where I always go. What I tend to do is I tend to switch on for mobile 3G. So I feel it's quite tough. I'll do something like first to repeat you. And the checkbox there at the bottom is for capturing a video, which is really, really useful when you just want to feel what it's actually like to use. To kind of make the point, though, about the 3G and even trying to make the right calls on the architecture, I get a speed index here of 3,403. Ideally speaking, I would like to see something lower than that, maybe 3,000, maybe a little bit less. But the reason I'm not going to get much better than that is because when I look at the request for just the index HTML, which had everything in to get that initial view up, you see numbers that look like this. The DNS over half a second, the connection, the SSL negotiation, time to first buy. But the content download, the bit I'm actually feel like I'm in control of, is very, very tiny. In other words, there's the flame transition. Don't mind if I do. 99% connection. It's like that. It's like, all that other stuff I don't feel like is really something I can affect. And this is what it's like on first view. On the left is desktop on cable. On right, mobile 3G. And off it goes pretty fast. But this is the bit where we go, now I'm going to bring it back to the 75%. This is how I'm going to try and win. By using, I did say it was a spoiler, service workers. Yeah, I'm actually going to explain the code of the service workers. Geoffie did a great job with that. And we've got plenty of stuff for you. But the important thing is by having a service worker on, my numbers for repeat views are really, very, very good. And the reason I'm visually complete, slightly after a second, is because I do a nice fade-in. So it doesn't think I'm visually complete. I could not do that. I could just snap it on. I don't think that's quite as nice. So I take the hit on the numbers. I know what I'm happy with. And this is what it looks like in video. Ready, steady, go. You can't say fairer than that. If a user has an app that does that, they are going to be so happy. Jake built an app called SVGOMG for SVG editing. And somebody remarked on Twitter, they said, I didn't realize the web could be this fast. It's like, yes, it really, really can. And it's really nice when it is. And it's perfectly possible as well. So then load stuff. I would say inline your app shell CSS, lazy load absolutely everything else. Bob Dodd did a great job explaining that yesterday. I'm saying the same thing today. Far future cache, your JavaScript, your CSS, your images, this is classic page load stuff, and user service worker. One other thing that I've been working on, which has been a 20% project-ish thing for me, is something called BigRig. And DevTools is absolutely amazing and what I use on a day-to-day basis. But sometimes I just want a bit of a smoke test for real measurements and be like, is that roughly doing the right thing? Or maybe I'm looking at somebody else's stuff and I'm just like, how much time is going into JavaScript or not? And where is that? Which JavaScript from which domain? And that's why I built BigRig. This is BigRig. You can have a play with it yourselves. The idea of BigRig is that you make a project. So let's say I make one for the Chrome Dev Summit website that I want to track. And inside the project, you have actions. And actions are things you're interested in. They're real actions, essentially. In this case, I do load, response, and animation. So let's say I want to do the initial home page load or something like that. And it creates it for me. And then you go in and it says, upload a trace for this action. And you're like, what? Traces are Chrome's internal way of measuring performance. Timelines are traces, effectively. And you can get a timeline file from WebPageTest. So here I've got Chrome Dev on an XS5, select that. And again, it's mobile 3G. Why not? And under the Chrome settings, you can check a box that says Capture DevTools Timeline. Turns out really quite useful there. Now if we go, we start the test and it takes a while. When it comes back in, you see there's this link here in the corner that says Timeline. So you click it. And then you go back to BigRig. And you give BigRig the file, like so. You do the dance while you wait. And eventually, it will say, this is what you spent your time doing. This is the parse HTML. This is the JavaScript. This is the styles, the layout, the paint, the composite. And you get those numbers immediately. And you can also go into the extended information where it will tell you, by domain, where the JavaScript was coming from, so 4,009 milliseconds on the site itself. And you start to get this over time. You can actually build up a picture of how am I spending my time across all these rail actions. So it's good for responses. I'm going to tap on a thing. What it does is if you give it a timeline file with console.time and console.timeend, it will use those as the labels. And it'll go, oh, you've got one there. OK, that looks like a response. That one looks like an animation, and so on. So it's good for animations. It'll give you those in frames per second. And again, you can start to see how you're doing there. This one's an actual real one. Paul Kinlan uses BigRig to monitor his site. And you can see on the far left hand side, there's a big block of green and big block of yellow. And big block of green, he was like, why have I got a big block of green? And we went to look at his site, and it happened that he'd forgotten to resize down an image. And it caught it for him, and he fixed it. And you can see it sort of settled down a lot for him. If you can post the timeline file, the trace file, to an endpoint, and it'll process it. And if you do that with the hook, you can see which web page test result it was. And you can also see the git commit as well. So you can be like, I had a regression. Why? Kind of useful. And in his case, in case you're curious, that's what the blame game looks like for him. I've suggested that he might want to lazy load his comments. Makes it quite easy to do that kind of stuff. So if you're interested, BigRig is on the Google Chrome GitHub org. Some people don't want a UI, though, and that's cool. So there's an alternative, which is the globally installable BigRig. Similar kind of deal, actually, just on your command line, where you can go BigRig with the file. And it's the same timeline file from before. And I'm just going to ask it to pretty print the results. Because otherwise, it'll return just a JSON to you. And you can see here, again, it's the same kind of details. But if you want to integrate it into an existing flow, you can do that as well. And that is under Node, BigRig, where you can just do NPM install. And then there's this one as well, which is another tool that I've been working on. These is kind of try and make rail measurement just a bit easier if you want to do it outside of DevTools. And there's loads to do, and there's loads I want to do. One of the things is like, it's hard to do a scroll test. So I've got the BigRig runner, and you can give it the site that you're interested in tracking, or just getting a scroll test from, telling it to look for the body element. And I'm going to pipe it through to BigRig. And you see Chrome's open in the background. It just does an automatic scroll test without me doing anything. And at the end of the scroll test, it spits out the results, which BigRig then pauses and says, well, that was a smooth scroll and an animation. And it was 54 frames a second. And it tells me what I was doing per frame. Kind of useful if you just want to, as I say, do a smoke test and go, how am I actually doing? OK, I have not so much time, so we'll come back into the final thoughts on rail in the real world. Rail and those thresholds, they genuinely work. If you build a site or an app against those rail thresholds, you'll find that it feels just right. It feels snappy. It's well worth dissecting your site into those rail components and trying to instrument your code with time and time end and so forth. And you could stick to the limits. They are very, very good. They will serve you well. And as always, test and use web-paced tests, use dev tools, and if you try BigRig, do let me know. And with that, I will say thank you very much.