HTTP2 Server Push & Preload – Reduce Network Requests

Pros (+)

  • Totally FREE to use.
  • Increases page speed.
  • Better caching than inlining CSS.

Cons (-)

  • Can be tricky to set up.
  • Doesn’t work in every situation.
  • Unnecessary downloads.

What’s in it for me? How HTTP2 server push can help you.

  • Beginners – server push can be tricky to set up and needs server access, but preload is much easier; you can preload assets with a few lines of code.
  • Intermediates – you’re no doubt already aware of the likes of preloading, but server push and preload aren’t the same. We’ll explain why it matters to you.
  • Power users – if you’ve implemented preloading and server push before, you will be surprised how easy it is to add it to Cloudflare for the ultimate in website speed.

1. What is HTTP2 Server Push?

HTTP2 server push helps reduce network requests by preemptively sending resources before the browser has asked for them. Bit of a mouthful, eh? Don’t worry, all it means is that files are sent ahead to help speed up the webpage for the client.

Normally a user clicks on a link for https://example.com and the server sends the files in stages.

  1. HTML is sent down the wire first of all.
  2. CSS stylesheets are sent next.
  3. JavaScript is usually sent last.

You can easily see that this takes three network requests.

To overcome this in HTTP1, web designers started to inline stylesheets and some minor JavaScript. This speeds up the webpage, but the resources aren’t freely cacheable for subsequent page requests. So whereas in the traditional format, the stylesheet only has to be sent once. With inlining it needs to be sent every single time.

Server push attempts to overcome inlining’s problems by sending all three files at once. Like so:

  1. HTML + CSS + JS.

Instead of three network requests we now only have one. Plus the next time the user visits https://example.com only the HTML needs to be sent.

It’s like having your cake and eating it. Well, not quite.

You know we don’t live in a perfect world, unfortunately. Server push can cause unnecessary network requests, because  on repeat visits sometimes all three files are sent even though only one is needed.

There are lots of different caches in the network, which is good as it gives the browser chance to check them and disregard an asset if it’s already in the correct cache. It’s more complicated than that of course, but in summary that’s what happens.

Some servers keep a temporary record of server pushes so as not to push the same resource twice. However, while this is good in theory, if the first push fails, then the user won’t get it a second time. Not something you want to happen.

Jake Archibald has a server push article where he explains caching in more detail.

2. Difference Between Server Push and Preload?

Just like a Golden Retriever and a Labrador aren’t the same, there are subtle, but important, differences between server push and preload.

More often than not, though, the end results look the same. It’s the implementation that differs.

With server push, you can push the resource as soon as the server receives the request. Whereas with true preloading, the browser has to receieve the HTML and parse it before it can preload the asset.

To make it more complicated – and no doubt where the confussion stems from – preloaded assets can be pushed. So you can push and preload an asset from your own server, which is the default behaviour. To only preload the asset you would have to set the nopush directive.

It’s also worth noting that you can only push resources from your origin server, but you can preload assets from your origin and third party servers.

MDN have some excellent preload documentation, as do W3.org on their preload page. 

Here’s how server push and preload look on WebPageTest.

Server Push and Preload Differences
Server Push and Preload Differences
  • The yellow highlighted files have been pushed by Cloudflare
  • Blue files have been preloaded.
  • You can see that it only took less than 0.3 seconds to load 6 files.

In order to achieve such rapid speeds, it’s best to subset the font files using Transfonter and self-host them. Regardless, it’s still quite incredible that this is all possible using Hostinger’s business hosting and a free Cloudflare account. Amazing really.

Of course, you could be a trendy and pay four times as much for Siteground. 🙂

3. Preload Resources Using Browser Hints

First of all, let’s get preload out of the way, as it’s the simpler of the two concepts to implement. Preload is a form of resource hinting and resource prioritization.

You will probably find that server push is deactivated on shared hosting, simply to prevent beginners blitzing the server with endless unnecessary requests.

This isn’t a problem, because they can’t stop browser hinting from taking place. For browser hints, like preload and prefetch, server access isn’t required. It’s for this reason why preloading third party resources is possible.

Using hints doesn’t reduce network requests and you won’t see a SERVER PUSHED – notification in WebPageTest, but it will definitely increase your page speed.

The IP address will also be missing from pushed resources, but preloaded resources will show an IP address, even if they’re pushed. Look at the two blank spaces on the right hand column below.

