Fronteers — vakvereniging voor front-end developers

Pre-browsing by Steve Souders

Transcript

(paul) He's been doing research into lately, so please, if you would, welcome Steve Souders to the stage.

[APPLAUSE] Thank you very much, Paul.

I'm so excited to have made it up the stairs without falling.

So it's great to be here in Amsterdam, and to be at Fronteers.

Let me get that guy going.

We got this guy-- hey, and we're on time.

That's awesome.

So I work today talk about prebrowsing.

And I actually don't put a hyphen in it, so we should get that straight right out.

Paul did an introduction.

Generally, I'll just say, I take slow things and make them fast.

I really enjoy doing that.

My wife doesn't enjoy it too much when I try to optimize everything around the house though.

But for work and web development, it's been a really good thing to focus on.

And what I wanted to talk about today is speeding up the way that websites are loaded, and improving the user experience.

Making our users happy by creating faster experiences.

Now, often we're challenged with network conditions when it comes to browsing the web and using web apps.

Paul just mentioned some caveats about using the Wi-Fi.

And we all face these conditions.

If you're on a phone, you might have to, God forbid, actually connect to one of these things, and do all of your traffic over that.

And it can really slow things down.

And when you're using the web, you can face this dreaded blank white screen, where things are just loading.

This is unfortunately the prototypical website to use for slow performance, CNN.com.

And I'll just mention anecdotally that I wanted to get this screenshot, and I was nervous about how fast I would have to capture the screen while it was still blank.

And I actually didn't have to hurry at all.

It was very easy to capture this blank white screen.

And when users see this, I talked a little bit last night, for people who were at the jam session, about feedback, browser busy indicators.

There are some indicators in this screen to tell you that the browser's working, but really not that much, right? And so it's going to leave our users feeling puzzled.

What's going on? So what we would really like is we would like it if we could have things done faster and before we really needed them, kind of like Corporal O'Reilly for MASH.

I might be dating myself with this show, but his nickname was Radar.

And he seemed to have this knack to anticipate what was needed, and to have it done beforehand.

And so he was a great assistant to the general of the camp.

And so that's what I want to talk about today.

And I call this concept prebrowsing, where we want to get what the browser needs before the browser needs it.

And again, I'll just mention that this word prebrowsing-- I just made it up, but, in fact, I do have the domain name for it.

So we'll just throw a little TM up there.

You might be asking, why can't the cache take care of this for me? And I totally agree with you.

As someone who thinks that the cache is needing a lot of improvement, I will say there are some good reasons why the cache is not going to satisfy the need that I'm talking about here.

First of all, the cash only works if you're repeating a visit, right? And so if you're going to a site for the very first time, there won't be anything in the cache for that.

So that's a very common experience.

Certainly from the Google search prospective, users are coming in doing new searches every day.

Even if you had visited the site before, those resources that are needed, the scripts, and stylesheets, and images, might not be in the cache.

You might have cleared the cache, some other antivirus software might have cleared the cache, you might have been watching a lot of YouTube videos, and so your cache items were purged.

The items might be in the cache, but maybe the website developer didn't specify caching headers.

Or maybe they did, but that time has passed.

And so the item in your cache might be expired, it might not be fresh, and the browser is going to have to check with the server and see if there's an update.

Or the resource might not be fresh and there actually is an update.

So there are lots of reasons why, even if the cache is working well, you might not have the items that are needed to make that website load quickly in your cache.

So that really got me down this path for the last couple years.

I've been thinking about this concept of prebrowsing, and it's very kind of zen like.

So let's just try to create a visual picture in our heads of what this prebrowsing thing is.

Let's kind of like put some scope around it.

So there are a lot of techniques for prebrowsing.

I'll be talking about those today.

Some of them have a high risk of false positives, but some of the techniques don't.

They're very safe.

Sometimes this risk is high.

The cost could be very expensive for users.

Sometimes the cost isn't that high, and it's a good thing to try doing.

Browsers do a lot of the prebrowsing techniques that I'll be talking about, but developers have to adopt some of them too.

And if you think I'm talking about you, yes, I am.

That's why I'm here presenting this.

So I also wanted to point out the tremendous amount of time invested in the background photos of these slides.

Does anyone get this one, just the facts? It's a fax machine.

Groan? Aww.

There'll be some other ones too.

Pay attention to these.

So just the facts, so here's what I'm going to cover today.

I'm just checking my time.

So I'm here to talk about link rel DNS prefetch, link rel prefetch, link rel prerender.

And we're going to talk about things the browser does, DNS pre-resolution, TCP pre-connect, prefreshing-- something that probably no one has heard before-- and we're going to talk about the preloader.

Now, in thinking about this presentation, I thought, how should I go through these seven things? Seven is kind of maximum for people to keep a mental list going in their head.

How can I try to present these in a way that will really stick with you, and you can follow the flow through this presentation? And I thought I could talk about it from this dimension, about who really has responsibility for each of these items, the developer or the browser.

