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.
This workflow wasn’t ideal for a variety of reasons:
- Manual process.
- Need to maintain separate “critical” stylesheets for inlining.
- 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">
<!--#else-->
<style>
/* critical path CSS styles go here... */
</style>
<!--#endif-->
<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:
- Critical CSS inlined within the
<style>
element will load almost instantly. - loadCSS script will asynchronously load the remaining page CSS as not to block rendering.
- 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.
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