Streamline Delivery

Rearrange, Reorganize & Reconfigure

Along with reducing page weight, the other most fundamental strategy to minimize load time is to optimize the way data is retrieved and transferred from the web server and then loaded by the web browser.

HTML Structure

The file resources of a website work together to form the content, visual styling and functionality users see and interact with in the browser. HTML code is the foundation of each page and coordinates how those resources are loaded. Optimizing the structure of HTML is an important step to streamline the loading process and ensure that pages load quickly and efficiently.

Render Blocking

When a user navigates to a page, the web browser loads and examines the HTML code. Any CSS or JavaScript files encountered in the HTML are downloaded and applied to the page.

This sequence is known as the critical rendering path and is particularly important for above the fold content. CSS and JavaScript references are considered render blocking because the page may appear blank to the user until those files are downloaded and interpreted by the web browser.

For a very simple page with only a few small files transferred over a fast internet connection, the loading process is nearly instantaneous. However as the HTML becomes more complex and CSS and JavaScript files become larger, more numerous or loaded over slower internet speeds, the display of the page can become noticeably delayed.

Consider the basic structure of an HTML file:

HTML
<!doctype html>
<html lang="...">
<head>
    <meta charset="utf-8">
    <title>Page Title</title>

    <link rel="stylesheet" href="styles.css">
    <script src="scripts.js"></script>
</head>

<body>
    <!-- visible content goes here -->
</body>
</html>

In general, the <body> section contains the visible content of the page, like text and images, and the <head> section is for the code and file references that aren't directly displayed to the user. Given the render blocking effect of conventional CSS and JavaScript references, any files placed in the <head> this way have to be downloaded, applied and executed before the user can see any content.

A Progressive Approach

A more efficient strategy is to separate and prioritize the most critical resources to load as soon as possible. Resources that are not essential to the initially-visible part of the page can then be deferred to the end of the loading process. The exact CSS and JavaScript to identify as critical will depend on the content, layout and functionality of each page, but will likely focus on above the fold content.

CSS

For CSS, this means applying critical styling immediately, while loading non-critical CSS in the background without delaying the initial display of the page. Often called asynchronous CSS loading, there are a variety of techniques to achieve this effect.

One option is to place non-critical CSS references at the end of the page, before the closing </body> tag:

HTML
<head>
    <!-- other <head> content -->

    <link rel="stylesheet" href="critical.css">
</head>

<body>
    <!-- page content -->

    <link rel="stylesheet" href="non-critical.css">
</body>

Depending on the quantity and complexity of the page content and other resources, one downside to this method is that files here may not begin downloading as soon as files referenced earlier in the HTML.

To avoid any delay, another simple method keeps file references in the <head> but uses a bit of JavaScript and the media attribute to download non-critical files in the background. The media value is then updated with the JavaScript onload event, applying that CSS to the page. A normal file reference is wrapped in a <noscript> tag as a fallback if JavaScript is disabled.

HTML
<head>
<!-- other <head> content -->

<link rel="stylesheet" href="critical.css">

<link rel="stylesheet" href="non-critical.css" media="(max-width:1px)" onload="this.onload=null;this.media='all'">
<noscript><link rel="stylesheet" href="non-critical.css"></noscript>

</head>

Although only supported by some newer web browsers, a similar technique uses preload in the rel attribute:

HTML
<head>
    <!-- other <head> content -->

    <link rel="stylesheet" href="critical.css">

    <link rel="preload" href="non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
    <noscript><link rel="stylesheet" href="non-critical.css"></noscript>

</head>