And that's a good way to think about it, but I'm going to take a different approach.

I'm going to look at it chronologically.

So for these seven things, let's think about it in terms of browsing the web.

The preloader is going to take place on the page you're currently loading, that you're currently looking at, right? Now, before you got to that page, you could have been on a previous page that had some of these link tags, and could have gotten some things done, like Corporal Radar O'Reilly, before the browser actually needed them.

And when you're going from that previous page to the current page, there's a transition that happens.

And during that transition, there are things that the browser can do.

Because during that transition time, we developers don't have any foothold, right? It's the browser that's in control.

So in this context of chronological flow, previous link rel, DNS prefetch, prefetch prerender, transition, DNS pre-resolution, TCP pre-connect, prefresh, and the current page preloader.

Let's go through these.

So let's set the context a little bit for this previous page.

We don't really know-- you're on the previous page-- we don't really know the user's next intention, right? So that means there's a high risk of false positives.

There's a high risk that we're going to do some activity without knowing the exact thing that the user is going to do next, which links they're going to click on, or what they might type in the URL bar.

So this could be wasteful, especially for users who are on mobile, and they're paying for every byte that's downloaded.

But there are some high confidence scenarios that exist.

And that's what you as developers, we as developers, want to focus on.

Some examples, if you're on a search page and you search for Adventure Time, there's a high likelihood you're going to click on the link for Cartoon Network.

No response for the audience.

Any Adventure Time fans? Wow, not as many as I thought.

My kids will be disappointed.

They were excited that I used that as the example.

If you're on a login page, again, very high likelihood the user's going to log in and go to their home page next.

And if you're looking at a paginated document of some type, again, a high likelihood the user's going to go to the next page.

So there are high confidence scenarios that exist, in which you could use these link tags that I'm going to talk about.

So the first is DNS prefetch.

This is what the syntax looks like.

You just say, rel DNS prefetch, and you can put in a domain starting with slash slash.

You can also put a URL if you want.

That's fine.

It's more characters, so just trying to be optimizing performance.

And this is a very low cost item.

This will get the DNS lookup done.

If the DNS resolution isn't already cached on the machine, it'll get the DNS lookup done.

And that is maybe a couple hundred bytes total over the network.

So it's a very low cost item.

It's not going to block or interfere with anything else that's going on, unless you're doing dozens of DNS lookups simultaneously.

And browsers may actually choose, depending on other information they have, to not only do the DNS resolution, but to actually establish a TCP connection.

And here's a good example from Air BnB.

If you look in their HTML right now, you'll see these references to the different CDNs that they use in their page.

So how much does this save us? Here's some stats from a Google article that came out a few years ago, and it shows that the median DNS lookup time is 87 milliseconds.

So that's a decent amount of time.

That data is a little old.

If you wanted to, you could look up Chrome histograms DNS inside of Chrome, and you could get stats for your own browsing session.

And here for me, across about 500 DNS lookups, the median time was 63 milliseconds.

So this is going to save some time for new domains that are being used by the page, so it's a worthwhile thing to do.

Now unfortunately, we don't have a lot of widespread support for DNS prefetch.

It's in Chrome, Firefox, Firefox Mobile, IE 11 is supposed to have it.

I haven't verified that yet.

The documentation says preliminary and subject to change.

But it is a worthwhile hint to put into our pages to try to get this pre-browsing effect to happen.

The other link tag, the second one that I talked about was link rel prefetch.

Here's the syntax.

In this case, you actually put the full URL for the resource that you want to get down into the browser, in anticipation of the user needing that for their next activity.

Now usually, I feel a little burdened, a little weighed down when I tried to read the spec, but this is the entire spec for link rel prefetch.

It's so short I'm actually going to read it.

I can't read this.

It's too small, so I'll read up here.

The prefetch keyword may be used with link, a, and area elements.

This keyword creates an external resource link.

The prefetch keyword indicates that preemptively fetching and caching the specified resources likely to be beneficial, as it is highly likely that the user will require this resource.

There is no default type for resources given by the prefetch keyword.

Very brief.

It's hard not to go wrong with this, but does this leave anyone wishing for more specificity? Like for me, I like them to say something like, browsers should actually download the resource.

Doesn't even mention that, right? So this left me with a lot of questions.

As I started looking into this and thinking about recommended it to developers, I wondered, well, do browsers actually download resources if you say link rel prefetch? How many does it download? Are they prefetched immediately or later after onload? What's the download priority? Does it compete with actual scripts on the page? Things I'm doing for the next page shouldn't compete with the current page.

What happens if I'm prefetching stuff, and then I transition to the next page? What happens to those prefetches? And is a supported over HTTPS? So I did my usual thing.

I created a browser scope user test.

If you don't know what that means, look it up.

Very helpful.

I created this test and then I tweeted about it.

I also put the test out on prebrowsing.com,

