High-Speed Web Applications: Beyond the Basics


Knowing how to run performance tests on your web application properly is one thing, and putting those metrics to good use is another. And both these aspects are crucial to the overall success of your performance optimization efforts. However, it can be quite an endeavor at times for it means you need to have a precise understanding of all the ins and outs of both performance data and performance tooling. This talk will shed light on how to overcome this challenge and walk you through the pitfalls and tricks of the trade of Chrome DevTools, providing you with a complete roadmap for performance analysis and optimization.



Hello and welcome to my talk High Speed Web Applications Beyond the Basics. A talk about the latest and greatest features in Chrome DevTools. Let me quickly introduce myself. My name is Michael, Michael Latke. Very hard to read, write and pronounce, so let's stick with Michael. What I do is I do consultings, trainings and workshops in the field of performance optimizations, Angular and reactive programming. I also run a company that is named PushBase, you can visit it, just click on the link in my slides. But now let's see what's on the agenda. First of all, I will talk about the network tab. I will show you what you can see in the network tab and then I will try to look at some latest features. One of the cool features that are shipped in Chrome is Fetch Priority and I will use Fetch Priority to optimize the largest content for paint with an image as well as with HTTP requests. Later on, I will show you how to look at the performance tab. This is not really easy because a lot of information and I hope or let's say I promise that after the talk you will be able to at least have a little bit more understanding on what you will see there and what to look at. To demonstrate some optimizations in the performance tab, I will use content visibility, one very nice cutting edge CSS feature and I will also introduce you to scheduling and chunking of work in the main thread. At the very end of my talk, some really, really exciting stuff. I want to talk about UserFlows. UserFlow is basically a new tool that is at the moment only available in Canary Chrome and it enables us to completely new ways how to measure runtime performance in the browser. In the end, I will pitch to you the latest and coolest tools on UserFlow, how to use them and also how to integrate that stuff in your CI. With no further pauses, I will jump right into network analysis and the network tab. So what you see here in this tool is first of all I selected the network tab and then you have a lot of information present. A lot of information about all the HTTP requests that are done from your application. And if you have a closer look on the right part of that slide here, you will see the waterfall diagram. In the waterfall diagram, you basically see a time bar chart thingy that displays all our HTTP requests, their start, their end and what time they are made up of. If you hover over one of those tabs, you see the request timing and the request timing can show you some information about connection time, how big the amount of data was and all the other times and durations that were required to make up the whole receiving of that data. In this slide, you see a column that basically tells us about the priority of HTTP requests. We can see that some of those HTTP requests are more important, have a higher priority than others and I want to leverage one of the latest features, Fetch Priority, to demonstrate what you can achieve with priority in your application. Without more information on the network tab, I will straight go into practice and show you how we can change all the requests that are done and how we can improve them. One of the first things that I want to improve, also visible in the network tab of course, is the connection time. In this slide, you see at the very top an unoptimized version of two HTTP requests to two different domains. As you can see, there is an orange block that connects and then a blue block that downloads, another orange block that connects and another blue block that downloads. If we leverage the pre-connect attribute on our links, we can basically tell the browser, look, to those two API endpoints, we will fire requests in the future, so why don't you just set up the connection right at the start of the application and then we can save the connection time later on. This is demonstrated in the lower part of the picture and you can see that both connection blocks are now parallelized at the very beginning and the whole chart is a lot shorter. The next thing, and this is the fancy new cool stuff, is the priority of those HTTP requests. Again, in this chart, you see an unoptimized version at the top, some execution of script, some fetching a resource A, fetching a resource B, and then rendering stuff. Of course, rendering an image is more important than executing some script or fetching some resources that are used later on. The first thing that we do is we should make all the yellow scripting blocks asynchronously and non-blocking. This can be achieved by the defer, the preload, or the prefetch attributes. Deferring scripts just means move that script to the very end of the queue and go on with processing, with parsing of your HTML, and preloading and prefetching means basically that I try to get data at the very beginning of, let's say, the part that is not visible in the page. Preloading would be preloading resources that are accessed at a later point in time on this very page, and prefetching could mean preloading some stuff that is used after a navigation. With those three things, we can already go far, but there is another really, really fancy and very, very helpful feature, fetch priority. So with fetch priority, we can basically determine on which of my HTTP requests have more priority than others, and I want to use it to update the largest contentful paint of an image. If we look at this code snippet here, we see two links that fetch some hero images, and one of those two images is more important than the other one. So normally, just by the order of HTML content, we would first fetch hero image one and later on hero image two. But now with fetch priority, I can tell the browser that the second image, even if it is later on in time, has more priority than the first one, and the browser would switch execution of those two HTTP requests and fetch the second one earlier in time. How would that look in practice? So I took ObservableHQ as a dummy website, and what we see here is a video image, or like I say, a small image of a video that we start to play later on, and this is definitely the largest contentful paint, the most important part the user should see at the beginning. By applying some tweaks to the HTML and using prefetch, we end up with the following improvement. So what you see at the top is the first line of this movie strip shows us the default page, and the second line of this movie strip shows what is the outcome of my optimization. There are two things different. First of all, the whole chart is way shorter now. I basically went from total seven seconds to 4.5 seconds. But the really, really important and interesting part here is the largest contentful paint is now present at the very beginning. So I went from seven seconds of the largest contentful paint, which you can see here at the top, to 2.5 seconds. This is also what is visible here in the detailed diagram at the bottom, and you can see that the image is really the first thing visible, and then after that there is some fetching, but the image is always visible and gives a very nice user experience for users that want to consume this video or at least want to see a first sneak peek. The next optimization that I want to do is I want to use or leverage fetch priority in HTTP requests. So when you use the fetch API, you now can also give it an importance of this HTTP request, and this is done by just applying another configuration as you see here. With this technique, let's see what I did in practice with it. If we have a look at the page, we see two different dynamic contents on the page. We see a list of movies and a side menu with a section that is made up of dynamic fetched menu items. And as you can see, those HTTP requests are filed quite late in time. So when I apply fetch priority, and you have a look on the next slide, you can see that I moved this stuff to the very beginning, and I was also able to basically shift the order of those two HTTP requests so that the images of the movie list is fetched first, and after that, the dynamic list in the side menu. Pretty cool, pretty exciting stuff. Everything that you saw is basically possible with this new cool feature, fetch priority. What's next? Next is the performance tab. The performance tab is one of the most insightful, but also most complicated charts to read. When it comes to performance tools. In the next slide, I want to give you a sneak peek on what you can look at and also how to improve that stuff. So let's start with what a frame drop or a long task is. First of all, a user always wants to interact with your page. Interaction means clicking, scrolling, or any other stuff that could happen to the keyboard or over the keyboard. One of the most important parts is to give the browser the chance to process those interactions whenever it is needed as fast as possible. If you look at the chart, you see gray boxes and those gray boxes are so-called tasks. A task is basically a unit of work that the browser needs to process before it can do anything else. For example, reacting to a user input. We can spot those long tasks, tasks that took too long to block user input or the processing of user input by this red area or by the small red triangle that you can see on the top right here. Another place where you can spot that stuff is also the overview at the very top. There you see these red bars and the green squiggles and those two things basically tell us where our long tasks are and how the frames per second rate and if the frames per second are consistent, you can assume that also our tasks are not too much blocking. At the very bottom, number three, you see an overview, in this case a total time of all long tasks and their blocking time. Total blocking time is one of the heaviest rated measures in, for example, the Lighthouse score and we should always try to reduce long tasks or total blocking time to a minimum. Let's now zoom in a little more and understand how one single task can look like. In this picture, we see one task in detail. We see that at the very top is a gray box. The gray box marks, of course, the stuff, but what you also see is the type of work, yellow, purple, or green, scripting, layouting, or painting. And below all of that, you can see the details, what exactly got scripted or what exactly got layouted or painted. In this slide, you see that this task is marked as a long task and we see the overtime area in this red dashed, or not dashed, but shuffled lines. And then we also see the long task flag, the red triangle at the top right corner of every gray box of every task that is marked as a long task. This information is very important for us because this is what we need to get rid of. What we need to get rid of is everything that is longer than 50 milliseconds. So as you can see here, 50 milliseconds is an okay-ish long task and everything that is over 50 milliseconds is basically the overtime of a task. With all that information, click, we jump to page relay outing and paint. This is the purple and green stuff that I want to show you how to optimize it and I want to use latest browser features available in Edge and also in Chrome. And in this slide show here, you can see from can I use where it is supported and I have told you already it is supported unfortunately only in Edge and in Chrome, but all other browsers are working heavily to get that shipped. So now as we understand where you can use it, let's see what could be the potential impact. This here is a lab measurement of taking one page in an unoptimized state, one page optimized with content visibility or notes on screen, which means all content is visible within the page and then all content off screen, which means it is somewhere below your screen size not visible to the user at the moment. If we look at the numbers, the top numbers is in green paint. So we can go from an unoptimized with six milliseconds paint to on screen optimized one millisecond paint and off screen really, really nice to 0.1 milliseconds off screen. This is really an interesting impact. I would say a tremendous impact. Even cooler for layouting. This is the lower part here in this slide. You see 11 milliseconds update layer tree and paint with the optimization, everything on screen 0.5 milliseconds and later on everything off screen. It's only 61 microseconds, which is a really, really interesting number and heavily dramatic impact. As lab measures are nice to learn and understand, but what we are really interested in is the field data. So let's see what I achieved in the wild. Optimizing rendering time is the first thing that I want to show you. And in the next slide we see again from observable HQ at the top some animation and layouting work that is present here. And the longest task in this layouting work took basically 260 milliseconds. Of course, a long task because it is longer than 50 milliseconds. And with my application of content visibility, I was able to went down to 15 milliseconds for the same work done in the same website. So this is a tremendous improvement and really, really, really nice to see with what is possible with just one to see slight changes in your application. The next thing that I want to demonstrate or introduce to you is scheduling and the frame budget. This is mostly important to get rid of scripting or to at least reduce the total blocking time of scripting. What we see in this slide here is scheduling of work and how it could improve input to next paint, total time to interactive and total blocking time. Imagine there is a button click and this button click would cause some work. And instead of executing that work right away, I take this package of work and move it into the next task, into the next gray box and execute it later on in time. In this very example, I used animation frame to do the update because it was a visual update that caused some pixels to change. But this is basically also possible with a lot of other scheduling APIs. So what is marked here is the scheduling moment in time and the scheduling duration. Let's see what theoretically would improve. What we see here in the pink, hot pink dashed horizontal line is the next possible moment when the browser could process user interaction. This is a very nice improvement and it also increased time to interactive by tremendous amounts, as you can see from this first bracket here. And we also reduced total blocking time by 50 milliseconds because every task is OK below 50 milliseconds. And now we made two instead of one task. Pretty amazing improvements, and this is just the theory. In practice, optimizing total time, total blocking time and input delay is the next thing that I want to show you. And in this very example, click, I want to demonstrate again the movies application and the bootstrapping of that application. If we look at this diagram here, we basically see one huge task that is processing some JavaScript files and then executing the framework. After some optimizations on the very left, we still have a little bit of a big task because optimizing a webpack bundle and its compilation is not that easy. About everything that is framework land is now optimized and we can see a lot of hot pink dashed vertical lines. And those basically are all separated tasks that in between give the browser the opportunity to process user input. And as you can see, all of those tasks are no long tasks. So pretty, pretty amazing improvements that we could achieve with scheduling and chunking. The last and most exciting thing that I can demonstrate to you is user flows. User flows is one of the fancy new features that Chrome DevTools will ship. At the moment, it is only accessible in Chrome Canary, but there is an open source library that you can use and install already today and run all that new stuff fully stable in your CI or from your CLI. The link here is github.com slash push dash based slash user flow. Please have a look. Very interesting. So what is user flows? If you imagine that Chrome has this tool that's called Lighthouse and Lighthouse so far was only able to measure bootstrap performance, performance that measured the moment when you navigated to a page the first time. And this was always a cold navigation and was always, as I said, limited to bootstrap performance only. With version 9 something, Lighthouse now enables three measurement modes, navigation, time span and snapshot. Navigation is basically the default Lighthouse measurement that was present ever since. So any measurement was a navigation measurement or navigation mode until version 9. The second very cool measurement mode and for me, most exciting one is the time spent measurement mode where you can start and stop recording of a duration of time and within that duration of time, you can run some user interactions, for example, fully automated with puppeteer. And at the very end, we see snapshot and the snapshot is basically a way to take it. So called snapshot of your page at any moment in time. And it is very useful to that to determine accessibility measures and other static stuff to a later point in time, not only at navigation. Let's see how this could look in practice. What you see here and in a second, I will show it to you live is a user flow report, basically a report that looks quite similar to a Lighthouse report, but as you can see, has multiple different steps. And what I did here is I basically ordered a coffee online. Let me quickly exit the slides and demonstrate to you how this report looks in real life. I will open up Chrome DevTools and I will hopefully, if I don't make a mistake, be able to drag and drop the report directly here, as you can see. So this is the normal Lighthouse report viewer and it already supports user flows. The first one, let me click on summary, is a navigation to this coffee cart application and I will open the application for you, just that you can see a very primitive application. I can select the coffee, click on that stuff, could enter some user data and then order basically a coffee. I see the confirmation message at the bottom and that's it, what I wanted to record. So let's go back and let's have a look at this. What I did was a navigation to this page and from the numbers you can see this is a default Lighthouse score. I can click on it and I see the full details. I have all my web vitals here, some images, the time, the tree map and all the diagnostics visible at the bottom. As a later point in time, I recorded the time span of selecting one coffee, so from a non-selected coffee to hovering over a coffee and then clicking that coffee and select it. This is recorded here. As you can see, it provides us a reduced number of our recording. We see total blocking time, cumulative layout shifts and other stuff. If I scroll more down, we also see all the detailed recordings. The last one is selecting a coffee snapshot. So after I selected a coffee, I wanted to make sure is all the accessibility still given, are CO terms met, is best practice still a thing and as you can see, those numbers here show us that it is reduced but it still gives us a lot of insights on what we can do with those new tools. Of course, there are more measurements. Again another time span for checkout, another snapshot for checkout, another time span for the order submission and another snapshot for order submission. Really nice tools. I highly recommend you that you check out the link from before on GitHub push based with a dash slash user flow and you can directly use it already in your project CLI or even CI. Let me jump back to the slides and open them full screen. And let me say thanks for your time. This is the very end of this very small, dense and brief talk about some latest and greatest features. I know it was quite a lot in some minimum time so if you have any question, feel free to shoot me an email michael.latky8pushbased.io. I'm also on Twitter. I'm more most probably more active on Twitter than on any other platform and again the GitHub link to the latest and coolest feature user flow. Please check it out and again, thanks a lot for your time and see you later. Enjoy the rest of the conference.
30 min
20 Jun, 2022

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Workshops on related topic