loading...
Cover image for The Business Value of Speed - A How-To Guide - Part 3: Optimizations for the
  Critical Rendering Path

The Business Value of Speed - A How-To Guide - Part 3: Optimizations for the Critical Rendering Path

marcradziwill profile image Marc Updated on ・7 min read

The Business Value of Speed (3 Part Series)

1) The Business πŸ’° Value of Speed 🏎 - A How-To Guide - Part 1: The Critical Rendering Path 2) The Business πŸ’° Value of Speed 🏎 - A How-To Guide - Part 2: Metrics and mapping of Business Values 3) The Business Value of Speed - A How-To Guide - Part 3: Optimizations for the Critical Rendering Path

Last week I already published the second part of this series about performance metrics and mapping them to business values. In this part, I want to show a fast and straightforward to apply solutions to optimize for the Critical Rendering Path.

If you missed part 1 and part 2, I recommend you to go through the sequence of steps of the Critical Rendering Path in the first part, and relevant performance metrics and mapping them to business values in the second part.

This post is the last post of this series. I hope you enjoy it. If so, stay tuned for the next posts with my newsletter.


If you like this article, smile for a moment, please share it, follow me and subscribe to my newsletter.


Tldr;

This post is the third of the series about how to get the business value of site speed. In this part, we dive into the optimization of the Critical Rendering Path. On one side I show you some fast and straightforward solutions to apply,
and on the other hand, you read about the long-term solutions.

Table of Contents

  1. Introduction
  2. Optimizing for the CRP
  3. Next steps
  4. Conclution

1. Introdcution

You already know what the Critical Rendering Path is about and why it is so important. Now I want to show you how you can optimize for the Critical Rendering Path and in the best case with a fast and straightforward solution.

I walk through the main parts that are involved in the CRP like JavaScript, CSS and the HTML. As we now know how the browser processes them, we can take action. By optimizing for the Critical Rendering Path, we simply improve the time to the first render.

Keep in mind that you do not need to load all your assets in the under 1-second aim we set in part 1. Load things later is your best friend!

2. Optimizing for the CRP

Generally speaking from the theory of the Critical Rendering Path, we want to archive the following:

  • Minimize the number of bytes we send to the browser
  • Reduce the number of critical resources
  • Shorten the Critical Rendering Path length
  • Defer all non-critical assets

But how do we get there? For some who are regularly reading my blog, what comes now is well known. The most crucial rule in web performance: Measure before you optimize! There are some essential metrics about the initial render of your page that you can receive from webpagetest.org or Lighthouse, but as you read in part two, nothing beats Real User Monitoring.

It's not a secret that fewer assets result in faster sites and faster rendering. But many sites still don't use these straightforward techniques to improve.

Remove unsused parts

Unused CSS and JavaScript is possibly the biggest problem. You are blocking the parser and the render without having any benefit. How to remove it? You can use any tool that can tree-shake your unused code away. Depending on your environment, you might search for similar tools like the following, that I use:

Bundler tools

If you want to check how much CSS and JS code in your application is unused, you can view it in the Chrome Dev tools. And for example, if you are using webpack, you can install the Webpack Bundle Analyzer
to help analyze your installed packages.

Use Code-Splitting

Code-Splitting is probably the most effective way to remove unused JavaScript. In many cases, it is easy to set up and has a massive improvement for your site. Check the Tooling.Report for bundlers with Code-Splitting.

Check your imports

Always use the direct import of the code you need, when you implement on your runtime code. The bundlers above can work this out for you with tree-shaking and just import the necessary parts.

import _ from 'lodash'
import {find, groupBy} from 'lodash'

Seperate critical CSS and non-critical CSS

CSS files are render-blocking. The browser must load and process them before it can paint the first pixel. To have a fast render and still lots of awesome styles, you can separate your critical from the non-critical CSS. You critical
CSS is everything that you need to display the content above the fold. You can define it by yourself, what's critical for you and what's not critical.

How does this look work? Let's make an example consider the following line in your HTML:

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

In this case, the browser loads the styles.css file from the server and parses it right away while it blocks the rendering process. We can fix this by extracting the critical parts and inline them. For the sake of simplicity imagine we have an img and a h1 above the fold. Our inline CSS would look
like this:

<head>
  <style type="text/css">
    .img {
      max-width: 100%;
    }
    h1 {
      font-size: 30px;
    }
  </style>
</head>

But what happens with the rest of our styles? We defer them with a little trick. Check out the following two lines and read them carefully:

<head>
  <style type="text/css">
    .img {
      max-width: 100%;
    }
    h1 {
      font-size: 30px;
    }
  </style>
  <link
    rel="preload"
    href="styles.css"
    as="style"
    onload="this.onload=null;this.rel='stylesheet'"
  />
  <noscript><link rel="stylesheet" href="styles.css" /></noscript>
</head>

And did you get it? Simple right? With these to lines, we can load the rest of your CSS asynchronously. Note: The <noscript>-tag acts as a fallback for some browsers and the this.onload=null will help some browser not to re-call the stylesheet.

Seperate CSS for different screens

For CSS, you can apply some resource-specific information for the browser. You probably all know the print attribute for the link-tag. The browser still downloads the print.css stylesheet, but it won't block the rendering.

<link rel="stylesheet" href="print.css" media="print" />

You can use the media attribute to apply the screen specification.

<link rel="stylesheet" href="style.css" media="screen" />
<link rel="stylesheet" href="portrait.css" media="orientation:portrait" />
<link rel="stylesheet" href="widescreen.css" media="(min-width: 42rem)" />

Minification

Minify your assets. This advice is fashionable but still not used widelyβ€”Minify your JavaScript, your CSS and your HTML. HTML is render-blocking as well πŸ˜‰! With minification, you remove all unnecessary parts of your code like whitespaces and comments.

For webpack you can use the optimize-css-assets-webpack-plugin or terser, for grunt the grunt-contrib-cssmin and for gulp the gulp-clean-css plugin. Just to name a few.

Data compression

With compression, you can modify your data with a compression algorithm. Gzip is the most popular, but with Brotli there is a newer and even better compression algorithm you can use. If you want to check if your server supports Brotli, you can use the Brotli.pro tool.

Combine CSS and JS files

With the bundlers mention above, you are also able to combine your stylesheets or JavaScript files to reduce the number of critical resources.

Making JavaScript unblocking

For JavaScript, we have several possibilities depending on your use case and the task of the JavaScript. As JavaScript is render-blocking, you should use one of these options to improve your site.

  1. Load JavaScript asynchronously

With the attribute async you tell the browser to load your script asynchronously. As soon as the DOM parser encounters the script tag the browser requests it from the server and continues parsing the DOM. The script, therefore, does not block the HTML parser.

<script src="app.js" async></script>
  1. Defer JavaScript

The defer attribute tells the browser to run the script after the HTML parser finishes parsing the document, but before the event, DOMContentLoaded fires. But you can not use this technique for inline scrips.

<script src="app.js" defer></script>
  1. Re-order inline scripts

For inline script, unfortunately, you can not use async or defer. Inline scripts execute right away the browser parses them. Therefore you can place them at the end of your HTML right before the closing body tag.

3. Next steps

You find all the resources for this article on GitHub. Feel free to check it out, try some stuff or fork it.

After this series on the Business Value of Speed, you should be well packed to understand all the essential browser functions and processes, how to measure and map performance and business metrics and how to optimize your site for the Critical Rendering Path.

3. Conclution

Where are we now? In the last parts of my series, you read much about the Critical Rendering Path and what the browser needs to do before it can display your site. In the second part, I wrote about the relevant metrics and how you can map them to business values in Google Analytics. In this part of the series, you learned about simple optimizations for the Critical Rendering Path and your key metrics.

If you like this article, smile for a moment, share it, follow me, check out my RSS feed and subscribe to my newsletter.

Cheers Marc

Further Reading

The Business Value of Speed (3 Part Series)

1) The Business πŸ’° Value of Speed 🏎 - A How-To Guide - Part 1: The Critical Rendering Path 2) The Business πŸ’° Value of Speed 🏎 - A How-To Guide - Part 2: Metrics and mapping of Business Values 3) The Business Value of Speed - A How-To Guide - Part 3: Optimizations for the Critical Rendering Path

Posted on by:

marcradziwill profile

Marc

@marcradziwill

I am a web performance consultant, dev-trainer and frontend architect. (he/him)

Discussion

markdown guide