so I'm getting my $10 worth out of that domain that I booked.

And I tweeted about it and I got a few results across about 50 browsers.

So those results are what I'm going to present now to describe how prefetch works across different browsers.

So again, we're not seeing a lot of adoption of prefetch.

It's in the old Android browser, Chrome.

Actually with Chrome, it turned out that we adopted link rel prefetch in Chrome pretty long ago, a couple years ago, I think.

And then it actually regressed, and it wasn't working.

We just discovered that.

So it's patched now in 31, but you have to attach this flag, and it'll be enabled by default pretty soon.

And it's in Firefox and Opera 15 Plus.

So there are some browsers that support it.

So for those browsers, they actually do download the resource.

How many prefetches are done? So this is kind of interesting.

We see in Firefox, it will never do more than one prefetch at a time.

So if you're trying to prefetch a lot of items, you're not going to get a big lift from Firefox.

I actually pinged Patrick McManus there, and they're going to revisit that and probably increase it to the six or 10.

We see Chrome does 10, Chrome 31, if you enable the flag.

Android does six in parallel, if you sharded across multiple domains, but it will only do one at a time across a single domain.

So if you have multiple items that you want to prefetch, you might want to think about sharding those.

What else? Oh wait, when are they prefetched, right? When does it actually happen? So it turns out three of the browsers don't start prefetching until after the onload event.

And I kind of like that, like I don't want these prefetch anticipatory requests competing with the actual page as it's loading.

But waiting until onload is kind of late.

Like if you think about the search experience, users might very quickly see the search results and click on a link.

They might even click on the link before onload happens.

So right now, we have a lot of-- I'll talk later about the preloader-- there's a lot of intelligence in browsers about prioritizing resource downloads, and I think who is it, Chrome and Opera, are on a better track here, where they don't wait to an absolute time.

They just want to queue up these prefetch requests until all the more important requests are done.

Unfortunately, they're actually not doing that right now.

So competing with other request doesn't make sense if you're waiting until after onload.

Before the two browsers that do prefetch during the current page, they actually give them the same priority as images.

So these prefetchs could be competing with actual content on the current page, and we're fixing that in Chrome.

Now, this one I thought was the most interesting.

What happens on page transition? Now, again, let's think about this.

What I've done is I'm on a previous page, and I've said, I think I know where the user is going next, and so I want you to prefetch these scripts and stylesheets.

Because when they transition to the next page, they're going to need them.

And when the user actually transitions to the next page, the browser cancels all those requests.

Huh? Does that like not make sense to anyone else? So this is another thing that the browser teams are going to have to get on board and fix, and we're fixing this in Chrome.

We really want these requests to finish, to at least complete while the user is doing that transition.

Now in Firefox, at least today-- I didn't read this in Chrome, and I didn't test it-- there is a little bit of a fix you can do to get around that.

I'll talk about in a minute.

So one thing if you're going to use prefetch is to make sure that the resources you prefe-- you want to think about which resources you're going to prefetch.

They should be cacheable, because all this is going to do is put it in the cache, right? And the user is going to transition to the next page.

And when that page requests the item, if it's not fresh, the browser is going to have to do an if modified since, do another HTTP request.

It'll be nice to get a 304 not modified back, but it'd be better to prefetch items that were cacheable, for at least the amount of time it takes for the user to get to the next page.

You want to focus on critical resources, so I would say probably you might want to do five or 10 prefetchs.

I wouldn't put images in there.

I would focus on scripts and stylesheets.

And prefetching the HTML would make a lot of sense, but typically we don't have HTML that's cacheable, so you might not do that.

And this is a fix for that canceling of prefetches that I mentioned a minute ago.

If your server supports the except ranges header, you can do that, and what at least Firefox will do is it will save the partial response at the point it got canceled.

And when the next page requests that resource, it will pick it up for where left off.

But what we really want to do is we want to get the browsers to fix that cancel behavior.

The last of these link rel techniques I wanted to talk about was prerender.

It's very powerful.

I think Chrome kind of took the lead on getting this one out there.

And this is the syntax, link rel prerender.

You giveth the URL to the page that you want it to prerender.

And think of it as loading that URL in a hidden tab, or a hidden tabby.

That's the groan I was looking for.

Thank you.

I had a really hard time with prerender.

Looking for images, I couldn't think of anything.

And to be honest, the only thing I could think of was rendering fat, rendering lard, and the Flickr images were not pretty, so I went with the hidden tabby.

In this context, although you should use caching headers as much as possible, the caching headers aren't such an issue.

Because the page is being loaded, it's not going to be reloaded if and when the user transitions to that page.

The hidden browsers, a hidden tab, is just going to be swapped into place, so you don't have to worry about the caching header so much.

When that page is loaded in the hidden tab, it's just like loading it in another tab, except the user can't see that other tab.

So the JavaScript is going to be executed.

And this could be a little bit of a challenge for JavaScript that has to do with ads, or impression counting, or other things like that.

