Optimizing CSS Coverage with Powershell

Fri, Apr 30, 2021 2-minute read

When optimizing website performance, the performance tools that Google has built are magical.

One place I started when working on my site’s revamp was Google’s PageSpeed Insights. After running an analysis on my home page, I saw this warning:

Almost a second of my site’s page load time was caused by loading non-critical CSS. You can use the “Coverage” tool in Chrome’s dev tools to dig into this deeper:

As you can see, “all.min.css” was taking 60kb, and my homepage was only using 0.9% of it. This ended up being the CSS theme for all of font-awesome, even though I was only using a few of its icons. If you click on the stylesheet, Chrome even shows you which styles are in not in use (with a red bar to the side).

When you search around on how to optimize this to remove the unused styles, people generally mention scrolling through this view carefully and only keeping the items that they see being used. Unsurprisingly, there is a better way.

If you click the down arrow “Export” icon at the top of the coverage tab, Chrome lets you save the coverage results as JSON. This exported JSON looks like:

Because this is in JSON, PowerShell makes it super easy to make a new stylesheet that contains only the content that was used. Here’s what I ended up doing:

$json = Get-Content c:\temp\Coverage-20210430T172219.json -Raw | ConvertFrom-Json
$targetFile = $json | Where-Object URL -match font-awesome
$newContent = $targetFile.Ranges |
    Foreach-Object { $targetFile.text.substring($_.Start, $_.End - $_.Start) }
$newContent | Set-Content c:\temp\font-awesome-min.css -Encoding ASCII -NoNewline 

Chrome’s coverage tools have a little bug in that they don’t realize when CSS is being used to pull in a font, so I had to add in a few missing @font-face rules. But after this fix, the stylesheet now uses only 3kb and 100% of it is used by the initial page load.