How I Got 100% on Google PageSpeed Insights
January 4th, 2018
Google PageSpeed Insights reported a 100% score (mobile section) for this site at the time of writing.
Other performance testing sites all presented A+/100% results.
I set out to redesign my blog and throw in my consulting services in there. I decided to try a few techniques that I learned over the past couple of months, to get some practice. 90% of my work consists in experimenting, so that my customers would later benefit from the results.
Some I already knew, others I learned recently.
- Functional CSS. The minute my colleague Pablo Boerr explained it to me, I saw the light. No more CSS override hell, a smaller file footprint and much faster rendering (due to no more overrides). This is a nice explanation.
- Flexbox. My friend Rachel Andrew has been preaching this for layout since it came out, but I didn't get around to trying it. Bye bye heavy responsive CSS frameworks. Bootstrap is 119KB. My current CSS for the entire site, including a webfont and a syntax highlighter, weights 7.1KB before gzip. This is a handy guide.
- No JS. It's not really a technique, but this self-imposed constraint forced me to rethink what was really necessary and what was not, as well as learn CSS better. As a bonus, the site becomes a lot more accessible and weighs less. I wish more sites dropped JS.
- No tracking. I'm tired of 3rd party scripts loading a bunch of nonsense and hoarding visitors' private data. I'm paranoid about privacy. Then you have services that aggregate trackers, so you can send your visitors' data and even record on-screen actions in one easy step. Plus, those scripts usually account for over 80% of all data transfer and are often served from poorly-configured CDNs. You can achieve the same through focus groups and asking for feedback, rather than pushing the expense onto developers, who then bill countless hours debugging 3rd party integrations.
- No images. Why do we still load a bunch of high resolution stock images of random happy people that have nothing to do with our services? I just want something that looks nice. The content is what really matters to me though. I used a CSS pattern for the h1 and footer background, and a customized webfont for a few icons. My friends insist that I put my photo on the About page, but I'll think about it.
- CSS minification. My asset pipeline automatically combines all my .scss files and minifies them. Nobody wants to wait for whitespace to load. This should be standard practice in 2017.
- Compression. I configured my web server to gzip the files before serving them. This one brought the overall transfer size from 27.22KB to 10.33KB. Not that it matters, but it leaves room to add more content/CSS if need be.
- Expiry headers. They ensure that content is cached properly.
- On the desktop version (97% score), PageSpeed Insights still complained about "render-blocking CSS in above-the-fold content", but at a transfer size of 2.58KB, who cares?! I couldn't find a good way to satisfy this requirement without JS.
That said, I kept optimizing well after I hit the 100% mark, because I wanted to see what else can be fine-tuned, for research purposes.
From Crazy to Insane
Credit to my friend Philip Tellis for the above expression and for his advice on performance over the years.
- HTTP/2. Considered standard by some, not everyone enables it. Thanks to Ian Littman for suggesting it. It's as simple as adding a few characters to the server configuration. It took me 20 seconds to switch. The advantages are numerous, including binary transfer and connection reuse. I didn't bundle my assets for delivery to leverage browser caching, since the CSS and fonts are reused across pages.
- Inline font CSS. Fonts (icons) are loaded by the request of the CSS file. That's a problem, because we need to wait for the CSS to load before we request the font. Dependencies like this are a common performance killer. I generated the font-related CSS separately, then programatically inlined it. This adds 340 bytes to the HTML, but fonts can load immediately, instead of waiting for the much larger CSS.
- Minify HTML. Twig, the templating engine, has the
spacelesstag. This removes unnecessary whitespaces when generating HTML output. It doesn't go all the way to remove newlines, because of considerations such as
<textarea>. It uses a simple regex. Tokenizing and properly minifying it made little sense, as the CPU usage versus the few bytes we save wasn't worth it.
- CSS selector specificity. It's not just about how fast things load from the server. We must consider browser rendering time. Processing CSS can be a heavy operation when the developer doesn't take it into account, such as using only class selectors. I use more specific selectors to allow the browser to find the concerned elements faster, such as using IDs, parents and tag names. Think of it as database indexing.
Any other suggestions or remarks are welcome in the comments below.