So there's a page visibility API I'm not going to go into here, but you can use that to wrap your JavaScript, and only execute that JavaScript, if and when that tab becomes visible.

I talked about how some of these techniques are high risk, low risk.

This is a pretty high risk technique.

There's a lot of cost in doing this.

Pages today, the average across the top 300,000 is one and half meg.

So especially on mobile, it's lower.

But especially for people who are on mobile, you want to be careful about prerender.

And even for people who are on lower end hardware, it might be a costly experience to have that activity going on in the background.

Not just the downloads, but also the JavaScript and CSS activity going on.

Now, one way that you could reduce that risk is use something like a touchstart or onmousedown.

So I talked about, in this previous context, we don't really know what the user's intention is.

And so there's the high risk of false positives.

But if you wait until the user is actually mousing down on a link, you can reduce this risk.

You have much more certainty about what they're going to, and so you could just ride an onmousedown handler that creates a link rel prefetch, or a link rel DNS prefetch.

I wouldn't do a link rel prerender, because you're about to navigate to that page.

But you could for example, while you're navigating to that HTML page, and waiting for the HTML to come down, you could command the browser to download some scripts and stylesheets that that page is going to need.

And this you can do with a lot more confidence.

So it's a way to address that.

So let's wrap up,.

We've got these three phases, again, that we're going to talk about, previous, transition, current.

Where in the previous one, I just finished talking about the three techniques.

And let's just wrap up the support.

Now, I want to point out these numbers, these version numbers, are based on the test results I got.

Again, I talked to Pat McManus, Patrick McManus, at Firefox, and he said they've had DNS prefetch and prefetch since Firefox 12.

It's just that there's no one with Firefox 12 who ran my test.

So from the tests I saw, these are the version numbers that are out there.

And we see prerender is only supported right now in Chrome, again, IE 11 says they're going to adopt it.

Let's go to the second phase, the transition phase.

Here is mostly the browser doing the work.

I've been spending a lot of time focusing on this phase, because I think it's a huge window of opportunity.

Why do I think that? This is from the navigation timing spec.

It kind of looks at the flow of page loading, and the times that you could get out of the window.performance timings

object.

And it's not necessarily drawn to scale.

I think this stuff, after the initial response, on down is much longer.

So it's not drawn to scale, but still the time that is this transition phase is quite a bit of time.

So the transition phase is from when the navigation starts, like when you click a link, to when the first byte of the HTML document response comes back.

That whole time, browsers are snoozing.

What are they doing, right? Developers aren't doing anything, because once you've left the page, and before the next page comes down, you have no foothold.

You can't be doing anything.

The browser is the only one working at this point.

And what's it doing? It's requesting an HTML document they'd just seen.

They're twiddling its thumbs, right? There's a lot we could do it this in this phase of the page loading sequence.

Well, it actually turns out that browsers aren't snoozing.

A lot of browsers have realized that this is a window of opportunity, and they're doing things in there.

So one of them is DNS pre-resolution.

So this is where the browser resolves the DNS that it might need before it actually needs it.

How does this happen? It happens with start pages.

So when you start your browser, you'll see, in the new tab, the 10 pages that you use the most.

When you start the browser, those 10 DNS resolutions are resolved, and you can see that in Chrome.

(if you go to chrome)//DNS, you can see the 10 domains that Chrome is going to resolve when it starts up.

So that will make it faster when you go to those domains.

Another thing that it can do is as you're typing a URL or search query, it can resolve the DNS for your chosen search engine, or for the website.

If I type CNN.com, it

can resolve that DNS name before I even hit Return.

And you can see when it will do those things in Chrome looking at Chrome predictors.

So for example, I go to the HTTP archive a lot.

When I type h, Chrome will actually do a DNS resolution for httparchive.org,

to make sure it's fresh and already resolved, before I've even typed the next character.

Other examples when this might happen, when you load a page, the browser will scan and look at all the anchors, and maybe even the image sources and script sources, and make sure that the domains in those URLs, in those links, are resolved.

And if you hover over a mouse, or a link, or certainly when you click down, it will make sure that that host name is resolved.

That might happen if, for example, you created links dynamically with JavaScript.

The browser wouldn't have seen it when it did a HTML scan, but it could see it when you actually do the hover.

Now, those are all resolving the DNS for the page that you're going to.

But that page is typically going to have about 15 domains that it uses for resources in the page.

So chrome actually goes farther, and tries to pre-resolve the resource domains that you're going to need.

And you can see that database, that mapping, here in Chrome DNS.

So for example, for web.adblade.com,

there are all of these domains for sub-resources that Chrome has recorded or needed.

And they have different confidence values and time set, it's been looked up before.

And so based on that information, Chrome will actually resolve the DNS lookup for those host names when you're transitioning to that page, again, to have that time done, that 50 to 100 milliseconds already done when the page is actually loading and needs to access those resources.

