Using SSI to detect cookies

In my never ending quest to micro-optimize the hell out of my site, I ran into a snag when trying to use SSI directives.

Version 10.2 of this site was my half-baked attempt at eliminating render-blocking CSS to speed up page loads. By manually inlining critical CSS via a Jekyll include and using loadCSS to asynchronously load the rest — I did pretty good.

Made Mistakes version 10 analyzed with Google’s PageSpeed Insights tool

This workflow wasn’t ideal for a variety of reasons:

  1. Manual process.
  2. Need to maintain separate “critical” stylesheets for inlining.
  3. Included a bunch of declarations that aren’t critical to rendering “above the fold” content — causing some file size bloat.

So with the help of Critical (and friends) I attempted to automated the process. Getting it working within the constraints of a Jekyll site with thousands of posts wasn’t easy, but I got close with a set of Gulp tasks. A tale for another day unfortunately…

Sorry a little off topic there, back to SSI directives.

I learned that to speed up things for repeat visitors, loading a cached version of the CSS instead of waiting for loadCSS to do its thing was preferred. By using Filament Group’s aptly named Enhance.js project as a boilerplate, this could be achieved by dropping a cookie and using SSI directives.

Structuring our HTML looks a little like like this:

<!--#if expr="$HTTP_COOKIE=/fullcss\=true/" -->
  <link rel="stylesheet" href="assets/stylesheets/style.css">
     /* critical path CSS styles go here... */
  <noscript><link rel="stylesheet" href="assets/stylesheets/style.css"></noscript>

The #if and #else conditionals are SSI directives used by Apache to do some neat things. In this context they determine if a cookie named fullcss has been set. If it has, cached CSS files will load using a standard <link> element. If it hasn’t, the inline CSS will be rendered by the browser instead.

For first time visitors:

  1. Critical CSS inlined within the <style> element will load almost instantly.
  2. loadCSS script will asynchronously load the remaining page CSS as not to block rendering.
  3. A cookie will be set to trigger the loading of cached CSS on future page loads.

After setting all this up and testing my pages against WebPagetest, PageSpeed Insights, and GTmetrix I saw an obvious drop in scrores. Apparently the SSI directives weren’t working as intended, causing style.css to render block each page load. Hmmmm…

Oh right, maybe it’s Cloudflare’s Auto Minifying setting mucking around! Sure enough, as soon I disabled their HTML minifier, lines like <!--#if expr="$HTTP_COOKIE=/fullcss\=true/" --> remained untouched. Unfortunately style.css was still render blocking the page.

Screenshot of Cloudflare’s Auto Minify settings.

Auto Minify removes unnecessary characters from your source code (like extraneous whitespace and comments).

Dug a little deeper and discovered you have to configure your server to permit SSI before they’ll be recognized. Oops! Dropped these two lines in my .htaccess file and everything magically worked.

Options +Includes
AddHandler server-parsed .shtml .html .htm

Screenshot of Google PageSpeed Insights score results.

So close to 100. If it wasn’t for the Google Analytics and AdSense scripts…