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.