So another thing that happens similar to this is TCP pre-connects.

This is creating a TCP connection to the actual web server, and that can take hundreds of milliseconds, so it's a good thing to get out of the way early.

And it's kind of the next aggressive step above a DNS pre-resolution.

So the browser will do this for high confidence navigations.

What's high confidence? Well, it's based on your activity, so if we go back to this Chrome predictors, the coloring here is actually an indication of whether-- if it's yellow, Chrome is just going to do a DNS pre-resolution.

If it's green, it's actually going to open a TCP connection, right? So this is a more aggressive thing you can do.

And if we look here in Chrome DNS at the sub-resource pre-connects, you can actually see the subdomains where it has done these TCP pre-connects.

So you can see for your own activity how much this is happening.

Now, the last one I want to talk about is something kind of exciting called prefresh.

You've probably never heard of this before.

This is an idea that Tony Gentilcore and I came up with about a year and a half ago.

And it's actually in Chrome now.

You can turn on with a certain flag.

I didn't think of this name.

Michael Kleber did, so Will, you should go ahead and put a TM on top of that.

And here, what happens, the concept is just like with the DNS lookups for subdomains, browsers should remember, for pages that you visit, the actual resources that were used by that page.

Those do change over time, but there is a lot of time where the same resources, the same version of jQuery, the same main.css is downloaded

for that page over, and over, and over every time you visit.

If only the browser could remember that, and as you're transitioning to CNN.com, the browser,

without any hints of link rel prefetch, the browser could know that it's going to probably need this version of jQuery, and this style sheet, and could download it proactively.

So that's the concept here is when you go to that web page, again, the browser can proactively preload these high confidence resources.

And this is going to save a lot of time.

What you would do is you would do this for the most important resources, probably scripts and style sheets, very high in the page, the ones that are most likely to block rendering of the page.

And so when the HTML document comes down, the browser won't have to do a get request for that resource and wait for all of the jQuery to come down.

It will already have it.

Or maybe it already had it on a cache, but it was expired, so it was going to have to do an if modified since and get a 304 response.

That's still is going to involve some latency impacts, so it would be good to get those out the way.

And even reading that version of jQuery, if you do have it cached, and it is fresh, you still have to read it off disk.

This prefresh could get that disk I/O time taken care of before the HTML document, while the HTML document is being retrieved.

And that way, these resources are going to be resolved, fetched, downloaded, and in memory by the time the HTML arrives is parsed and ask for it.

So in Chrome, the way you turn this on is with the speculative resource prefetching flag.

And if you go into Chrome predictors, and you click on the other tab, resource prefetch predictor, you can see this database of information that Chrome is building, and it records information that has a confidence score.

And it sees like how many times have you been to that page? Out of that number of times, how many times was this resource there? How many times was it not there? And so, for example, if I to jdrop.org,

there's a very high confidence that I'm going to need style.ccs.

So we have three phases that we were talking about, previous, transition, current.

This transition phase, developers don't have much of a foothold, and luckily browsers are doing a lot of activity here to take advantage of getting things in cache down into the browser before it's actually needed.

So now, I wanted to talk about this last phase, the current phase.

And this is where we have the preloader working, right? So this is something that doesn't really involve developers.

You don't have to do the work for it.

It's done by the browser, but it is important for developers to be aware of how it works, and how it's changing over time.

So what really is the preloader? I think this is the biggest performance optimization made in browsers in the history of browsers ever.

Bigger than new JavaScript engines, bigger than any other prefetching tags that we have.

I think the preloader has done more for performance than anything else in browsers.

The motivation for the preloader came from observations I made eight years ago about how scripts were loaded back in the days of IE 6 and IE 7.

When you started downloading a script, the HTML parser would stop.

It would hit that script source, and it would stop while it downloaded the script, parsed and executed it.

So if you had, for example, script source one, script source two, script source three, it would download one.

And then after it was downloaded and parsed, it would download two.

After it was downloaded and parsed, it would download three.

And after it was downloaded and parsed, it would continue parsing the rest of the page.

So everything was blocked downloading the script, and it really didn't make sense, especially the downloading part.

I understand that these three scripts have to be executed in order, but you could download them all in parallel, and if the third one comes back first, just cue the response and wait and parse it later, while you wait for one and two to come back.

And so that's what motivated the preloader.

That's exactly what happens now is the main HTML parser will stop at that first script tag, but the look ahead, or speculative parser, will continue on looking for tags like script, link, IMG, iframe.

And when it sees those, it will queue up more downloads, and so we could get more parallelization in download and speed up page loading.

A study at Google found that just this one change made pages 17% faster.

Now, this preload activity involves a lot of logic, and a lot of this logic is new.

There's a lot of corner cases and edge cases involved.

Overall, the logic is let's get the really important stuff, scripts and stylesheets, preloaded as quickly as possible, because those are critical to the rendering of the page, and it's going to block rendering, so we want to get those down.