Server Push and Preload WebPageTest Network Requests
Server Push and Preload WebPageTest Network Requests

Browser hinting is especially good for preloading critical resources like:

  • Site logo.
  • Hero image.
  • Header video.
  • Self-hosted fonts.

You simply have to include the rel=”preload” attribute and the correct as type. Note that fonts also need the crossorigin attribute included, but the shorthand version is okay.

Another cool feature is using media queries inside the link element itself.

<link rel="preload" href="image.png" as="logo">
<link rel="preload" href="font.woff2" as="font" crossorigin>
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">

<link rel="preload" href="small-image.png" as="image" media="(max-width: 600px)">
<link rel="preload" href="big-image.png" as="image" media="(min-width: 601px)">

You can also use WordPress hooks to conditionally load assets for certain pages. That’s how I only load Poppins font files for my homepage.

There’s a thorough preload article by Addy Osmani Google – Preload, Prefetch and Priorities in Chrome with some useful examples.

4. OpenLiteSpeed Server Push

Like most WordPress geeks, I’ve been itching to try out a virtual private server, but have been put off due to the extra cheese involved. It’s not that I’m greedy, but my site is perfectly fine as it is. Further down the road, if I get enough views then upgrading won’t be an issue, but for now it’s pointless. I’d be spending extra money for nothing.

There is a solution, though. I wouldn’t mention it otherwise…

Google Cloud’s free tier always free products.

Although my free $300 credit had expired from when I set it up last year, which is probably a good thing. You see they want you to spend the free credits as soon as possible, then you end up on a paid plan. That’s not good. It defeats the point in signing up in the first place.

Sticking to the free plan is what it’s all about.

The plan was to install CentOS, but long story short, I was impatient and gave up. Instead I opted for a one-click install of OpenLiteSpeed, which uses LiteSpeed Cache. Having a caching plugin and a server built on the same architecture is really powerful.

It’s like Apache releasing a WordPress caching plugin. Imagine that!

Not to mention, the code that you use is similar to Apache so anyone with Apache experience will find it straightforward. I’m talking about items you might edit in .htaccess, etc. 

Google Cloud is intimidating at first, as it’s not the most intuitive interface. It likely started of as something for professionals rather than the public, either that or it’s just always been difficult. However, it’s got some superb features and getting a free VPS from a company with the networking experience of Google isn’t to be sniffed at.

More to the point, the speeds on the free tier are scorching fast, considering that I’m not using a CDN.

OpenLiteSpeed Server Push
OpenLiteSpeed Server Push

You will notice that the pushed files start downloading immediately after the HTML has finished. It does come up as SERVER PUSHED in WebPageTest so it’s definitely working.

Now I’m not sure if Cloudflare’s version is loading the pushed files sooner because they’re utilising early hints or whether it’s just a smidge faster?

OpenLiteSpeed Server Pushed
OpenLiteSpeed Server Pushed

One thing to notice is that in the OpenLiteSpeed example it shows an IP address for the request, unlike the Cloudflare one that doesn’t.

Another thing is that the OpenLiteSpeed setup only pushes once. This makes sense in that it reduces unnecessary network requests on subsequent visits.

You have to clear your cache for it to push the resource again.

The best thing to do with anything like this is test the living daylights out of it. Once you’re familiar with its quirks and features, as Doug Demuro would say, you’ll be a more powerful website owner.

OpenLiteSpeed Request Number 2 Server Pushed
OpenLiteSpeed Request Number 2 Server Pushed

Finally you can see in the request details panel that it clearly says SERVER PUSHED.

That’s about all I’ve got for OpenLiteSpeed – it seemed like a good example to highlight that not all server pushes will look the same. One of the most powerful things about running several sites is that you can compare them against one another.

Back-to-back testing can give you a deeper insight than just relying on one sample.

To activate server push on LiteSpeed Cache just open advanced settings, optimization tab, then turn on CSS push, JS push or both. It’s important that you turn off inlining critical CSS to prevent it being loaded twice.

CSS HTTP2 Push LiteSpeed Cache
CSS HTTP2 Push LiteSpeed Cache

Turning on HTTP2 push for JavaScript is exactly the same.

JS HTTP2 Push LiteSpeed Cache
JS HTTP2 Push LiteSpeed Cache

