Boost Page Speed & Save Time Generating Critical CSS

Sun Apr 7, 2019

If you’ve built a website in the last few years, you undoubtedly have heard of Google’s Page Speed Insights. One consistent score I’ve struggled with delivering critical css in a separate file from my site’s main css. It seems like I never have the time to pull the critical above the fold styles and put them in their own file.

I primarily work in with Bootstrap with custom build tools, so I can include only what I need to minimize the amount of CSS in the my site’s CSS file. But that doesn’t help the critical CSS portion of my scores. I’ve recently added Critical (https://github.com/addyosmani/critical) to my build tools and it’s proven to be a useful tool. The first time I used it, my mobile score went from 78 to 99 and my desktop score when all the way to 100.

Why does this help? When a browser is first loading a webpage, it has to grab a few essential files before it can render the page. When I include the main.css as a whole, the file can be quite large depending on how much of the Bootstrap framework I include. Breaking apart the CSS into what the user can see in the viewport (above the fold) greatly reduces the time the browser has to download the critical CSS.

Now I should say that I use a static site generator called Hugo (https://gohugo.io). So it is fairly straight forward to implement, because I have static HTML every time my build script executes. Your implementation may need to be different.

1. Installation

This example is for a build script I wrote for the static site geneator Hugo. First I installed the Critical module using npm.

$ npm install critical --save

2. Build script

Then imported the module into my Gulp build script.

// First import the module
const critical = require('critical').stream;

function compileSass(done = () => {}){
  del([sassPaths.dest+'/*']);

  // Process Sass - generates main.css
  gulp.src(sassPaths.src)
    // .pipe(sourcemaps.init())
    .pipe(sass.sync().on('error', sass.logError))
    .pipe(autoprefixer())
    // .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest(sassPaths.dest));

  // Critical CSS - generates index.css
  gulp.src('public/index.html')
    .pipe(critical({
      base: 'public/',
      inline: false,
      minify: true,
      css: ['public/assets/css/main.css'],
      dimensions: [{
        height: 200,
        width: 500
      }, {
        height: 900,
        width: 1200
      }]
    }))
    .on('error', function (err) { log.error(err.message); })
    .pipe(gulp.dest('static/assets/css'));


  console.log('Bugo: Done compiling .scss files');
  done();
}

In the function compileSass, I am generating the file main.css. Then I process that file and the site’s home page (index.html). for a couple different screen sizes. This generates the site’s critical CSS into a file called index.css. You can change the process mutliple pages, but be aware that a new file will be generate for each page. Using the home page as worked for me pretty well, but it you find your seeing rendering errors for FOUC then use that page.

3. Add Styles

Next we’ll add index.css into the HTML’s head tag.

<link rel="stylesheet" href="/assets/css/index.css">

And finally defer the site’s main.css before the end body tag.

  <script type="text/javascript">
    /* First CSS File */
    var giftofspeed = document.createElement('link');
    giftofspeed.rel = 'stylesheet';
    giftofspeed.href = '/assets/css/main.css';
    giftofspeed.type = 'text/css';
    var godefer = document.getElementsByTagName('link')[0];
    godefer.parentNode.insertBefore(giftofspeed, godefer);
  </script>
</body>

This was so much less work than doing it manually, I’ll be using it again for all my projects.


Tags

Gulp Critical CSS Bootstap Performance