And so we're going to make images a lower priority, right? Even though they're important visually, it doesn't matter if I have an image downloaded if all rendering is blocked on the page waiting for a style sheet.

So that's the general idea, but there are a lot of corner cases and surprises.

You might notice I intentionally misspell this.

I've added this to my spell checker, because I think a z is more fun.

And surprises should be fun, so I hope you'll join me in my campaign to change the spelling of surprise.

So one surprise will come, and probably not too much of a surprise to this group, when it comes to responsive images loaded via JavaScript.

So here, there actually is no IMG tag for that image in the page.

Or if there it is, it doesn't have a source attribute, it has a data source attribute.

So the preloader, as it's speculative parsing down into the page, is not going to recognize that image and start prefetching it.

So if you're using responsive images, using the JavaScript technique, the IMG images in the page are going to be seen by the preloader, and they're going to get queued up for download first.

So if these IMG images are actually a lower priority image than your JavaScript images, this could be bad for you, right? Because you're going to get these lower priority IMG images recognized by the preloader, queued up for download, and then eventually JavaScript is going to start executing.

It's going to find all these data sources, figure out the right size and what to request, and it's going to queue up those requests, but they're going to be later in the queue.

And this is especially problematic if all of the images are on the same domain.

So one thing you can do is you could do either everything with IMG or everything with your responsive images technique.

I actually saw this on a top 20 website in the world, where they had lower priority images done with IMG, and the highest priority product images were done with JavaScript, and they were showing up really, really late.

These low priority images would visualize, would render very quickly, and it was because they were being queued up later, and they were all on the same domain.

So at least if you split the responsive images on a separate domain, they won't be competing for a single pool of TCP connections.

So that's something to be aware of with the preloader.

Another pattern is, back in my book from 2007, I advocated putting scripts at the bottom.

And now this preloader, as it scans the page and it sees these script tags, even though they're at the bottom because the general logic is load scripts earlier, it's going to load those much higher in the download order.

And so when it does that, again, it's competing for this limited pool of TCP connections.

It's going to steal connections from other resources that are higher up in the page, but maybe aren't scripts, like images.

So in this scenario, n you might have some images that are critical to the page.

You thought, if I put my scripts at the bottom, it will give my image a chance to download first, but the preloader is going to see that script at the bottom and promote it, right? So a great example of this-- and I'm sorry.

I realized you can't read this.

This is Airbnb, and I've highlighted there the image, which is this giant like 1,200 by 700-- what is it? 1600 by 700 image in the background, right? Obviously, that's a critical, critical image for the user experience of this page, and they put it kind of in the middle.

And at the bottom, just like my book from 2007 said, they put all of these scripts sources at the bottom.

And the assumption might be that these will be downloaded after the critical image.

So I'm going to give my critical image, which is important to the rendering user experience, a higher priority.

But in fact, if we look at this dump, from Chrome-- this is using WebPagetest.

From Chrome, we see that-- it's kind of hard.

I'll go back and I'll tie it like here's these scripts at the bottom, b2.js, da.js.

And now if we go here, we'll probably see some of those.

I don't see one of them there, but believe they are there.

They got promoted above-- this is the critical image.

So those scripts got promoted above the critical image.

Now, I was all prepared to come here and kind of wine and wince about Chrome and the preloader, and try to get those guys.

There's a bug to get this fixed.

And then, I actually loaded it this week and found that the bug was gone.

This is the dump I did back in March of this year.

This is the one I did this week, and they've already fixed it.

This is, I think, James Simonson did this fix, and a bunch of other good ones with the preloader.

So what they did was they changed the logic a little bit, and they said, we realize we're promoting the script from the bottom.

We're going to let some images creep into that initial set of high priority downloads, and this relaxation of that logic was enough to get the rendering.

If we look at the previous page, here, that big honking image didn't render til about four seconds.

Here, it's rendering at 1.2 seconds.

So the highlight of this, the main takeaway of this, is that this preload logic is something that's new.

All the browsers are doing it.

And it is maybe going to have some edge cases, some corner cases.

Overall, it has a huge benefit of speeding up websites.

But we are going to find anti-patterns, examples of atypical behavior, and we just need to raise those up, and browsers can look at them.

And there's probably a way to alter the logic to make the preloader work well in these scenarios.

So if you're like me, and you want to take slow things to make them fast, I recommend that you start thinking about these pre-browsing browsing techniques.

Even though there isn't widespread support, I think there's enough support across major browsers to think about using DNS prefetch, prefetch, and prerender.

And I think you can also lobby the browser vendors that you know to get those techniques supported.

I think if you are a browser developer, that it is good to continue to consider something like prefresh, to look at the code-- it's all open source in Chrome-- and to work on these DNS pre-resolution and pre-connect techniques.

And for both browser developers and website developers to continue looking at the preloader, making sure you understand how that is impacting your site today, and seeing if there are techniques that you should adopt to make the preloader work well with your site, and for browser developers to make sure their preloaders work well with as many sites as possible.

