 Bad inlining sounds like a like a pop band A hop band No, a pop band pop band. I thought you made up a new genre. It's like hip-hop, but it's not so hip It's just hop just a hop band So so I've been looking at the performance of some websites recently specifically Formula One websites, but I also looked at the Google IO website and I can't do an episode on that because showing other people's websites lands in all kinds of legal difficulty and checks So I can't do that But instead what I'm going to do is show you the top 10 Where performance pitfalls that I have seen while looking at a variety of different sites recently I had nine good ones But then once I had nine what I have the 10th row and got thrown a 10th, haven't you because it sounds better It's the one like which video you're gonna look at on YouTube the top nine No, all the top 10. Yes, absolutely. So that's what this is the top 10 First we should talk about How a page actually loads or how it should load. Oh, wow, we're going back to the basics Oh, yeah, well, this is mostly load time performance stuff. In fact, almost exclusively. This is this is load performance I would say first up you need whatever you need to display call content for a news article It's the content. You know, it's the text of the image if the images are part of the call content as well You're saying for a blog post if it's more app-like then maybe this is just The shell of a user interface Don't render buttons that don't work. That's you know, it's annoying No one like clicking buttons and nothing happens. So you would just like maybe have the shell of a user interface Next it's what you need to make that first interaction work For a blog post or a news story The main interaction is reading. So there's probably not too much to worry about here For an app more like, you know, Squoosh or something. This is where you make the buttons work This is where you make those buttons appear. So that first interaction is there and then there's everything else This is a bit of a simplified model You can introduce more phases more progressions, whatever, but really If more of the web just had these three phases, everything would be so much faster I'm going to show you some things that happened that stop this model working correctly the things that get in the way So in number 10 and remember I said I just kind of threw one in to make up the numbers That's this one Number 10 it is sprites and icon fonts Ta-da, I mean by very definition. They load more than you need Yes, and If this happens less and less now, which is why it's way down on my list But I have seen this cause a delay especially to the interactivity part. Here's a sprite Like I say, I can't show stuff from other sites. So here's a Google one. This is what you'll find on Google.com So it's one image file and it contains a whole bunch of icons We used to do this in the HTTP 1.1 days because In htp1 you could only download one thing at a time We used to spin up multiple connections so you could download more things in parallel. So if you had 60 icons or whatever It's that's lots of connections that you will need to spin up Well with htp1.1 you would spin up six, but you would only be downloading six at a time and yeah I was going to say because you couldn't even spin arbitrary spin up arbitrary amounts connected Those were limited by spec to six. So you had six requests in parallel at most so reducing I think the spec limited to two browsers quickly ignored the spec. Okay, that's good to know It was still pretty limited to between six and 10 depending on the browser from memory So this image here on the google site is 100k But individually those icons a lot of them are 500 bytes if you encode them individually Google does use all of these icons at once There's a little button you press and it shows you all of the different google apps and they all appear at once So it's not too bad But what i've seen on other sites is like a 300k sprite sheet But the page is only using one of those And that means the user is paying 300k For one image that could be 500 bytes. I'm guessing that point was it's in the cache So all subsequent loadings of another icons would be super fast, but the first impression matters This is really at the roots of web performance Is a lot of sites are built with this model of like well, let's prepare everything in advance and then give you something And it's just not a model that really works it it depends on the user doing particular things afterwards, but You can get the same benefit by giving them everything they need first and then Downloading the rest in the background and you get that same you're ready for the next thing But you didn't compromise showing them the first thing and that's really those phases i'm talking about Hey, and it's the same with icon fonts We saw that actually on the google isle website They were pulling in a whole icon fonts and they were using the hamburger icon and that was it So that's like 50k for what should be like 30 bytes or whatever I would say yeah avoid it these days just serve the stuff separately It means the browser can be smart about which icons it needs which icons it needs with higher priority Yeah, it's just it's just something we don't need to do anymore in the world of htp2 next up number nine Dom ready delay and this was one that I didn't Expect to come up, but it it did appear on a couple of sites. It's a real gotcha actually This is what it looks like. So you've got your main script in the head It's got it's got defer, you know, so it doesn't block rendering great And then at the bottom of the body you've got some less important scripts And they're using defer as well. So there's no render blocking going on here It all looks good on the surface But in the first script it does this And it might not do that literally it might be using some Like jQuery ready function or some other kind of ready function that bundles with with a library But if it uses DOM content loaded under the hood That will wait for all other deferred scripts to download and to execute And so this this kind of model that looks great from the html Where you've got like one thing at the top there and then the less important stuff further down It it's spoiled by having this DOM ready thing. Is the correct alternative and DOM ready? Because there's a second event right which basically we're looking for is the an event the DOM parsing from the index html is done so There is another thing called ready state which has which Has two points one which is before the deferred scripts and one which is after So you can use that but hey if your script is defer It's already going to wait until the DOM's ready anyway So the solution here is just don't use it right. You know don't use DOM ready um There might be a cases where Someone added this code in because one of the other scripts adds something in that they need or whatever But if you need a certain part of the DOM to be there and then you enhance it There are better ways of doing that There are web components that you don't have to go all in on web components with shadow DOM and all of that But you can use just the the shell of a custom element as a way to to be alerted that when an element appears on the page There are mutation observers as well, but really In most cases I would say just you know if you've got the third script that's going to run when the DOM is ready off you go Next one Number eight. This is bad inlining All right, so inlining is when we bundle one asset inside another I mean we tend to use inline to refer to some particular kinds of formats We don't tend to do it when you bundle JavaScript within JavaScript We just call that bundling inlining. It tends to be another format inside another format and it's often great for micro optimizations But when it goes wrong, it goes wrong badly. So I'm going to do a countdown with an account down Here we go here are the ways that I've seen inlining go wrong first up JavaScript Uh inlining JavaScript for your first interaction tends to be a really good way of doing things We did this on Squoosh. We've got all of our JavaScript for our first interaction inlined at the bottom of the document But yeah, it should go after everything that's needed for the first render and your first render is html and css I actually saw a couple of sites recently that had a few hundred k of JavaScript right at the top of the document And this is pretty much as bad as a blocking script. The browser has to download 100 k's worth of stuff Before it can render the content before it can discover things like images and maybe other things like you know css and other scripts And yeah, you're saving an extra request, but also you're giving up lots of cash granularity and all other kinds of things So inlining is is that like is a good tool to have but you should use it very consciously and With small units Absolutely. Yeah, avoid blocking your content render on JavaScript. It's good advice in general But just inlining it is just the same problem. But in a different spelling, you know, it's the same thing So you put it at the either in a separate file is fine As long as it's loading in a non-blocking way using defer or async Next one images I would say it's almost always a bad idea to inline images because they can be quite big And it's the kind of thing that you could have involved in your build script And someone changes the image doesn't compress it as well or something and it turns from like A moderately bad thing to a really really terrible thing um I saw one website Where they had an svg because svg is small, right? But inside the svg they had a 1.9 megabytes png inlined it was You know and something had gone wrong there. They didn't mean to do that. But because it was inlined Because the svg was inlined in their JavaScript as well So it became like a huge huge problem and also base 64 will make your data one third bigger Yes, which um, you spoke about hoofman coding in the last episode does Give you a lot of that back But um, yeah, it's still quite a bit bigger um, I want to call out svg specifically Because inline images doesn't happen so much But inline svg is happening a lot more because you can put it in your html You can put in your css you can put it in your JavaScript And it's sometimes a really good micro optimization, but it can also be big I saw a site that had a set of sponsor icons that quite High up in their page before the main content and It all added up to be like a few hundred k Of svg down. Yeah, that's So and because it's inlined it's now blocking the main content and other things If it's in separate files, it means the browser can, you know Apply different priorities to different icons, especially if you scroll away before it loads them Uh, it can do the right thing and it can also render that main content much earlier My main reason for inlining svg is because I want it to be affected by my css Which is an image tag. It doesn't do I know I feel that we it would be good if there's a better way to do that Like somehow have a you know svg that comes from an external file, but it can be um Affected by your html. I guess really the answer there is just fetch it with JavaScript and then put it in the page We'll give you that Yeah, one thing I see a lot right now Um, and I think it's for the same reasons you mentioned there is people putting svg in their javascript But as jsx So it's been converted to you know, the the pure javascript interpretation of jsx, which does add some overhead Um, and you end up with these large complicated bits of svg are now in the javascript And that's a problem for your first interaction Because if your first interaction contains these icons, especially if the icons that you don't need right now They're adding Size to your javascript means it downloads slower. Your first interaction happens later All right, next one is the big one. Can you guess what it is? um I Don't think I don't think it's woof. No, it's not woof. Woof is a really good format of this type of file though I was gonna say like it is it is a web font, but I think we should wait until it's Watson has calm down And yes, it is it is woofs inlining woofs is bad. You are absolutely correct. It is a web fonts Uh, especially because you know, this is going to be inside your css CSS blocks rendering and so if you add 500k of fonts to that That means blocking for a lot longer. And this this is what I've seen now Fonts are difficult when it comes to web performance because it you know while the font's downloading It might mean that your text is blocked or that your text will swap which is also not great But when you inline font data It's going to block the whole rendering of the page And also it could be blocking rendering on fonts. You don't even use on that page. And that's what I was seeing so almost never do this I say almost never because you know, there are cases where if you subset the font to just a few characters You can get away with it. But you you know, you have to I was about to say you do it on prox You actually build it for prox where we inline a font But specifically only the letters that we use for the first render. Yes, and I do it in squoosh as well the squoosh logo Is just the letters for squoosh Inside that svg file. So Yes, okay, there are cases where it's good, but you you have to be so careful. Um, it's yeah, it can't just be for for general fonts All right Back to the main camp down. We love talking about images. Let's talk about some big images images download in parallel They don't block things like, you know rendering. They don't block rendering like css blocks rendering And also the browser is smart like it gives images in the viewport a different priority to images outside the viewport. So What is what is the problem here? In the viewport images have the same priority or higher as than script So if your image is too big That can delay your first interaction because the image and that script are going to be fighting for like You know the same bit of bandwidth because just because like htp2 can download things in parallel Doesn't mean you magically get twice the bandwidth that you have right? It's still you know sharing those things out so It's another opportunity for us to plug squoosh use squoosh make your images smaller Many images i see on the web could be a tenth of the size and it's not always down to using some new Format that's only supported in chrome, which i'm talking about avif here But like even just as a jpeg things could be so much smaller and webp has has really good support now as well Yeah, i did a couple of experiments about 50 percent of the page weight is images on average according to hvrcraft at least and The vast majority of those images can be compressed to have their size even fully automatically without perceptible loss of quality So we really have a lot of Things you can do better with images on the web. Absolutely. Yeah, as i say a lot of time It doesn't matter. It just means that image is going to load slow, but in some cases it delays like more important things Uh, another thing that i want i want to point out that sort of gets lost A lot of people don't know about is that this image will still load like images predate css by some years Uh, so the idea that images load before layouts, um, or before css layouts It happens before because they existed before css layout even existed So this will download the browser will download it at low priority It will still use bandwidth, of course, but it will be at low priority because it knows it's not in the viewport this won't This means that the image is now dependent on layout and so it knows it's not part of the layout So it won't download that's something i didn't know and find it really interesting that You could I guess it makes sense because the image tag has been used to preload images via javascript without even being attached to the document So it needs to load but that loading equals lazy now had to actually introduce image to be Self-aware about whether or not it is being laid out and where it is being laid out that that changed that behavior or something I didn't realize yeah, and that comes at a cost as well So don't just put this on all of your images because especially for your main image at your top of your screen If you put that if you put loading lazy on that then the browser has to download the css It has to lay out the page And then it will go. Oh, there's an image here. I'll start downloading that whereas without Without that attribute it will start start downloading the image much sooner So yeah, it use it on things that you know are not going to be needed yet But don't use it on images right at the top of the page all right next up Sticking with images, but this time how they're loaded loading main images with javascript. I see this a lot htp2 is very good at loading things in parallel The browser is good at figuring out the priority thing should be most of the time sometimes gets it wrong But it's good most of the time But the problem with loading content with javascript is the javascript has to load and execute before the browser knows anything about The next thing, you know So I see this kind of thing going on where there's an image carousel Sort of thing that's powered by javascript and it will just be divs on the page with Days of attributes which mean nothing to the browser awesome javascript implementation of responsive images And then some javascript comes in goes. Oh This should be an image and it creates the image and then it starts downloading but that's Many may seconds later depending on the on the connection And you can't band it fix it with like a preload or prefetch But really you should be using the elements that are given to you by the platform here And you absolutely right one work around is to use preload, which is a good way to tell the browser about stuff That's going to be needed later But yeah, really You should only use preload if you're out of better options and in this case We have the image tag, which is pretty good at loading images and responsive images have really good support across browsers So there you go The browser will see this as soon as it passes the page and it will prioritize it accordingly use all of the Smarts that are built into the browser. All right next up number five Halfway through the list now primary resources on other origins I saw this on almost every site that I audited It looks like this I've seen it with unpackage Specifically a few times but also just separate cvn's or separate services or whatever hdb2 Is great. It means you can have many things Downloading in parallel over the same connection But because this is pointing to a different server, it has to then set up another connection And this is this is one of those things that used to be good advice Like because you had that connection limit to a server in hdb1 We would use lots of servers and up that limit But now that's bad advice because with hdb2 we only need that one connection But if it's on another server, we have to set up another connection and that takes time That can be a couple of seconds on 3g I also say like I think around trip time and as a result creating a new connection to a server is one of the Costliest things in the first load of a page. Absolutely not not too bad if it's for secondary content So I wouldn't worry about that but it's bad for primary content I would say I really like unpackage. I use it on a lot of like prototypes and playing around and that sort of thing but Unpackage will also redirect to the latest version of the library by default So what what happens here is you end up paying a connection cost And then it does a redirect and that tells the browser to go and request something else And I saw this on a few sites and that is just like on 3g Seconds seconds and seconds worth of time just wasted on just finding out the right thing to download Yeah, not great. All right next up number four External font services. This is a little bit similar to the previous one But it's so commonly specific to font services that I I want to give it its own place in this list A lot of font services are not your friend when it comes to web performance Um, and that's a shame because we all like to use web fonts. It's very, you know, nice to have a different design on the page So the problem starts here. We've got a render blocking resource css But it's on another server. So we need another connection. So there's a couple of seconds But then they tend to serve the fonts themselves on yet another server So that's yet another connection another couple of seconds wasted Even if it was the same server, it it doesn't matter because font files are requested using cores Uh, and they that will always use another connection. Uh, if it's no credentials So that's that's a fact not many people know. Yeah, if you're making a cross origin request If it's with cores, you know, like fonts or like, you know, fetch or xhr whatever That will use a different connection to say an image file or a css file or a script file Uh, because it wants to keep that boundary for privacy reasons. So yeah, anyway another connection and then some even go on to do this where it's like Yeah, like a style sheet is requesting another style sheet And that's even more render blocking time. It's it's bad. It's just really bad Because this also this import isn't discovered early. So it Well, you know, it might not create a new connection It will definitely incur another round trip because now this file has to request it before any more processing can be done Yes, and I have seen cases where it's on yet another server as well It's a disaster Yeah, when you've got a style sheet that loads of style sheets You could use a preload You know to say that makes it happen in parallel rather than in series You can do that with the font itself as well. Just make sure you use cross origin on there but Again, remember that those URLs might change if you're using them on a different service You know, you might put all of these pro preloads in and then tomorrow They've changed their URLs and now you're preloading a bunch of stuff that you don't even use and that's even worse for the forms If you don't know the full URL you use a pre connect That'll at least set up the htp connection sooner Again, make sure you use cross origin to tell it whether it's a cause connection or not But really the best solution is to bring those fonts and the css onto your own server And you can do that with google fonts because it's all open source, which is great Uh, you can't do that with closed source fonts for various Contractual and legal reasons. I mean check with your your your service that you use Maybe they do allow it. Maybe they don't but I think yeah Some will allow it, but only if you pay them A bazillion dollars, you know, they tend to up the price for doing that, which is not great So what you can do is you can do something like this. You can async load your css So this is using a preload tag to load some css with high priority And then you've got the actual, uh, Your style sheet tag there initially uses a print media Which means it will load low priority But that's so your preload will bump the priority back up, but it means it won't block the rendering of the page either And then once it loads you switch the media And it applies to the page. This is some arcane javascript magic, by the way Yes, well, this is the the filament group came up with this and it used to be a lot worse Um before we had things like preload that to be able to do this So this is much better than it used to be Um, you'll also want to use the font loading api to provide a smooth transition because this will this will just do swap Swap fonts Uh, unless you add some css to change that you can add as much css as you want to control this process with the font loading api so There you go Not easy But it's okay for font services. Uh, that won't let you do anything better than this It's better than blogging rendering for all of that time All right, okay into the final few ones Layout instability And this is this is a big one. Um It's kind of different to the other ones because it might not be part of your Main content code. It might not be part of your first interaction code But if something comes in late and adds stuff to the page which moves stuff around Then your core content isn't ready. Like if your user's reading something and it moves some under them It's not ready yet. It's so frustrating um to avoid it like JavaScript should enhance what's already there in the DOM Uh, so if you've got an image carousel You would start with the first image there and it would be, you know The correct width and height taking up space on the page And then the JavaScript comes in and adds the buttons Or hydrates that part of the page depending on what terminology you're using But adding those buttons those buttons would just appear rather than shifting around of a content on the page It's just yeah horrible user experience when stuff shifts around And i'm really glad that we're we're using metrics now to Call out sites which which have a really bad experience here um Yeah, so test your pages on a slow connection and ensure stuff doesn't move around Uh one special mention I would say uh a lot of sites still do this Where uh this image will take up almost no space on the page And then the browser will download enough of the image to know its width and height and then pop It will take up the the correct aspect ratio space on the page and everything else shifts around Don't have to do this anymore If you give the image a width and a height doesn't have to be Correct just the correct aspect ratio And then auto height The browser will reserve space for that image. No shit, which is great And with the aspect ratio css property, you can give the same behavior to things that are not images If you have something that hasn't any content in it, but you want to reserve Something with a certain aspect ratio use the aspect ratio css property. Yes. What is the browser support good enough for that yet? I thought so. I will put a link in the description. I'm gonna do some I'm gonna put do some really quick live Can I using excellent live fact-checking aspect ratio? And I think it's in firefox. It might not be in safari No, I well the thing is that yeah, it might it's not in 14.1 So yeah, maybe it's not ready yet, but I feel like they were deeply involved in specking this It is in the next firefox next firefox next chrome. Oh, there you go. That's yeah I I've been wanting that forever good bit of aspect ratio indeed But this image thing landed much sooner. It's still relatively new like in terms of the age of the web But it's you know, it works across all browsers now, which is really nice. You don't get that layout shift You don't have to use the padding hacks that is a sort of stuff. Oh god the padding egg I'll put a link to that as well in case anyone's trying to target some super old browsers Next We're at number two now. This is over bundling Um So this is a little or as I call it under splitting under splitting That's a better name for it. And yeah, it's a form of inlining, isn't it? But this is mostly about CSS and JavaScript But inlining JavaScript in JavaScript and inlining CSS in CSS And it's it's much more common of a problem A lot of sites will have one javascript file for their whole site Or one css file for their whole site and that means any given page the user is downloading Like a chunk of the website the entire website just to get to that first interaction or even first render the google io website If you visit like The link to our talk You download but before you even get to render you download all of the animation data for the home page Even though you are not on the home page I like no It's like 600k or whatever is it's absolutely massive like Also the google io website it I feels okay to Say nasty things about one of our own sites. I know it's it's you know Don't want to do it too frequently to other people's websites, but oh good god the google io website isn't great Is it and they've also got like all of the ui strings in a bunch of other languages? Like most users are only going to see one language, but It's like the risetta stone in there, mate It's It's incredible Anyway, don't don't do that Chrome DevTools has this excellent coverage report that you can do You reload your page and it'll tell you how much of your javascript and css is being used Uh, it's it's a good way to identify a problem early on Like sometimes you've got a huge bit of javascript that is Used but you shouldn't need that much javascript to do a thing You know this won't highlight that but you can see in this case There's a bunch of javascript being downloaded that isn't being used Just because there's some script unused isn't a problem because if it's part of your everything else low priority bundle That's fine But for your blocking render stuff or for your first interaction stuff You want to see a high coverage there because you just want it to contain the stuff that you really really need We built a website remember this one. I I do We looked at various bundlers to see you know how they do things and one of the things we looked at is code splitting Uh, so the information is here for a bunch of different Bundlers for how you would split that out and ideally have an entry point for every Type of page on your site not literally every page But like on the google io website You would have one entry point for the home page and one entry point for uh, the page that displays the information about an individual session All right, we're at the end now It's the final one number one. Oh and it is this Uh content loaded with JavaScript The fastest way to get to first render on your page is html and css And doing it with JavaScript is always going to be slower Like if you really really optimize things you can get close But it will always be slower And usually it is a lot slower because you I mean by very definition the index html file is the first one that the browser loads like everything else will come in later Yeah, and you and so the more you have in there the better you're doing You can end up with a pattern like this where your html downloads and then you know the browser goes There's some JavaScript i'll download that and then the JavaScript downloads and it executes and whatever and then the JavaScript Goes but actually I need some data from this Free interface jason file and so go and fetch that and then i'll look through that and find the data and put it on the page It's it's slow it's slow and there are cases where it's your only option depending on what apis you're using or whatever, but Really it's very few But it's a pattern i see in the wild a lot and it is very slow Even a static render that is just a ui Shell will really help with this perception of performance You know Even if it's fairly basic at least the user gets something other than just a white screen But even better if you can do a content render just using your html and your css And I i'm going to be shamelessly plugging the talk that the two of us gave at jamstike conf Where we go through these steps like we We send a shell we teach our build system to build a shell for a highly interactive web app a game And try to cut down the javascript required to get the first interaction going And the game of all isn't that small so that that walks you through those steps Yep, that's a talk that we rehearsed to death We spent so much effort rehearsing it and then like I did the video edit myself because the Conferences video didn't come out very well and about 300 people watched it. So yeah. Yeah, we'll send more people to that video Get my money's worth out of that one I do want to call out a specific Form of this problem, which I've seen a couple of times and I didn't I didn't realize how Bad it was at first It's when this happens So I think this happens When the developer will notice a lot of layout shifting on the page as their JavaScript is loading in So they'll hide it With an overlay that might have a loading spinner in or to say the word loading or something And then the main JavaScript loads And they remove That overlay ta-da This suffers from a priority issue So if you've got a blocking bit of JavaScript in the head of your page The browser's like whoa I am going to fire all the bandwidth at that because that is blocking rendering. It does the same with css And it will do this like sort of the same fonts as well a different phase And then things like images if they're in the viewport it starts pouring bandwidth into those That the browser tries to do this so it gets the the fastest load time Of course it does But this tricks the browser Because it sees the script at the bottom of the page and goes Yeah Not important. Not important. You already have your nice black overlay with a spinner. The user is happy. We've got a bunch of content on the page here And that that's going to include images and css backgrounds So I better get those ready like in parallel with the JavaScript and that that's what happens It it tends to the images End up the same priority or even higher priority than that script at the bottom Yeah, you've created a a blocking experience But not one that the browser actively recognizes as a blocking experience So your recommendation is put the spinner first put a blocking script in order to first script in the middle and then the content after right Do you know what that would be faster? That's the thing that would actually be faster, but no like the the truly Yeah, the best thing you could do here is a proper static render That gives you the contents with with no layout shifting Or if you have this problem if you do just want to do a quick fix Link roll preload as script in the head of the document there and the browser will bump the priority of that script loading at least That's not a perfect solution. But if you've got 10 minutes, that is our solution that will improve things massively Especially depending if you've got a few big images on the page And that's all I've got Um, I'll put some links into the articles I wrote where I looked at individual sites. Um, that includes videos You can see how many seconds are added by each of these You know performance gotcha pitfall things and how fast things could be if you know alternatives were used which are much better for performance and and we're gonna link to our talk and all of you Watching should watch that one because we need more views on that one. Yes, please. Thank you very much Uh, but yeah, please please go and do that So close to the end so close to the end Why didn't I'll wing it. I'll just wing it. I don't need notes I've got the oldest in my head. I've been doing this job for 20 years All right, well that's some good b-roll