Pro Tip: server push will only work on a CDN if your nameservers are pointing to it, as in a full-site setup or like Cloudflare is set up. This way your CDN acts like your origin server.

When the browser connects to a CDN that’s used for static assets only, the files will start downloading immediately anyway, which makes server push reduntant. However, you can still use preload for important resources.

5. Cloudflare Server Push

Before we go over how to activate server push on Cloudflare, let’s have a look at some before and after examples to see how they compare. 

One thing that I have deliberately left out of the equation is Prefetch. You can think of prefetch as preload’s big fat cousin that’s always eating lots of pizza (or data). Prefetch can easily become wasteful, even with the best of intentions.

No matter how good your analytics are, it’s impossible to guess everyone’s mind. For this reason, I don’t implement prefetch. Although it might be useful for you so by all means don’t rule it out.

5.1. Original Setup – Inlined CSS

Cloudflare Inlined CSS
Cloudflare Inlined CSS

This is probably the fastest way to load a webpage for the first-time user, but subsequent visits will be better of using server push as the CSS will already be cached.

5.2. New Setup – Server Push

Cloudflare Server Push
Cloudflare Server Push

Now we’re using server push to load three files at once, it gives us the initial speed of inlining, but without the drawbacks. The first load is fast, but the repeat visitor will see improvements when visiting another page. 

Due to WordPress using a template system, the CSS files are used across multiple pages. So although inlined CSS is still cached by the browser, it’s only available for that one page. Pushed CSS stylesheets, or JavaScript files, can be downloaded once and used countless times.

For a small site it isn’t such an issue, but when traffic increases, the problem is compounded. It could literally result in thousands – if not millions – of unnecessary requests and wasted resources.

To make the tests reasonably accurate, I opted for 9 tests, which is the maximum you can do on WebPageTest. You can go higher with the likes of SiteSpeed.io – something on my radar for future tests.

5.3. Server Push & Preload

On this example I made a test page and preloaded the fonts, which are hosted in my root folder.

Cloudflare Server Push Preloaded Fonts
Cloudflare Server Push Preloaded Fonts

You can see that the preloaded font files – in red – load after the pushed resources, but still load much faster than if they weren’t preloaded.

Unfortunately, Cloudflare only offer server push on CSS and JS files only. For fonts, preloading is the best we can do.

The preload links in this instance were added using a WordPress hook, as it was the easiest way to load them conditionally for one page. Though, as you’ll soon see, it isn’t the fastest option in our toolbox.

5.4. Cloudflare Server Push Setup

Presuming you’re already using Cloudflare, setting up server push is straightforward. You need to do the following:

  1. Add a line of code to wpconfig.php.
  2. Use the official Cloudflare plugin.

Adding the following line of code to wpconfig.php, which should be in your root folder /public_html.

  • define( ‘CLOUDFLARE_HTTP2_SERVER_PUSH_ACTIVE’, true);

Place the code just above the line that says something like “happy publishing.”

Activating Cloudflare Server Push
Activating Cloudflare Server Push

You will find the official Cloudflare plugin in the WordPress plugin directory.

Cloudflare WordPress Plugin
Cloudflare WordPress Plugin

You don’t really have to do much with the plugin, apart from adding the API key and website name, as it doesn’t have a lot of settings. That’s either good or bad depending on your outlook. The point being, you can do all your adjusting on the Cloudflare website.

I’ve turned my usual caching plugin off, apart from Autoptimize for minification and aggregation.

Similar to our OpenLiteSpeed example, we can check server push is working in WebPageTest. Notice the missing IP addresses for the pushed files, due to three resources sharing one request.

Cloudflare Server Pushed WebPageTest
Cloudflare Server Pushed WebPageTest

Lastly we can look in the request panel of WebPageTest to scrutinize the details.

Cloudflare Request Number 2 Server Pushed
Cloudflare Request Number 2 Server Pushed

Depending on how big your files are and how often they’re called will determine the gains you can make with server push and preload. It might not suit eveyone, but it’s another tool in our optimization toolbox that we can use if the application looks a good fit.

Like all page speed tweaks, you’ll have to test it thoroughly before rolling it out to your users.

6. Push and Preload Drawbacks

A properly configured WordPress website is always going to be fast, especially on CDN. It’s not outright speed that we gain from server push, but better optimization that is the key ingredient. Yes, server push is fast, but so is inlining. In fact inlining is usually slightly faster.

