WEBVTT 00:00.000 --> 00:10.440 Anyway, it is time now, so we're going to start. 00:10.440 --> 00:15.400 Before I start, though, I think we should address the elephant in the room, which is my 00:15.400 --> 00:16.400 hair. 00:16.400 --> 00:18.640 Obviously, you might be wondering what's going on with that. 00:18.640 --> 00:24.320 Well, for a long time now, I have become what is typically called follically challenged. 00:24.320 --> 00:25.320 Okay? 00:25.320 --> 00:26.680 I've been going quite bald. 00:26.680 --> 00:33.560 And like many men in my situation, I just decided to go to Turkey to get a hair transplants. 00:33.560 --> 00:48.480 Now, little bit, I know that the clinic that I chose, not part of the gang. 00:48.480 --> 00:52.360 Little bit, I know that the clinic, the hair transplants clinic that I chose, only use 00:52.360 --> 00:57.800 this hair, donated by browser developers. 00:57.800 --> 01:02.480 I don't really like Zen AI, but for this kind of thing, I like to make an exception, 01:02.480 --> 01:05.480 just get everything so wrong. 01:05.480 --> 01:08.560 Am I trying to say that all browsers developers are clowns? 01:08.560 --> 01:09.560 No. 01:09.560 --> 01:10.560 Okay? 01:10.560 --> 01:13.200 They sometimes do seem to do some clowning things, though. 01:13.200 --> 01:14.200 Okay? 01:14.200 --> 01:18.120 Case in point, what we're going to talk about today is that some of the browsers do 01:18.120 --> 01:22.160 with I, it's called a two phase or a two step loading process, where they don't load 01:22.160 --> 01:26.480 everything on the page at once, they load one part, and when that's done, they start 01:26.480 --> 01:30.920 loading the second batch of resources. 01:30.920 --> 01:36.480 Because of this, you get rear situations like this, where we have three very different 01:36.480 --> 01:42.360 waterfalls in the tree browsers for the exact same HTML page. 01:42.360 --> 01:45.880 Same HTML, and it's a very simple one we're going to show it later. 01:45.880 --> 01:50.840 All HTML still loads radically different in all the three main browsers. 01:50.840 --> 01:55.720 Now you tell me, that is not a bunch of clowns trying to take on their audience with 01:55.720 --> 02:00.440 superjumps, okay? 02:00.440 --> 02:04.840 So what I'm going to try to do today is try to explain why this happens, why these loading 02:04.840 --> 02:09.800 behaviors are there, and then maybe also give some ways to try and combat these inconsistencies 02:09.800 --> 02:11.520 between browsers. 02:11.520 --> 02:16.840 So let's start with the Y, and it turns out that it's not the browser developers who 02:16.840 --> 02:21.360 are the clowns, it's usually more the server developers, okay? 02:21.360 --> 02:25.080 You wouldn't believe the weird stuff that servers do. 02:25.080 --> 02:30.600 This one, for example, send back, I requested images in one, two, three order, it send 02:30.600 --> 02:32.800 back in, three, two, one, okay? 02:32.800 --> 02:37.600 And in this case, the first image that's up on there was my largest contentful paint 02:37.600 --> 02:42.560 image, so the most important image on the page, and when a Google looks for a looks 02:42.560 --> 02:49.120 out for SEO things, so that was delayed behind these two other less important images. 02:49.120 --> 02:52.760 It's not just these simple examples either, this is a more complex one, where a very 02:52.760 --> 02:58.160 important JavaScript on top, and some important fonts also were being delayed by a bunch 02:58.160 --> 03:00.600 of images, these purple things in the middle. 03:00.600 --> 03:04.280 A ton of images that I really didn't need at that point, I really wanted to JavaScript 03:04.280 --> 03:09.760 first, but the server was sending me other stuff than I had requested. 03:09.760 --> 03:12.320 Now, you might think, Robin, how is that the server's fault? 03:12.320 --> 03:15.960 How is the server supposed to know what it needs to send? 03:15.960 --> 03:23.200 Well, because the browser literally tells the server what it needs to send when, this 03:23.200 --> 03:27.880 is only called the prioritization system, so the browser is basically going to assign 03:27.880 --> 03:33.160 a priority, a level of importance to each type of resource it's discovers. 03:33.160 --> 03:40.200 For example, when they're blocking CSS in the head, super important, highest priority. 03:40.200 --> 03:43.480 Partial blocking JavaScript is also important, high priority. 03:43.480 --> 03:48.200 The third JavaScript, if you add the third, that means that the browser can execute 03:48.200 --> 03:53.920 this JavaScript after the main page is done loading, so it doesn't really have to execute 03:53.960 --> 03:57.840 or download immediately, so it gets a low priority. 03:57.840 --> 04:01.600 Then you have things like preloads, things that the browser knows it might need, but 04:01.600 --> 04:05.240 not discoverable right now, might get a medium priority. 04:05.240 --> 04:10.600 The browser actively tries to guess which things are most important when, and it communicates 04:10.600 --> 04:12.200 this to the server. 04:12.200 --> 04:16.760 The way the data does this are difficult to explain, most modern browsers you can now see 04:16.760 --> 04:18.080 this in a request header. 04:18.080 --> 04:22.640 There's literally a priority request header that tells you when which resource should 04:22.640 --> 04:24.640 be coming in. 04:24.640 --> 04:31.640 This is very important, especially for HTTP 2 and 3, because they use a single underlying 04:31.640 --> 04:35.320 TCP or quick connection to send the resources on. 04:35.320 --> 04:39.880 They have one connection for many different things, and if they get the order wrong, 04:39.880 --> 04:43.960 there's not going to be room on that connection for the more important stuff if you keep 04:43.960 --> 04:47.960 sending me low priority images server. 04:47.960 --> 04:51.960 So it is important if we get these orders straight, and again it's a server who often 04:51.960 --> 04:53.640 make mistakes in this. 04:53.640 --> 04:56.080 This is research I did a couple of years ago. 04:56.080 --> 05:00.960 The top is what the browser sends, this is the browser is expecting to see that. 05:00.960 --> 05:08.640 You can see a lot of some very well-known servers, get it nearly right, Apache, not quite 05:08.640 --> 05:14.200 right, and then completely wrong, no chase. 05:14.200 --> 05:19.120 The thing is this last one is actually one of the worst possible cases for but performance. 05:19.120 --> 05:23.080 If you send your resource like this, your page is going to take a very, very long time 05:23.080 --> 05:24.080 to load. 05:24.080 --> 05:28.760 You might say Robin, oh, the research you did a couple of years ago, since then we have 05:28.760 --> 05:33.200 HTTP 3, everything is much better, right, right. 05:33.200 --> 05:39.560 I did research again last year, this is very fresh, looked at a ton more, very well-known 05:39.560 --> 05:46.880 companies in hosting the virus only 2, 2 out of all of these, get this right, it's not 05:46.880 --> 05:51.600 that everyone else gets it completely wrong, okay, there's a lot of great area in there, 05:51.600 --> 05:56.320 but still only 2 of these actually do what they're supposed to do and listen to what 05:56.320 --> 05:59.440 the browser is telling it, okay. 05:59.440 --> 06:03.920 So with that in mind, imagine that you are one of these people, okay. 06:03.920 --> 06:09.760 One of the browser developers, how would you deal with this, right? 06:09.760 --> 06:14.040 You have a browser you see in your analytics coming in, a lot of servers are not listening 06:14.040 --> 06:17.080 to us, they're doing very weird stuff. 06:17.080 --> 06:22.600 How can we protect ourselves against that if the server isn't even listening, okay? 06:22.600 --> 06:27.000 And one of the ways they do that is a thing that I mentioned before, this two-phase loading. 06:27.000 --> 06:32.800 The idea there is, let's say you have a web page with 100 resources, if you request 06:32.800 --> 06:38.040 all 100 of them at the same time, which you could, it's allowed in HTTP 2 and 3, should 06:38.040 --> 06:43.680 be possible, if you do 100 at the same time, the server has a 100 different ways to 06:43.680 --> 06:44.680 mess it up. 06:44.680 --> 06:54.400 However, if you only request the top 10, or maybe top 20, most important resources first, 06:54.400 --> 06:58.960 and you delay the 80 other ones until those are done, then yes, the server is still going 06:58.960 --> 07:04.560 to mess up those 10 to 20, but at least only those at the beginning, you're not going 07:04.560 --> 07:09.760 to be delaying your JavaScript for very low priority images down the line, right? 07:09.760 --> 07:16.760 So that's kind of one of the main reasons that we have this set up, so browsers trying 07:16.760 --> 07:21.760 to protect themselves against Rome servers, not the only reason this is still around, 07:21.760 --> 07:24.920 but one of the main reasons that we have it. 07:24.920 --> 07:29.520 And because of that, it's one of the main reasons that we get these very different waterfalls, 07:29.520 --> 07:36.960 because of course, of course, none of the browsers agree on how to best do this to face 07:36.960 --> 07:39.120 loading thing, okay? 07:39.120 --> 07:42.800 All of them have a different opinion on how to best do that. 07:42.800 --> 07:47.200 And when I started, it was very frustrating, because almost none of this was documented 07:47.200 --> 07:49.080 at all. 07:49.080 --> 07:56.200 The only thing that we had was a Google Doc from one of the chromium developers that had 07:56.200 --> 07:59.640 a very short description of what this was doing, we're going to look at it soon, very short 07:59.640 --> 08:04.320 description, and that was it, super vague, super difficult to interpret, there was nothing 08:04.360 --> 08:07.200 for Safari, nothing for Firefox. 08:07.200 --> 08:13.520 This has since slightly improved with a couple of articles, may or may now be due to some 08:13.520 --> 08:18.880 of my nagging to be honest, but still it's very under documented what this does and how 08:18.880 --> 08:23.160 it does it, so that's why I'm doing this talk today. 08:23.160 --> 08:27.880 Because of this, because of the under documentation, I had to do a lot of my own research, 08:27.880 --> 08:31.480 so I've been spent a lot of weeks, setting up different types of sites, trying out 08:31.480 --> 08:35.400 them in the different browsers to get this working. 08:35.400 --> 08:40.080 So I'm going to present to you my research now, and because I know that the academics 08:40.080 --> 08:48.080 like that, I'm going to try to change it to a bit more formal wear, like this, to get 08:48.080 --> 08:50.160 the mic going, there we go, very nice. 08:50.160 --> 08:51.560 So let's talk about the results. 08:51.560 --> 08:58.400 I'm going to talk about Chrome first, because it has the most complex and most evolved 08:58.400 --> 09:01.880 system in here, so we can get all of the concepts from Chrome, and then we can look 09:01.880 --> 09:04.600 at Safari and Firefox next. 09:04.600 --> 09:10.560 So again, Chrome, for a long time, all we had was literally these four lines in that Google 09:10.560 --> 09:15.920 doc, that's all you got, and we're going to read them now, they're not very intelligible. 09:15.920 --> 09:19.200 So Chrome loads resources in two phases. 09:19.200 --> 09:25.840 Tight mode is the initial phase and constraints loading lower priority resources, so 09:25.880 --> 09:32.840 it delays lower priority resources until the body is attached to the document, until the 09:32.840 --> 09:34.760 body is attached to the document. 09:34.760 --> 09:41.920 I have no clue what he's saying, luckily the writer anticipated my stupidness, they actually 09:41.920 --> 09:45.440 added another line to say, what does that mean? 09:45.440 --> 09:52.240 It means essentially after all blocking scripts in the head have executed, so all blocking 09:52.240 --> 09:58.760 JavaScript in the head has to be done executing before tight mode can exit. 09:58.760 --> 10:01.320 Keep that in the back of your mind, that's going to be important. 10:01.320 --> 10:06.160 Last sentence is, in tight mode, low priority resources are only loaded if there are less 10:06.160 --> 10:10.600 than two in flight requests at the time that they are discovered. 10:10.600 --> 10:14.800 I'm not going to explain that one, we're going to see a couple of examples of that later, 10:14.800 --> 10:19.520 but I hope you can agree with me, this was not clear at all what the browser was trying 10:19.520 --> 10:20.520 to do. 10:20.840 --> 10:26.240 So I had to put on my academic where. 10:26.240 --> 10:30.480 First thing we need to understand is what do these lower priority resources mean? 10:30.480 --> 10:33.240 It delays lower priority resources, what does that mean? 10:33.240 --> 10:42.120 Well, Chrome has a specific way of giving priorities to resources, HTML and CSS are going 10:42.120 --> 10:46.960 to be highest priority, JavaScript in the head, so the synchronous blocking JavaScript is 10:46.960 --> 10:48.560 going to be high. 10:48.560 --> 10:53.640 One kind of depends, asynchronous and defer JavaScript is obviously going to be less important 10:53.640 --> 10:59.280 because it executes later in the pace load, so Chrome gives it a low priority, similar 10:59.280 --> 11:02.880 to images in the body, they also get a low priority. 11:02.880 --> 11:09.960 Now, when the document says low word priority, it actually means medium, low and lowest. 11:09.960 --> 11:14.080 So during tight mode, that first initial phase only highest and high resources will 11:14.080 --> 11:21.200 be loaded, everything else Chrome intentionally delays until that is done. 11:21.200 --> 11:25.280 And I can very easily illustrate that with this very simple page. 11:25.280 --> 11:30.560 These are just two rendered walking JavaScript, so synchronous JavaScript in the head and 11:30.560 --> 11:32.640 then 10 images. 11:32.640 --> 11:36.560 And I've intentionally delayed those JavaScript, the server waits two and a half seconds 11:36.560 --> 11:37.960 until it starts replying. 11:37.960 --> 11:43.400 So you go clearly see that while the browser has discovered all 12 resources at the same 11:43.400 --> 11:50.800 time, it waits requesting the images until the two JavaScript are done. 11:50.800 --> 11:54.760 Wait to requesting them, not even downloading them, requesting them until the two JavaScript 11:54.760 --> 11:59.800 are completely done loading, clearly showing that there is this tight-moting going on. 11:59.800 --> 12:04.560 Now, this is what you would have seen in Chrome about a year and a half ago. 12:04.560 --> 12:08.520 If you do this now, you will see something more like this. 12:08.520 --> 12:12.840 There are suddenly five of those images are being loaded in that tight mode at first 12:12.840 --> 12:14.960 phase as well. 12:14.960 --> 12:20.240 And this is because about a year and a half ago Chrome made a change to its priority system, 12:20.240 --> 12:26.320 where it says the first five images on the page are not the default low priority, they 12:26.320 --> 12:28.320 are now the medium priority. 12:28.320 --> 12:34.600 The idea being that that largest commonful pain image is probably one of those first 12:34.600 --> 12:40.360 five, so if they make this change at a browser level, they might improve LCP times where 12:40.360 --> 12:44.680 the internet as a whole, that was the idea behind this. 12:44.680 --> 12:50.760 You might be still be confused because medium is still not allowed in tight-mote, but 12:50.760 --> 12:53.040 still they were downloading in tight-mote. 12:53.040 --> 12:57.880 So they also update the tight-mote logic saying that from this point on, tight-mote 12:57.880 --> 13:04.160 can also load two medium priority resources at a time. 13:04.160 --> 13:08.840 That explains what we saw then, so we have the two JavaScript's tight-mote, and then 13:08.840 --> 13:13.560 there are two medium at the time, so the first five images, the first two can start. 13:13.560 --> 13:18.400 When those are done, we have allowance for two more, two slots open up, those and then 13:18.400 --> 13:20.440 there's one just left over, gets loaded. 13:20.440 --> 13:25.440 And then we again have to wait until the end of tight-mote before requesting the next 13:25.440 --> 13:26.440 images. 13:26.440 --> 13:30.320 So that's the basics of this. 13:30.320 --> 13:36.200 So let's get to that weird, lost sentence of that paragraph that I showed before. 13:36.200 --> 13:42.760 Low priority resources are only loaded if there are less than two other in flight requests. 13:42.760 --> 13:46.920 So what I've done here is the same page, but I've just delayed the first JavaScript a bit 13:46.920 --> 13:47.920 less. 13:47.920 --> 13:54.200 It already returns after, I guess, a second and a half, but the other one keeps running. 13:54.200 --> 13:58.480 So what you have from the point that the first JavaScript completes, there is only one 13:58.480 --> 14:04.320 high priority resource in flight, that JavaScript, which means we can now start loading one 14:04.320 --> 14:08.680 lower priority resource as well, which is the first image. 14:08.680 --> 14:12.840 So that one gets done, again, a slot opens up for a low priority image, the next one, 14:12.840 --> 14:17.800 the next one, the next one, the next one, that's one so forth until tight-mote is done. 14:17.800 --> 14:21.520 So that's what that second sentence means. 14:22.520 --> 14:24.640 How does that still make sense? 14:24.640 --> 14:28.480 Because from now on, it's gloves off. 14:28.480 --> 14:34.800 Something that I found very surprising is that tight-mote really is only while they're 14:34.800 --> 14:40.440 blocking scripts being downloaded, not CSS. 14:40.440 --> 14:44.920 This is a very similar page, just without JavaScript and just three CSS files in the 14:44.920 --> 14:45.920 head. 14:45.920 --> 14:51.640 And even though the CSS files were rendered blocking, there is no tight-mote. 14:51.640 --> 14:56.320 Everything gets requested at the same time, because tight-mote is only triggered by scripts 14:56.320 --> 14:57.320 in the head. 14:57.320 --> 15:03.720 Very surprising to me was even surprising to browser developers at Chrome that I talked to, 15:03.720 --> 15:07.440 because they thought it was included. 15:07.440 --> 15:08.440 Fantastic. 15:08.760 --> 15:14.360 So now that you guys all know the basics, it's time to put that to the test. 15:14.360 --> 15:17.720 I'm going to ask you to think a little bit for yourself. 15:17.720 --> 15:20.720 You don't have to shout out anything just think for yourself. 15:20.720 --> 15:25.760 Given this page, what is that going to look like in a waterfall? 15:25.760 --> 15:26.760 And why? 15:26.760 --> 15:27.760 How is this going to get loaded? 15:27.760 --> 15:33.080 So we have two rendered blocking javascripts of high priority, two deferred javascripts, 15:33.080 --> 15:35.760 which in Chrome are going to be low priority. 15:35.760 --> 15:39.320 And then we have our 10 images again, first five, or medium, and then we have five 15:39.320 --> 15:40.320 lows. 15:40.320 --> 15:57.800 10 seconds, imagine what the waterfall is going to look like. 15:57.800 --> 16:03.440 Now we realize this is a bit difficult to really do this, you kind of need a nose for 16:03.440 --> 16:08.560 these kinds of things. 16:08.560 --> 16:11.160 So let's see. 16:11.160 --> 16:15.920 What basically happens is we first download those two high javascripts, I priority javascript 16:15.920 --> 16:21.080 images in tide mode, along with the five medium priority images. 16:21.080 --> 16:26.680 And then after tide mode is done, only then do we request the deferred javascript and the 16:26.680 --> 16:28.720 rest of the images. 16:28.720 --> 16:33.160 Now I hope this is somewhat obvious given the explanation I did just now. 16:33.280 --> 16:35.400 It just followed these priorities. 16:35.400 --> 16:36.480 That's what it does. 16:36.480 --> 16:40.240 To me, when I started out web development, and even a couple of years ago, this would not 16:40.240 --> 16:42.760 have made any sense. 16:42.760 --> 16:46.760 I would have thought things in the head of the page should be much more important than 16:46.760 --> 16:51.520 anything in the body, that's why we have the head versus the body, right? 16:51.520 --> 16:54.320 This is clearly no longer the case. 16:54.320 --> 16:57.640 And this might be obvious for some of you here, I can pretty much guarantee that, 16:57.640 --> 17:02.440 especially for newer programmers, newer developers, this might come as quite a shock. 17:02.440 --> 17:06.000 When they first discover this. 17:06.000 --> 17:12.360 So this is Chrome, Chrome really follows the priorities to determine tide mode. 17:12.360 --> 17:17.040 Let's talk about Safari. 17:17.040 --> 17:19.080 Yeah. 17:19.080 --> 17:24.760 For those in the know that it's not very polar, by the way, that's someone else. 17:24.760 --> 17:28.200 Safari, very interesting, I did the exact same test. 17:28.200 --> 17:30.320 So Chrome is on top Safari on bottom. 17:30.360 --> 17:33.080 You can immediately see two clear things. 17:33.080 --> 17:36.800 Once Safari clearly has that tide mode. 17:36.800 --> 17:41.440 It is still delaying requesting those images until the JavaScript is done. 17:41.440 --> 17:42.800 So it has a tide mode. 17:42.800 --> 17:46.280 Second thing, it doesn't do that medium priority thing for the first five images 17:46.280 --> 17:47.280 that Chrome does. 17:47.280 --> 17:52.840 It's still basically what Chrome is doing up until you're in half a go. 17:52.840 --> 17:55.800 It also does that weird. 17:55.800 --> 17:59.880 You can download lower priority things if there are only one other thing in flight at the same 17:59.880 --> 18:00.880 time. 18:00.880 --> 18:03.880 That's also the same as Chrome, very clear. 18:03.880 --> 18:09.480 Again, here are the similarities and everything goes in different directions. 18:09.480 --> 18:15.760 For example, I just told you that Chrome doesn't really care about CSS in the head for 18:15.760 --> 18:17.120 tide mode, only scripts. 18:17.120 --> 18:20.160 Well, Safari does, because of course it does. 18:20.160 --> 18:25.320 And Safari, if you have CSS in the head, it is going to trigger tide mode and it is going 18:25.320 --> 18:31.800 to delay images or more priority stuff until the CSS is downloaded. 18:31.800 --> 18:38.320 Very, very clear difference between it too. 18:38.320 --> 18:43.320 Then I decided, let's look at what happens if I move my JavaScript outside of the head. 18:43.320 --> 18:47.360 Because again, Chrome says only blocking stuff in the head. 18:47.360 --> 18:52.120 So if I put the same exact same JavaScript on top of the body, which by the way is still 18:52.120 --> 18:58.320 partial blocking is still going to stop rendering the page, same effect, but Chrome doesn't 18:58.320 --> 18:59.320 really care. 18:59.320 --> 19:00.840 It says, oh, it's not on the head. 19:00.840 --> 19:04.120 I don't need tide mode, I'm just going to request everything at the same time. 19:04.120 --> 19:05.520 Safari does not. 19:05.520 --> 19:12.200 Safari indeed says, this is a blocking JavaScript, everything after it should be blocked. 19:12.200 --> 19:15.720 And I thought, okay, that's going to be everything after it, so I wanted to verify that, 19:15.720 --> 19:21.440 so I put everything on the bottom of the page, you can indeed see Safari seems to do what 19:21.440 --> 19:22.440 I thought it does. 19:22.440 --> 19:31.160 Nothing before the JavaScript are being blocked, so just to be sure, just to cover all 19:31.160 --> 19:36.800 my bases, I had to go ahead, I had to do it and put the JavaScript in the middle of the 19:36.800 --> 19:38.800 page. 19:38.800 --> 19:46.040 I mean, at least Chrome is consistent. 19:46.040 --> 19:49.880 Safari, I tried, I really tried to find out what the hell it is doing. 19:49.880 --> 19:53.320 I couldn't find the logic that they're doing sometimes. 19:53.320 --> 19:57.480 They do block stuff before, sometimes not, sometimes even block things after. 19:57.480 --> 20:02.440 It's very inconsistent, but it is clear that they do some more advanced logic and Chrome 20:02.440 --> 20:06.680 when it comes to resources in the body, okay. 20:06.680 --> 20:13.880 So slightly more difficult exercise, exact same HTML people, exact same, I didn't change 20:13.880 --> 20:16.760 anything about the HTML. 20:16.760 --> 20:44.280 What is this going to look like in Safari? 20:44.280 --> 20:55.200 So let's see, Safari obviously has time mode, what is requested in time mode, the 20:55.200 --> 21:03.680 high priority JavaScript, but also the deferred JavaScript as well, right, and I tested 21:03.680 --> 21:09.720 this further, even if there is no synchronous JavaScript, what's going to happen, Safari 21:09.720 --> 21:14.920 is not going to trigger type mode for deferred asynchronous JavaScript, so by itself it 21:14.920 --> 21:20.760 won't trigger type mode, if it's not going on, but if type mode is in effect, they will 21:20.760 --> 21:26.160 get requested during type mode, just to make things easy for web developers. 21:26.160 --> 21:33.160 And again, to reinforce, this is what it looks like, Chrome, very, very different in Safari 21:33.160 --> 21:36.160 because they fundamentally treat these things differently. 21:37.160 --> 21:43.160 So for Chrome, I kind of can't know what's going on now, it's kind of what the dog says. 21:43.160 --> 21:47.720 Safari, I'm still a bit in the dark, I have the high level things that they do, but they still 21:47.720 --> 21:53.520 have some weird characteristics going on there like with Async and Defer that I don't know 21:53.520 --> 21:58.720 why they're there, what the logic is behind them, or how consistently they're being applied. 21:58.720 --> 22:01.160 Okay. 22:01.160 --> 22:05.840 That's Chrome and Safari, let's go to Firefox. 22:05.840 --> 22:09.320 This is a little bit dangerous for me right now because there are a ton of resilience 22:09.320 --> 22:10.320 in the room. 22:10.320 --> 22:13.320 Please don't kill me. 22:13.320 --> 22:21.560 For Firefox, I can actually be quite short, it doesn't do type mode at all. 22:21.560 --> 22:26.520 Whatever you put on your page, Firefox is very happy to just request it all at the same 22:26.520 --> 22:27.520 time. 22:27.520 --> 22:28.520 Thank you very much. 22:28.520 --> 22:31.760 That's a server development. 22:31.840 --> 22:37.200 It's a way the most pure of the three browsers because it trusts in the standards, it trusts 22:37.200 --> 22:41.640 in the networking algorithms that they will get it right. 22:41.640 --> 22:47.440 Now I did this talk a couple of months ago and I didn't explain this further and it 22:47.440 --> 22:53.720 talked up post it to YouTube and I got a lot of views including some of the Firefox 22:53.720 --> 22:55.720 fine club. 22:55.720 --> 23:00.000 Apparently these guys have a lot of very passionate, very vocal fans who believe that 23:00.040 --> 23:05.520 Firefox is the best browser and they kind of misinterpreted what I was saying. 23:05.520 --> 23:09.000 They thought that I said, oh, it doesn't do type mode, which means it is somehow the 23:09.000 --> 23:13.680 worst browser or the slower browser of the three, that's not what I was trying to say 23:13.680 --> 23:14.680 at all. 23:14.680 --> 23:20.160 In fact, you could argue that for servers that do it correctly, Firefox should be a little 23:20.160 --> 23:25.400 bit faster because every thing, the server can correctly prioritize things and it can 23:25.400 --> 23:29.680 start filling caches, start pulling things in the room and origin if you're a CDN. 23:29.680 --> 23:35.720 So it should actually be faster for proper servers and even on servers that make mistakes, 23:35.720 --> 23:39.360 it's highly going to depend on what the server is doing and the web page, if that actually 23:39.360 --> 23:42.160 matters that much in practice. 23:42.160 --> 23:47.160 So I'm not trying to say the far from somehow the worst browser for not doing type mode, 23:47.160 --> 23:53.400 the main message again I'm trying to bring is it's crazy that all three browsers handle 23:53.400 --> 23:58.120 the same simple HTML page in such different ways. 23:58.120 --> 24:03.600 It is very confusing and very annoying if you try to make a web page that will perform 24:03.600 --> 24:06.800 well in all the three browsers. 24:06.800 --> 24:11.600 And for a long time, it was even more annoying even more confusing because there was actually 24:11.600 --> 24:16.440 no way that you could manipulate the browser so you could tweak the behavior there was no 24:16.440 --> 24:17.840 way to do that. 24:17.840 --> 24:22.800 Let's say the browser gets it wrong and there's something in type mode that should be not 24:22.800 --> 24:23.800 or vice versa. 24:23.800 --> 24:27.800 There was no way for you to manipulate that and you were stuck with the browser was doing. 24:27.800 --> 24:36.280 Now luckily over time people got the message that we needed some kind of mechanism to 24:36.280 --> 24:39.560 improve this, to be able to deal with these browser consistency. 24:39.560 --> 24:50.040 We needed a weapon of our own in the fights against the browsers and this used to be a balloon 24:50.040 --> 24:55.480 sword but the radiators are way too warm. 24:55.480 --> 24:57.640 That's a popping you've heard at the beginning. 24:57.640 --> 25:04.080 So let me use my backup, let's go on the katana, let's see that. 25:04.080 --> 25:13.080 The weapon that we eventually ended up with is something called fetch priority. 25:13.080 --> 25:18.560 You can now add fetch priority to just about anything like a ton of things can now be manipulated 25:18.560 --> 25:23.440 with fetch priority and that directly influences that priority that the browser decides to 25:23.440 --> 25:25.600 be given resource. 25:25.640 --> 25:28.360 You don't set the priority directly. 25:28.360 --> 25:33.280 You can only do fetch priority high or low, not highest or lowest or medium, that's all 25:33.280 --> 25:34.280 where it works. 25:34.280 --> 25:38.760 What you're basically telling is the browser, it should be a little bit higher than what 25:38.760 --> 25:45.200 you might think it should be or lower than what the browser thinks, not the fixed priority. 25:45.200 --> 25:48.240 We're going to see that creates issues of its own. 25:48.240 --> 25:53.760 But with that, that is a very powerful tool to indeed try and move some things around 25:53.760 --> 25:56.520 in the page loading process. 25:56.520 --> 26:00.960 For example, if you have something in the second phase that you want to get in the 26:00.960 --> 26:07.120 tight mode, that's very easy to do in Chrome because, again, it's all priority based. 26:07.120 --> 26:11.760 So far, it's slightly more difficult because it has other heuristics and practice 26:11.760 --> 26:14.440 I only found this to work for images. 26:14.440 --> 26:19.360 But that is the most important use case anyway, which is trying to put fetch priority 26:19.360 --> 26:21.320 high on your LCP image. 26:21.360 --> 26:24.920 So you're going to just come up with a page image that one image that Google looks at 26:24.920 --> 26:27.200 for its metrics. 26:27.200 --> 26:31.720 If that is in the second phase, it's going to be slow. 26:31.720 --> 26:36.200 Which fetch priority high you can bring this into the tight mode phase, so it loads much 26:36.200 --> 26:37.200 earlier. 26:37.200 --> 26:41.400 Both in Safari and in Chrome, yes, I kept the slide in. 26:41.400 --> 26:44.520 It's slightly more difficult to see in Chrome because it has weirder waterfalls. 26:44.520 --> 26:50.640 But here again, the fifth image there will get requested at high priority early on because 26:50.640 --> 26:51.640 it is the LCP image. 26:51.640 --> 26:58.080 That's one way you can get things into tight mode, then you might also want to get things 26:58.080 --> 26:59.080 out of tight mode. 26:59.080 --> 27:00.640 The browser is too eager. 27:00.640 --> 27:05.120 You know that you won't need this resource early on, so you're explicitly telling 27:05.120 --> 27:07.200 the browser, please back off a little bit. 27:07.200 --> 27:10.880 Again, Chrome works very well, fetch priority low works very well, and it's a variety of 27:10.880 --> 27:11.880 use cases. 27:11.880 --> 27:18.920 Safari, I tried, I couldn't find a single one. 27:18.920 --> 27:23.560 The main use case I wanted to use this for was what we had before, right? 27:23.560 --> 27:27.720 You have your defer JavaScript that I know won't be needed. 27:27.720 --> 27:30.960 I don't want to load my defer JavaScript that early on. 27:30.960 --> 27:37.360 I want an out of tight mode into the second phase, there's no way to do that. 27:37.360 --> 27:41.800 I can put fetch priority low on it, and it lowers it from high to medium, but it doesn't 27:41.800 --> 27:48.600 shift it out of tight mode, other characteristics to determine what it should look like. 27:48.600 --> 27:54.040 Chrome and Safari, the use tight mode, Firefox does use tight mode at all, which means 27:54.040 --> 27:59.280 that fetch priority is a super powerful mechanism in Firefox, because you have very fine 27:59.280 --> 28:05.400 grain control over how to order resources at the server, which is why it's slightly ironic 28:05.400 --> 28:10.920 guys that Firefox was the last browser to actually shift this, but I'm very happy to say 28:10.920 --> 28:14.360 that they shift this a couple of months ago. 28:14.400 --> 28:17.560 That's now available in all the browsers, very nice. 28:17.560 --> 28:20.800 And Firefox's implementation is actually quite good. 28:20.800 --> 28:24.600 It's quite flexible, it's quite advanced, you have a lot of control over all the things 28:24.600 --> 28:26.080 that you want to do. 28:26.080 --> 28:29.360 And they even add a documentation page for it. 28:29.360 --> 28:32.120 In 2025, can you imagine that? 28:32.120 --> 28:33.120 Amazing. 28:33.120 --> 28:38.360 But seriously, thank you. 28:38.360 --> 28:44.320 The problem is, even with this, even though we can now very fine grain control Firefox, 28:44.880 --> 28:50.480 that's not enough, because if we optimize everything for Firefox, we might still make things worse 28:50.480 --> 28:58.480 in the other two browsers, because you guessed it priorities are not consistent along the browsers. 28:58.480 --> 29:04.400 I always like to use the font example, because it's so weird, for fonts, normal fonts 29:04.400 --> 29:11.920 are going to be highest priority in Chrome and low priority in Firefox, almost complete opposite. 29:11.960 --> 29:18.160 And if you don't preload the fonts, so preload is basically the font is probably going to be in another CSS file, 29:18.160 --> 29:21.160 but I know you're going to need it, so maybe you could start requesting it earlier. 29:21.160 --> 29:24.400 That's how preload does. 29:24.400 --> 29:26.880 browsers take it as a very different signal. 29:26.880 --> 29:29.760 Firefox says, oh, you're telling me about a new resource. 29:29.760 --> 29:33.360 I'm going to bump it in priority, it goes from low to medium. 29:33.360 --> 29:38.360 And Chrome says, oh, you're telling me about this resource, that must mean you don't like it at all. 29:38.440 --> 29:40.440 I'm going to move from highest to high. 29:42.840 --> 29:45.320 Let's make it worse, let's add fetch priority. 29:47.320 --> 29:53.400 fetch priority high, Chrome does not care about your fetch priority high, okay? 29:53.400 --> 29:56.200 It wasn't high, it was going to stay at high. 29:56.200 --> 30:02.600 Safari and Firefox are going to bump it one, so for medium time, fetch priority low. 30:02.840 --> 30:08.520 Chrome and Firefox make it minus two, because minus one is so douchewa, you know? 30:08.520 --> 30:11.560 Why not go for minus two to really give a kick? 30:11.560 --> 30:14.440 What's the Safari just goes for minus one, obviously, right? 30:14.440 --> 30:21.000 So they're very inconsistent, this is a problem because bumping these things around will impact 30:21.000 --> 30:23.560 other resources that are their own priorities. 30:23.560 --> 30:27.000 And they also have other inconsistent ways of distributing this. 30:27.000 --> 30:31.320 So you end up not knowing what the order of priorities is going to be in all the other browsers, 30:31.400 --> 30:33.400 if you optimize for, say, Firefox. 30:34.840 --> 30:41.000 And the best example of that that I found for today is that there is no way in Firefox 30:42.280 --> 30:47.480 to get that LCP image to load before your default JavaScript. 30:49.400 --> 30:54.440 So let's say we have, on top, we have a default JavaScript and then an image without fetch priority high. 30:55.640 --> 31:00.440 By default, you would load the JavaScript first and then the image. 31:00.520 --> 31:02.760 That's a default, occasionally, behavior in all the browsers. 31:04.200 --> 31:07.960 In Chrome and Safari, as you can tell, if you add fetch priority high, 31:09.800 --> 31:12.760 the image is now going to get a higher priority than the JavaScript, 31:13.480 --> 31:16.200 and it's going to be loaded before the JavaScript. 31:16.200 --> 31:20.520 When or without type mode, this is even, uh, have to do with type mode anymore. 31:20.520 --> 31:25.480 When or without type mode, your image is going to come in before your JavaScript, as you probably 31:25.560 --> 31:27.720 want, because this is your LCP image. 31:28.680 --> 31:35.240 In Firefox, you can't do that, because for some reason, Firefox images begin at ultra low priority. 31:36.040 --> 31:39.160 That's one step below lowest. I had to invent that just for Firefox. 31:40.200 --> 31:43.480 Okay, everyone else is low. Firefox is at ultra low. 31:44.200 --> 31:50.600 So yes, doing fetch priority high bumps, it two steps from ultra low to low, 31:51.160 --> 31:53.960 but that's still the same as the D for JavaScript. 31:54.600 --> 32:00.520 So there's no way to get your, um, to get your LCP image on top of your D for JavaScript. 32:00.520 --> 32:03.400 Without also marking the D for JavaScript as fetch priority low. 32:04.920 --> 32:11.720 Okay. Now, pre-empting the Firefox Fan Force 5 Club. 32:12.760 --> 32:16.040 Okay, I'm not saying this makes Firefox a worse browser. 32:17.000 --> 32:23.000 Okay. In fact, I could have easily shown examples where, um, 32:23.880 --> 32:28.120 the other browsers don't allow you to do things. In fact, I did show some examples of that, right? 32:29.480 --> 32:32.920 It's not the Firefox or any of the other as worse or faster. 32:32.920 --> 32:39.080 And again, mainly talking about how frustrating it is that they all do things in so many different ways. 32:40.600 --> 32:43.560 Okay. This means that for me as a developer, 32:44.360 --> 32:49.800 it is almost impossible to create a web page that performs, 32:50.600 --> 32:54.600 that has good web performance and consistent performance on all three of the browsers. 32:55.320 --> 32:57.480 Almost impossible in today's ecosystem. 32:59.080 --> 33:02.840 And I could forgive this if this was just tight mode and if it was just a priority. 33:03.880 --> 33:10.120 Maybe. But of course, I looked at tons of other stuff as well. I didn't have time today. 33:10.520 --> 33:15.960 Believe me, none of these things are consistent along the browsers. 33:15.960 --> 33:22.120 And they can have very big impacts on how resources are loaded and when things get drawn on the screen. 33:23.640 --> 33:29.320 Right? It is not just one or two things. It is the whole ecosystem. It's very difficult to do. 33:29.320 --> 33:33.800 And that brings me to the original inspiration for today's talk, which is this meme. 33:40.440 --> 33:44.040 If you're a new web developer starting now, even if you follow the standards, 33:44.040 --> 33:47.800 even if you use one of the big known platforms and CDNs, 33:48.600 --> 33:54.920 you cannot be sure that your thing is going to be loading well in all the browsers and all the environments. 33:56.680 --> 33:59.320 It's not really the fault of the developers either. 33:59.320 --> 34:03.880 You know, we have been trained to look at just what I like to call the Chrome web titles. 34:04.920 --> 34:06.920 Not the core of the titles, the Chrome web titles. 34:07.000 --> 34:11.720 Even though, as we said, Firefox is doing an excellent job in catching up there. 34:11.720 --> 34:18.120 Safari, of course, is not. People look at this. People mostly test in Chrome. 34:19.160 --> 34:25.880 And they think whatever works well in Chrome is also going to do well in Firefox. 34:25.880 --> 34:29.480 And Safari, and as I just try to explain, that's absolutely not the case. 34:30.600 --> 34:35.560 And because these metrics are missing for the other browsers and some tools are missing for the other browsers. 34:35.640 --> 34:37.800 People typically don't test, don't verify. 34:38.840 --> 34:43.160 So a lot of sites, I think, are much slower on Safari and Firefox than they could be or should be. 34:46.360 --> 34:51.000 What I think we need, I'm not sure that the browsers need to be more consistent with each other. 34:52.040 --> 34:56.920 It's very difficult to know which browser is doing it right. It's very difficult to know which is the foster approach. 34:58.120 --> 35:00.520 I would settle for having this all well documented. 35:01.480 --> 35:07.240 Having this properly on, you know, something like Web.deph, which is way too Google focused for me, 35:07.240 --> 35:13.000 even though it's a great resource, even on something like MDN, which is way too focused on the standards for me. 35:13.000 --> 35:17.800 It doesn't actually explain things that are not regulated by standards like everything it's talked about today. 35:19.080 --> 35:21.080 We need more documentation. 35:22.280 --> 35:26.760 We need more people to be aware of this so that they can actually test for these outliers. 35:27.320 --> 35:29.800 So I'm hoping to contribute with my talk today. 35:29.800 --> 35:34.520 I'm going to finish now because I'm all out of time with the best analogy, the best analogy 35:34.520 --> 35:39.000 I've ever found for how an HTTP3 connection works. 35:43.320 --> 35:45.320 Thank you very much.