I just want to do one last shout out before I leave the stages.

I started working on this deck awhile ago, and during the time my office mate Ilya Grigorik's book came out, and I started looking through there.

I saw that he had written down a lot of the things that I had been trying to figure out, so it was a good corroboration of the things I'd been looking for.

And if you want to read more about these techniques, and get the details of course, these are just high level slides.

I recommend you take a look at the book.

You could buy it.

That would be great.

I'm sure he would love the royalties, but it's also available free online.

And that's it.

Thank you very much.

[APPLAUSE] (steve souders) Do we have time for Q&A? (paul) Yeah, we do.

(steve souders) Oh, cool.

(paul) Join me right here.

All right.

There's a lot of people talking during your presentation, and one of the themes that came up a bit was around mobile data plans.

So a lot of these techniques allow us to like, speculatively, get new data.

If people are on data plans where they pay by the byte, like are these an anti-pattern in those cases? Or how do we handle that? Yeah that's going to be a hard problem.

I was talking to someone last night about the suggested network API changes, so that mobile web pages could know what kind of connection the user is on.

But that's still a problem.

You might be on Wi-Fi, and you're actually having to pay for it, or you might be on a roaming plan that you don't have to pay for.

So first of all, for the DNS prefetch stuff, the real killer is latency.

And DNS involves latency right? Even though overall, it's not a long amount of time, 100 milliseconds, it is going to be worse on mobile.

And it's a very low cost item, like I said, a couple hundred bytes.

And so at least for mobile, a DNS prefetch, and for browsers, this DNS pre-resolution stuff makes total sense.

If you notice, prerenders in Chrome-- it's not in Chrome for mobile, at least not yet.

And so that's something that we have to take into consideration, and it might be that prerender and maybe even link rel prefetch fetch aren't going to make sense on mobile until we have some way to verify that users are OK with doing that kind of proactive download inactivity.

Yeah, go ahead and pull that off.

Thanks.

One article I pointed out yesterday, if you Google for multinets, all one word, Angela, Angela Nicoara Multinest? Nets.

Multinets? Yeah.

It's a great paper.

And it talks about, basically what they did was they took a version of Android and rewrote some of the network interface management code, so that there was a new UI in Android, where you could pick one of three targets that you wanted to optimize, my battery life, my data plan usage, or the speed of loading.

And based on that selection, it would alter the way that your network interfaces were being used, especially when you had multiple network interfaces available to choose from.

And I think aside from all the technical stuff in it, that simple concept of letting users have a simple choice of what their target optimization is, I think, is something mobile developers, mobile OS developers should think about.

I think that would be really important, and would help in this context.

Yeah, there's a lot of cases where maybe I'm tethering through like the signals for, oh, I'm on Wi-Fi so it doesn't matter.

Like, I might actually be connected from Wi-Fi to my phone, but my phone might be on an international data plan.

There's a lot of things that's hard to make assumptions in this area.

I guess we should also point out the network information API has kind of been in proposal for a while, and it it's not implemented anywhere.

It does have this concept, actually I think it was an earlier draft of this concept of a metered property, where you could identify if the data plan is basically in a situation where they are paying by the byte.

As far as I know, there's no implementation there.

But it's a little tricky, right, because this might be a thing where you don't actually want developers to be able to make a choice about this.

You would rather just kind of have the browser do the best thing, so that you, as a developer, aren't choosing kind of what sort of pre-behavior you want.

One question in the browser support table.

I think a few people noticed they were not seeing mobile Safari there.

So can you speak to mobile Safari support for some of these things? Yeah, there isn't support for it in mobile Safari, or Safari.

I don't think Safari showed up on any of the tables either.

And Safari, as of today, still doesn't support the nav timing API.

I mean the codes in webkit, but it's not turned on.

That flag isn't turned on.

And so I don't know, but, yeah certainly, there are some things that have to do with performance that are lagging there.

One question.

So actually before working on the Chrome team, like four years ago, I filed a ticket against Chrome, and I was like, why can't Chrome just cache jQuery? Why can't it just have everything that's in the Google CDN just like permanently in the disk cache? Like is that a good idea? Yeah, I think that's a good idea.

And I think we're all pretty aware of the articles that show the amount of fragmentation around things like jQuery.

The most popular version of jQuery is the one from a year and a half or two years ago.

And so it might be kind of hard to have all of those versions in the browser permanently.

And then, it would kind of get hard, like where do you draw the line? Like the fifth most popular JavaScript framework might be really hurt that it didn't make the cut, and there might be some allegations about political motivations, or something like that.

And so that's this prefresh concept is meant to kind of try to target that.

Like, for some reason, that version of JavaScript might not be in the cache, but I have information that you're going to need it.

And so I can make sure to pre-warm the cache before the page even asks for that resource.

Nice.

One last question.

This just came up.

