SVG Optimizer (SVGO) is a popular open-source tool that is used to minify SVG files. It works by “safely removing editor metadata, comments, hidden elements, [and] default or non-optimal values.” Looking at the Github Dependency numbers, SVGO is a pretty widely used tool being used in 4.6 million repositories. For reference, React is used in 7 million repositories.
SVGO is a well-maintained project that, in most cases, will remove all of the unnecessary characters that it safely can. However, as much it helps to reduce the page weight, what ultimately matters is whether or not it can make a visible difference in performance. This is precisely why Lighthouse prioritizes metrics like first meaningful paint (FMP), first contentful paint (FCP), and largest contentful paint (LCP), instead of the size of static assets and number of requests.
The question we need to ask is: does SVGO actually make a visible impact on performance? Let’s look at the details.
How many bytes can SVGO save?
The number of bytes saved by SVGO is largely dependent on the file it is minifying and how it was created. In some cases, it might reduce the file size by a low single-digit percentage, and in some cases, the figure might be as high as 90 percent. It’s especially effective against vector files created with tools like Sketch and Adobe Illustrator that have very precise values, spaces, long names, and comments.
To put it to the test, I tried SVGO on various SVG bundles and compared their file sizes before and after minifying under the standard defaults of SVGO. If you’re interested, you can view the raw data of my analysis.
Flagkit is an SVG icon-set of country flags created with Sketch. As we said earlier, SVGO is very effective against files exported with this tool.
After running SVGO on all the icons in the set, here’s what the distribution of compression percentages looked like:
On average, SVGO reduced the file size by 54.8 percent. Cumulatively, for all the files, it saved around 446kB, or 56 percent. If we were to use all of FlagKit’s icons in our app, we would save slightly less than half a megabyte with SVGO.
The compression ratio is less stellar when compared to Flagkit, but that’s expected because the SVG files in this bundle are much larger. In this case, SVGO saved around 24.2 percent on average and cumulatively, 824kB, or 23.7 percent.
World map (HD)
Finally, let’s try a single large SVG file. An HD vector map of the world from amCharts is around 1.3MB in size.
Here, SVGO reduced the file size to 880kB, saving around 420kB, or 31.5 percent.
The savings between unminified and minified bundles amounted to:
- Unminified = 793kB
- Minified = 346kB
- Savings = 447kB
- Unminified = 3.4MB
- Minified = 2.6MB
- Savings = 805kB
- World Map:
- Unminified = 1.3MB
- Minified = 880kB
- Savings = 420kB
Missing component: Compression
You may have noticed that we’re missing a key step above: compression. Most static assets and HTML pages on the internet are delivered using GZIP compression. The more efficient brotli algorithm is already used by 30 percent of websites, according to W3 Techs. Both compression algorithms are able to significantly reduce the size of the static asset.
We should, therefore, compare the before-and-after file sizes post-compression. In this section, I’ll check the size of minified and unminified bundles when served via the Cloudflare CDN.
Note: based on my observations, the Cloudflare CDN uses Brotli level 3 compression by default, which is inferior compared to the maximum level 11 compression, but is still good enough for testing the final file sizes. If your CDN uses the best available compression, the difference in size would be even smaller.
Here’s what difference looked like between the size of bundles post-compression (I used the tool
- Unminified + brotli-3 = 127kB
- Minified + brotli-3 = 55kB
- Savings = 72kB
- Unminified + brotli-3 = 592kB
- Minified + brotli-3 = 470kB
- Savings = 122kB
- World Map:
- Unminified + brotli-3 = 503kB
- Minified + brotli-3 = 370kB
- Savings = 132kB
As we can see, the difference in size is much greater. Now let’s see what this means in the context of web performance.
Testing our findings in-app
For our experiment, we’ll try to load all of these files at once and see how significant this delta is.
svg-sprite to bundle all of our SVGs as CSS sprites to avoid multiple requests affecting the speed data. I uploaded the sprites as an npm package named
test-svgo and used the unpkg.com CDN to serve them. Therefore, all files were tested via Cloudflare CDN, similar to how you’d serve files in a production setting.
For its performance audits, Google Lighthouse, arguably the most popular performance scoring tool, uses a 1.6 Mbps↑/750Kbps↓ throttled connection, which represents the bottom 25 percent of 4G and the top 25 percent of 3G connections. This is equivalent to the Fast 3G mode in Google Chrome DevTools. I tested all three bundles on the same mode and noted the time it took to download them. Here are the results:
- Unminified + brotli-3 = 700ms
- Minified + brotli-3 = 309ms
- Savings = 400ms
- Unminified + brotli-3= 3.28s
- Minified + brotli-3 = 2.94s
- Savings = 620ms
- World map:
- Unminified + brotli-3 = 2.78
- Minified + brotli-3 = 2.05s
- Savings = 730ms
Is the difference here significant enough to make an impact? Yes, it is! However, there are big caveats to this.
Caveat 1: SVG doesn’t block render
SVG images are generally non-blocking resources, unless you’ve inlined them in your CSS. Unlike CSS and often JS, they won’t block the rendering of the page and can be loaded in parallel.
Google Lighthouse extensively prioritizes metrics related to user interactions.
Hence, the priority should be make the first render as fast as possible and then sequentially load everything else on the page.
By this definition, figuring out what needs to rendered first and prioritizing those resources instead is a much better way to improve performance than SVG optimization. Optimizing SVGs would make a real difference only if they are both large in size and absolutely must be loaded in the first fold.
Caveat 2: Bundling is often not preferable
Yes, it was true in the era of HTTP1.1 that bundling was the way to go to improve performance, but with HTTP2, the overhead for a request has significantly reduced. When you bundle SVGs, you also load files which aren’t immediately needed.
Take a look at these two sample pages from the
test-svgo project, page A and page B. Page A loads illustrations using a bundle, while Page B loads them directly. Page A is better at loading them all at once, but Page B starts rendering illustrations much faster — providing a better user experience.
In the bundles we created, the minification created a significant difference, but more often than not, we’ll want to use our files individually, and when loaded individually, minification hardly makes a visible dent in the performance. You can see this for yourself by look at the minified and unminified versions of the same pages we just looked at.
Caveat 3: It’s rare anyone needs this many SVGs on a single page
We did our testing assuming that we’ll have to load a lot of files (or one big one) to test SVGO’s capabilities. It’s possible that you might have multiple large illustrations on the page, and using SVGO can make a difference, but in most cases, those SVGs tend to be icons, logos, and simple illustrations.
Going from 1.2MB to 880kB is significant, but going from 2kB to 1.2kB doesn’t really make much of a difference, even if you have dozens of icons on the page. This is because in aggregate form, the savings would be way less, even if SVGO cut it down by 50 percent.
SVGO is a great tool that can meaningfully reduce the size of SVG files, but the savings are often limited because SVG files are often tiny — and unlike loading images in CSS or JS, which can block rendering of the page, SVGs can load in parallel.
SVGO makes sense for really large files, like the world map we tested in this article, but if you’ve got a limited number of smaller SVGs on your page, SVGO won’t drive up your performance. Plus, if you do need multiple SVGs, it’s likely that you won’t need to load them all immediately.
A bigger impact on performance can be driven by carefully thinking about which of your resources need to be rendered first.
Another case against SVGO is its impact on maintenance. If you’re maintaining two sets of SVGs, that’s great. But if you’re running SVGO on all your files, it becomes harder to do simple things like modify fills and strokes.
Overall, we shouldn’t worry about saving kilobytes if we end up losing sight of the bigger picture — the metrics that actually matter, like FMP, FCP, and LCP. To conclude, in most cases, minifying SVGs should not be a priority when optimizing for performance.
LogRocket: Full visibility into your web apps
LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.