Server push aids our caching strategy, whereas inlining resources hinders it.

Pushed resources aren’t browser cache aware, which means they’re sent ahead blindly, even if a copy is already in the client’s cache. This is a waste of bandwidth and ultimately costly, as it will use your viewer’s data. This is especially painful if they’re on a limited allowance; the smallest mobile data plans usually start at 250 or 500 MB. Pushing large files repeatedly can soon eat into this.

From the server side, the only way you can keep track of pushed files is with the Push Diary. According to the Apache docs this is as follows:

The module will keep a diary of what has been PUSHed for each connection (hashes of URLs, basically) and will not PUSH the same resource twice. When the connection closes, this information is discarded. Apache Server Push Documentation

From my own simple testing, I noticed that Cloudflare does utilize this feature, or something similar, as the resources aren’t pushed on repeat visits.

Preload and Push Repeat Visit WebPageTest Waterfall
Preload and Push Repeat Visit WebPageTest Waterfall

However, in order to achieve this you need the ensure the Browser Cache TTL is set to anything other than Respect Existing Headers. You can of course tweak your own .htaccess settings to get the same result, but it’s much easier to let Cloudflare do the hard work for us.

In an earlier version of this blog post, I stated that preloading was wasteful, but I was wrong. Preload is actually browser cache aware and can intelligently use resources. It has no drawbacks in this regard. My service worker is set to cache everything, but it isn’t caching my self-hosted fonts. Point being, I’m now glad to report that preload wasn’t to blame.

Cloudflare Browser Cache TTL
Cloudflare Browser Cache TTL

As developers and site owners it’s our duty to push and preload files repsonsibly. In reality, however, it’s unlikely you’ll find a perfect strategy for pleasing everyone. Though I’m sure you’ll agree it’s not about being flawless, but doing the best job we can overall.

Serving cached assets on repeat visits is the best possible outcome. Reduced network requests – check, increased speed – check, and no unnecessary data usage – check.

What this means for WordPress developers is that we have to use server push wisely. It’s not a magic wand that we can apply to everything. It’s strictly for critical assets that make a worthwhile difference. Bearing in mind, if you’ve got a huge website, consideration is a must.

For every pushed resource, you’re potentially adding thousands of redundant hits – increasing strain on your origin server and wasting user bandwidth.

The same can also be said for inlining, which is why Frank Goosens recommends to be cautious with inlining when using Autoptimize.

7. Server Push & Self-Hosted Fonts

One big disappointment, for me at least, is that I can’t get server push to work for fonts. As soon as I add the crossorigin attribute the push degrades to a preload. Without adding crossorigin, the font files are pushed, but not used. Seems that I can’t win.

It’s worth mentioning that on my forensic level searching, I noticed that Filament Group have some pushed fonts that aren’t used on their website. It seems to me that they possibly run into the same issue regarding crossorigin, either that or they forgot to delete the font files?

Server Push Fonts - Filament Group
Server Push Fonts – Filament Group

Even when I reached out to Zach Leatherman, who is a well-known font guru and ex-Filament Group employee, on Twitter. He said he hadn’t yet played with server push for fonts. So although I’m guessing, I’m sure that it isn’t possible to push fonts, otherwise he’d have known about it.

If anyone has information contradicting this then please get in touch and I’ll update this article accordingly.

8. Link Headers – Best Application

One important point that I’m just updating this post with is the best location to place your preload links. While the code is very similar, the speed can vary quite dramatically.

Like walking to the shop, the nearer you are, the faster you can get your favorite bag of sweets.

Computers have a sweet tooth, too; only theirs is the opposite to ours – they don’t like more sweets, they like less. Less code to munch on that is.

The request comes in for https://parallaxsite.com/font-test/ and the HTML for that file is sent immediately. What isn’t immediate is the fact the webpage doesn’t know we’re preloading the fonts until it parses the HTML.

It’s this slight delay that causes preloads to lag behind our pushes. Not to panic, .htaccess to the rescue.

We’re going to move our link header as close to the initial request as possible. If you’ve got control of your own VPS or private server, that would be in httpd.conf, as far as I’m aware. For those of us on a shared server .htaccess is the next best option.

  1. httpd.conf – fastest option.
  2. .htaccess – second quickest.
  3. HTML – website pages and posts – where most links are – slowest option.

Of course HTML gives you a more granular approach, so it isn’t necessarily the worst option.