(The loadCSS JavaScript snippet adds a fallback for browsers that don't support preload.)

Media Conditions

To further reduce the quantity of render-blocking CSS, media queries can selectively load critical resources based on conditions like screen size. All files will be downloaded, but with appropriate priority, and only CSS with media conditions that apply to the current browsing device will block rendering.

HTML
<head>
<!-- other <head> content -->

<link rel="stylesheet" href="critical-general.css">
<link rel="stylesheet" href="critical-large.css" media="(min-width:1000px)">

</head>

Inlining Critical CSS

Depending on the structure of the page and the size of CSS resources, deferring non-critical CSS can go a long way to streamline the loading process, but what about the remaining render blocking critical CSS?

To eliminate all render blocking CSS, critical styles can be applied to the page with an inline style block. This technique avoids the render blocking effect of a separate file reference by embedding the critical CSS directly in the HTML.

HTML
<head>
<!-- other <head> content -->

<style>
    .critical-style-1 {...}
    .critical-style-2 {...}
    /*-- etc --*/
</style>

</head>

A potential downside to this method is that inlined CSS won't be cached by the web browser and is therefore re-loaded each time the page is viewed. HTTP/2 may also make this method less advantageous or even obsolete.

JavaScript

Much of the same strategies apply to optimizing JavaScript loading, however JavaScript typically acts on the HTML once the page is loaded, so in many cases all JavaScript can be safely deferred.

As with CSS files, one of the simplest ways to defer non-critical JavaScript is to place <script> references at the bottom of the page:

HTML
<!-- other HTML above -->

    <script src="non-critical.js"></script>
    <script src="jquery.js"></script>
    <script src="jquery-dependent.js"></script>

</body>

Also similar to CSS, the downside of this method is that files may not start downloading as soon as those referenced earlier in the HTML.

Unlike CSS however, <script> references with a src attribute can use the async and defer attributes to allow JavaScript files to download in the background without interrupting the rendering process. Both async and defer start downloading immediately, but while files with defer will run after initial page rendering in the order they appear in the HTML, each file with async will run as soon as it's loaded. For this reason, async is often only used for resources that are completely independent.

async

defer

A typical deferred JavaScript setup will look like this:

HTML
<head>
<!-- other <head> content -->

<script src="critical.js"></script> <!-- if necessary -->
<script defer src="non-critical.js"></script>
<script defer src="jquery.js"></script>
<script defer src="jquery-dependent.js"></script>

</head>

Inline JavaScript

Ideally, most if not all inline JavaScript should be moved to a separate file to maximize caching, but if inline <script> blocks can't be avoided and they also rely on defer'd files, the applicable code can be wrapped with an appropriate event listener:

HTML
<head>

<script defer src="jquery.js"></script>
<script defer src="jquery-dependent.js"></script>

</head>
<body>
    <!-- page content -->

    <script>
        document.addEventListener('DOMContentLoaded', function(){
            // more jQuery-dependent stuff
        });
    </script>

</body>

All Together

Putting it all together, this is a simple example of HTML structured to separate and prioritize critical versus non-critical CSS and JavaScript resources, minimizing delay for above the fold content:

HTML
<!doctype html>
<html lang="...">
<head>
<meta charset="utf-8">
<title>Page Title</title>

    <link rel="stylesheet" href="critical.css"> <!-- can be optionally inlined -->
    <link rel="stylesheet" href="non-critical.css" media="(max-width:1px)" onload="this.onload=null;this.media='all'">
    <noscript><link rel="stylesheet" href="non-critical.css"></noscript>

    <script src="critical.js"></script> <!-- if necessary; can be optionally inlined -->
    <script defer src="non-critical.js"></script>
    <script defer src="jquery.js"></script>
    <script defer src="jquery-dependent.js"></script>

</head>

<body>
<!-- visible content goes here -->
</body>
</html>

Resource Hints

Resource hints preemptively trigger the sequence of network connections and file downloads involved in loading the page. These are most useful for important resources that are not directly referenced in the HTML, giving the browser a head start by prompting selected files to begin loading sooner than if the browser discovered those same files through the normal course of evaluating and loading the page.

There are several types of resources hints, indicated with the rel attribute on the <link> element, each with a unique potential role in improving load time. Support varies, but most modern browsers can take advantage of the performance benefit. Web browsers may also limit the number of domain/network connections made with resources hints, so they should be used sparingly and purposefully.

dns-prefetch

Similar to looking up an address on a map, when a user visits a website the browser begins the process of establishing a connection with the web server by finding the domain name on the internet. Although this usually takes only milliseconds, if a website loads files from a separate domain name - common for third-party resources - the browser makes a connection for each domain.

dns-prefetch tells the browser to start that process right away, rather than as the need is discovered later in the loading process, saving that time.

HTML
<link rel="dns-prefetch" href="https://example.com">

preconnect

Similar to dns-prefetch, preconnect goes further in the process of connecting to third-party domains and includes any needed security protocol, saving even more time.

In most cases, preconnect is preferable to dns-prefetch but is only supported by some newer web browsers. Fortunately they can be used together, getting the benefit of preconnect in browsers that support it with a fallback to the more deeply supported dns-prefetch.

HTML
<link rel="dns-prefetch preconnect" href="https://example.com">

preload

While dns-prefetch and preconnect make the initial network connection, preload takes the process yet further and also downloads a specific file. This is ideal for resources that are both important to the initial display of the page and not directly referenced in the HTML.

Images that are needed for above the fold content and indirectly called for through a CSS file (rather than directly in the HTML like an <img> tag) are perfect candidates for preload. Rather than waiting for the browser to analyze the HTML, download the CSS, analyze the CSS and then load an image referenced in the CSS, preload tells the browser to load the image right away.

While dns-prefetch and preconnect only need the rel and href attributes, preload is a bit more complicated and adds the as attribute, which indicates the file type. Common as values include "image" for images, "style" for CSS, "script" for JavaScript and "font" for font files.

This example preloads a CSS background image file needed for above-the-fold content but not referenced directly in the HTML:

HTML
<link rel="preload" href="header-logo.svg" as="image">

To make preload a little more complicated still, for files that may not be supported by all browsers like some video file formats, the optional type attribute will prevent browsers that don't support a particular file type from downloading it at all.

prefetch

While dns-prefetch, preconnect and preload speed up the loading of resources that are needed as soon as possible, prefetch is a lower priority version of preload that downloads files that will very likely be needed in the near future. prefetch is typically used for files that will be needed on a page the user is likely to visit next.

This example triggers a low priority download of the CSS styling for a page frequently visited after the current page:

HTML
<link rel="prefetch" href="blog.css" as="style">

prerender

prerender works like prefetch, but loads an entire page and all of its dependent files in the background.

HTML
<link rel="prerender" href="blog.html">
Advanced Tip

Resource hints can accept the optional media attribute to specify conditions like media type or media queries to load files selectively for different screen and device configurations.

A summary of how to use each type of resource hint:

And a few points to remember:

HTML
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

A simple and effective configuration of resource hints:

HTML
<head>
    <!-- other <head> content -->

    <link rel="dns-prefetch preconnect" href="https://fonts.gstatic.com" crossorigin> <!-- for font file(s) referenced in CSS -->
    <link rel="preload" href="header-logo.svg" as="image"> <!-- images referenced in CSS -->
    <link rel="preload" href="background-texture.jpg" as="image">

    <link rel="stylesheet" href="critical.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400&display=swap">
</head>

Web Hosting

Web hosting is the collection of services that store and distribute websites across the internet, including the hardware and software of web servers. Matching server configuration and resources to the needs of a website ensures that files are always delivered quickly and efficiently. This becomes more important as website traffic grows or content becomes more complex and resource intensive.

Response Time

Response time is the time is takes for the web server to respond to a request from a user's browser for the files of a website and is an important basic measurement of a web server's overall speed. Faster is better, but ideally response time should be under 200ms.

response time under 200 milliseconds

Geographical location is a factor in server response time so it's worth running some tests to confirm that the hosting provider offers adequate speed for the regions most commonly served. Response time can also be influenced by general server demands, so the synergistic effect of an otherwise performance-optimized website will help make the most of server speed.

Uptime

Any service interruption in website hosting can lead to lost sales, so reliability is another important consideration. Downtime among reputable web hosts is generally rare and brief, but as with any aspect of choosing a hosting provider it's worth doing some research on the credibility of advertised or guaranteed uptime.

HTTPS & HTTP/2

HTTPS and HTTP/2 help make websites secure and fast.

HTTPS

Anytime the privacy of personal information is a concern, like online purchases and form submissions, total security is a must. HTTPS adds a layer of security to the connection by authenticating and encrypting the exchange of data, preventing eavesdropping and other security risks.

In the past, HTTPS was generally only used for banking, ecommerce or other applications that involve sensitive data, but it's now commonplace for all types of websites. Even for purely informational websites that don't use private or sensitive information, HTTPS ensures that data transferred between the web server and the user isn't tampered with or altered.

Modern web users associate secure websites with credibility and trustworthiness, so using HTTPS demonstrates a commitment to protecting the interests of the customer. As a bonus for SEO, search engines favor secure websites, so HTTPS also improves search engine visibility.

Although securing a website with HTTPS doesn't make a significant impact on load time by itself, it does make it possible to take advantage of a feature than can: HTTP/2.

HTTP/2

Together with other layers of technical systems that make the internet work, HTTP is the networking protocol that allows web servers and web browsers to communicate. At the time of its original development, HTTP didn't anticipate the way the internet would evolve and the greater complexity of the modern web.

HTTP/2 is an updated version of the HTTP protocol, designed to better address that complexity and boost performance. One of HTTP/2's most notable improvements is the ability to transfer many files simultaneously, rather than just one or a few at a time. Given that most websites load several dozen to several hundred file resources, this has great potential to improve loading speed.

Browser developer tools can help confirm that a website is using HTTP/2. Some web hosting providers automatically use HTTP/2 for websites with HTTPS or it may have to be specifically enabled. The potential performance benefit is great enough that if a web hosting provider doesn't offer HTTP/2, it may be worth considering a different provider.

Although HTTP/2 doesn't technically require a secure connection, HTTP/2 and HTTPS effectively go hand in hand because modern web browsers only support HTTP/2 over HTTPS.

CDN

Transferring data around the internet involves some inherent delay, often called latency. Network latency is partly influenced by the geographic distance between the web server and the location of the device loading a website. In other words, the closer the web server is to the user, the faster a website will load.

A CDN (content delivery/distribution network) is a supplemental form of web hosting that aims to improve efficiency by caching and distributing files from a robust network of servers across a wide array of geographic locations. In addition to speed, CDNs also have the potential for greater reliability and resilience during temporary spikes in website traffic.

Common Files

The simplest way to benefit from a CDN is to load commonly-used files from one of the fast, reliable and free public CDN resources. In most cases, using a CDN is simply a matter of updating the path of the file.

For example, loading a self-hosted copy of the popular jQuery JavaScript library might look like this:

HTML
<script src="jquery.js"></script>

To use a CDN copy of jQuery - in this case from Google Hosted Libraries - update the reference to:

HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

One of the biggest potential benefits of free public CDNs is that in many cases the file won't need to be downloaded at all. CDN copies of popular code libraries like jQuery and other resources like Google Fonts are so commonly used across the internet that it's likely the user has already visited a website using that same file. The web browser saves that copy and reuses it instead of downloading it again, loading the page that much faster.

CDN Services

Beyond just common public resources, CDN services can be used to distribute files unique to a given website like images, CSS and JavaScript. CDNs can be separate services, but more and more web hosts are offering a CDN option as an add-on, so it may be as easy as activating that feature on the existing web hosting package.

HTTP Compression

HTTP compression is data/file compression applied by the web server to reduce the size of files for faster downloading. Once received by the user's web browser, the files are decompressed and used normally.

HTTP compression is best for text-based code files like HTML, CSS and JavaScript, rather than media files that are already compressed, like web-optimized images, video files and PDFs. The processing overhead is typically not worthwhile for already-compressed media files and in some cases applying HTTP compression to these files can even increase file size.

The exact method and details to setup HTTP compression will vary depending on the software and setup of the web server, but it typically involves enabling compression and then defining specific file formats to be compressed. Using the popular Apache web server as an example, enabling compression with the .htaccess configuration file might look like this:

.htaccess
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain text/html text/xml text/css text/svg text/javascript application/javascript application/x-javascript application/xml application/xhtml+xml image/svg+xml
</IfModule>

Cache Control

File caching is a powerful tool for reducing unnecessary data transfer as users navigate between different pages of a website and make repeat visits to view new content or make additional purchases. Web browsers are smart about storing and reusing files that have already been downloaded and cache control helps to maximize that benefit by specifying long shelf lives for stored files.

Although it's possible to configure more detailed options, in general cache control works by setting a maximum age for each file type. A common strategy is to set long expiration periods for static files that are unlikely to change and shorter periods for files that could change frequently. It's a good practice to set the expiration period for HTML files to a relatively short time to ensure that any recent content changes are loaded on subsequent visits.

As with HTTP compression, the details of managing cache control will vary depending on the specific server configuration. Some methods offer more options and finer control, depending on the need. For the Apache web server, a very simple cache control setup in the .htaccess configuration file might look like the example below - setting a default expiration period for all files, with longer or shorter times by file type as desired:

.htaccess
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
ExpiresByType text/html "access plus 1 hour"
</IfModule>

Cache Busting

Although important for loading performance, setting long cache expiration periods can interfere with users seeing updates to existing content and files. Cache busting strategies ensure that visitors see the most up-to-date versions of any recently updated files.

One such technique is to change the name of each updated file, forcing the web browser to recognize it as a different or new file and download a fresh copy. This is most commonly done by updating a numeric date at the end of a filename - like updating blog-styles-01-01.css to blog-styles-02-05.css and so on - each time the content of the file is updated.

Additional Resources

For websites using the popular Apache web server software platform, the .htaccess file included in the HTML5 Boilerplate front end template is a good example of a variety of server configurations like HTTP compression and cache control.