Yorin asked this.

He said, I'm confused.

Should we put scripts at the bottom or not? Oh, I didn't even talk about that.

So the real thing, like scripts at the bottom was so 2007.

--pull that off.

Thanks.

One article I pointed out yesterday, if you Google for multinets, all one word, Angela, Angela Nicoara Multinest? Nets.

Multinets? Yeah.

It's a great paper, and it talks about basically what they did was they took a version of Android and rewrote some of the network interface management code, so that there was a new UI in Android where you could pick one of three targets that you wanted to optimize, my battery life, my data plan usage, or the speed of loading.

And based on that selection, it would alter the way that your network interfaces were being used, especially when you had multiple network interfaces available to choose from.

And I think aside from all the technical stuff in it, that simple concept of letting users have a simple choice of what their target optimization is, I think is something mobile developers, mobile OS developers should think about.

I think that would be really important and would help in this context.

Yeah, there's a lot of cases where maybe I'm tethering through like, the signals for oh, I'm on Wi-Fi, so it doesn't matter.

Like, I might actually be connected from Wi-Fi to my phone, but my phone might be on an international plan.

There's a lot of things that's hard to make assumptions in this area.

I guess we should also went out the network information API has kind of been in proposal for a while, and it's not implemented anywhere.

It does have this concept, actually I think was an earlier draft of this concept of a metered property, where you could identify if the data plan is basically in a situation where they are paying by the byte.

As far as I know, there's no implementation there, But it's a little tricky, right, because this might be a thing where you don't actually want developers to be able to make a choice about this.

You would rather just kind of have the browser do the best thing, so that you, as a developer, aren't choosing kind of what sort of pre-behavior you want.

One question in the browser support table.

I think a few people noticed they were not seeing mobile Safari there.

So can you speak to mobile Safari support for some of these things? Yeah, there isn't support for it in mobile Safari, or Safari.

I don't think Safari showed up on any of the tables either.

And Safari, as of today, still doesn't support the nav timing API.

I mean the codes in webkit, but it's not turned on.

That flag isn't turned on.

And so I don't know, but, yeah certainly, there are some things that have to do with performance that are lagging there.

One question.

So actually before working on the Chrome team, like four years ago, I filed a ticket against Chrome, and I was like, why can't Chrome just cache jQuery? Why can't it just have everything that's in the Google CDN just like permanently in the disk cache? Like is that a good idea? Yeah, I think that's a good idea.

And I think we're all pretty aware of the articles that show the amount of fragmentation around things like jQuery.

The most popular version of jQuery is the one from a year and a half or two years ago.

And so it might be kind of hard to have all of those versions in the browser permanently.

And then it would kind of get hard, like where do you draw the line.

Like the fifth most popular JavaScript framework might be really hurt that it didn't make the cut, and there might be some allegations about political motivations, or something like that.

And so that's this prefresh concept is meant to kind of try to target that.

Like, for some reason, that version of JavaScript might not be in the cache, but I have information that you're going to need it.

And so I can make sure to pre-warm the cache before the page even ask for that resource.

Nice.

One last question.

This just came up.

Yorin asked this.

He said, I am confused.

Should we put scripts at the bottom or not? Oh, I didn't even talk about that.

So the real thing, like scripts at the bottom was so 2007.

I still feel good about it.

They're terrible in the head, right? Yeah.

Well, no, they're great in the head if you make them async or defer.

So the real thing we should do is adopt async or defer patterns for scripts.

So if you put all the scripts at the bottom, it means that they're-- So probably the more important thing than position is the ability to place async on them.

Yeah.

Or defer.

The thing about async is then you have race conditions about execution order.

Defer will preserve execution order.

There's this race condition bug in defer that's in IE 6, 7, 8, and 9, I think.

Oh, really? Basically, yeah.

So I ran into this.

You can just like Google defer attribute bug.

But basically, let's say a common case, jQuery, jQuery UI have those two as script tags, and you have to front both of them.

There's this bug in IE where, if the first script, like jQuery, touches the Dom, it'll start to execute the second script right after it touches the Dom, before the rest of the first has finished.

So in this case, it'll start to run jQuery UI, and it'll be like, window.jQuery or is not defined.

So probably the best solution there is defer, as long as you're not serving it to IE 8 and 9.

I would bet maybe you have a test page, or I can do one real quick when I go sit down.

I bet if you put an inline script block that does nothing, or just says var foo equals 1.

Between those two scripts sources, it will separate the execution, right because-- I like it.

Yeah.

OK.

I'm sure like Mathias Bynens is already doing this as we're talking.

OK, yeah.

We'll figure that out.

Even though it's not in the spec, IE respects the defer attribute, even for inline scripts.

It does.

IE does.

I know what else doe-- OK.

Good to know.

It's not supposed to, but it does.

All right.

Thank you guys very much.

Thank you for Q&A.

[HIGH FIVE] Woo.

Post a comment