Pro tip: another benefit of link headers is that you only need add the link once for the full site.

On a big site this could literally save you thousands of links. Imagine running a massive warehouse, this type of trick is a huge data – and time – saver.

After hours of testing and looking at the Apache documentaion, I decided to post a question on Server Fault. Five minutes later and I had an answer – preload link in .htaccess. Yeayy!

This is the code that I then applied to make my conditional loading work:

SetEnvIf Request_URI "^/font-test/$" PRELOAD_FONT

And below is the screenshot from my .htaccess file. The code in the brackets is a regex or regular expression.

SetEnvIf Font Preload Header Links .htaccess
SetEnvIf Font Preload Header Links .htaccess

Place preload links near the top of your .htaccess files so they get read as quickly as possible.

Whereas previously I struggled to conditionally load the fonts using .htaccess, they’re now running smoothly thanks to Mr White.

The speed is almost as rapid as server push, so I’m chuffed to bits.

Server Push Preload Link Header SetEnvIf .htaccess
Server Push Preload Link Header SetEnvIf .htaccess

Change the /font-test/ to any URL path and for multiple pages you can see the Apache SetEnvIf page, as I’m not qualified to answer that unfortunately. If you’re stuck you can always ask a question on Server Fault like I did, or for more general stuff try Stack Overflow.

It’s not difficult once you’ve got the code snippets, but that said please tread carefully with .htaccess because it can lock you out of your website. You have been warned! It’s also a hidden file on some hosting providers.

9. Advanced Configuration – Early Hints

Apache is the most popular web server and their HTTP2 Server Push documentation expains everything, including more advanced options like early hints and H2 Push Resource.

You configure early hints by firstly turning them on and then you can take advantage of them in .htaccess or httpd.conf file. However, you might struggle to do so on a shared server.

H2EarlyHints on
<Location /xxx.html>
H2PushResource /xxx.css
H2PushResource /xxx.js
</Location>

Early hints aren’t enabled by default; this prevents issues with older browsers. Unfortunately early hints aren’t backwards compatible so thouroughly test your set up before rolling them out.

10. Debugging HTTP2

There are several options for debugging HTTP2 preload and server push headers. Chrome DevTools is possibly the easiest option.

Note that it only shows push for actual server pushes. Preloads are harder to detect from the initiator column, from my experience, but you can check the progress bars and also inspect the headers themselves. 

Generally the easiest method is just looking at the speed increase/decrease in WebPageTest’s waterfall charts. It’s all you really need for basic configuration checks.

Chrome DevTools Initiator Push
Chrome DevTools Initiator Push

Curl is great for checking URLs and seeing what headers are returned. However, it isn’t installed on Windows 10 by default so you’ll have to follow a tutorial on how to install it. Stack Overflow is a good place to start – installing Curl on Windows 10.

11. Summary: 12 Things to Remember

Now that we’ve outlined the basics of HTTP2 server push and preloading, it’s time to summarize what we’ve learned.

  1. Server push is only possible from the origin server.
  2. Preloading is more flexible, as it can be used on third-party assets.
  3. Pushing resources is usually a better option than inlining, as it aids caching for repeat visits. Inlined assets are cached, but they’re only reusable individually rather than globally.
  4. Preload is browser cache aware – great for reusing assets and saving resources (money/data).
  5. When preloading fonts the crossorigin attribute must be used, even on the same origin.
  6. Server push is available on Cloudflare CDN using the plugin and updated wpconfig.php file, although you can still get it to work without the plugin, just use the Apache docs for guidance or standard preload links in headers or HTML.
  7. Early hints are an advanced option if you have server access.
  8. OpenLiteSpeed on Google Cloud is a brilliant way to try out VPS for free.
  9. LiteSpeed Cache is the easiest way to turn on server push for OpenLiteSpeed users.
  10. Testing your pushed/preloaded resources is vitally important.
  11. WebPageTest is the best option for quickly checking page speed after server push upgrades.
  12. Chrome DevTools is the easiest method for detailed push/preload debugging.

That’s about all I’ve got for server push, guys. Hopefully you’ve learned something new to help speed up your own website.

Do please let me know if there’s anything you feel I got wrong; if you’ve have a suggestion or tip then shout it out in the comments. I’ll be sure to include it in the next update.

Until next time, keep pushing, tweakers!

Share This Post

LinkedIn

Leave a Comment