
120kb less
After quite some times working on rebuilding my website from the ground up and trying to spare user from downloading every useless bytes, I just found out that I was forcing a nice download of 120kb only for displaying a really discrete grain effect over the background.
If it seems easy to plan then orchestrate a full optimization of a system or a website, it is another set of affairs preventing long term degradation.
As I'm not planning on building an observability system for my personal website, I'll have to be careful with asset additions and changes like this one.
The culprit #
Once done with every thinkable tweak allowing for the lightest payload possible, I introduced, on second thought, a film-like grain effect applied over the background of my website. It was a simple .png file of 250px/250px, I didn't think much of its size. On top of that, it was converted and served either as a webp or an avif depending on the browser capabilities.
Taking my homepage as an example, with this new grain.avif image, I was going from these stats:
35 requests
27.4 kB transferred
66.1 kB resources
Finish: 10.95s
DOMContentLoaded: 4.71 s
Load: 8.91 sTo these:
36 requests
147 kB transferred
185 kB resources
Finish: 11.33 s
DOMContentLoaded: 4.67 s
Load: 9.26 sStats recorded with a 3G throttled connection.
The impact on loading time is anecdotal, but multiplying the transferred size by more than 5 feels like chopping my optimization work with an axe.
A simple fix #
At first, I was tempted to simply remove this effect, thus immediately resolving the issue. Except I'm quite fond of the texture it adds to my otherwise bland background.
Then, I searched for an alternate way of making a noisy grain effect that would be lighter and found it in the svg specification.
The following simple code was the answer:
<svg viewBox='0 0 110 110' xmlns='http://www.w3.org/2000/svg'>
<filter id='grain'>
<feTurbulence
type='fractalNoise'
baseFrequency='0.55'
numOctaves='3'
stitchTiles='stitch' />
</filter>
<rect width='100%' height='100%' filter='url(#grain)' />
</svg>This svg file weighs only 292b: more than 119kb less than the previous image.
The result #
Here, side by side, are the old and new noisy grain effects:

It is clearly not the exact grain when shown bare like that, but when used as an overlay, the effect is pretty much the same using this bit of css and adjusting opacity:
.grain {
position: absolute;
inset: 0;
background: repeat center/110px url("/public/images/grain.svg");
border-radius: 0;
opacity: 20%;
pointer-events: none;
}opacity needs to be adjusted: on a light background you may need to set it higher than on a dark one. mix-blend-mode can also be used in order to improve the grain integration depending on the color of your background.
Bonus: a live noise grain generator #
You'll find below a small web component I built in order to generate your own grain effect svg file with custom parameters. You can adjust the baseFrequency and numOctaves of the grain effect. Opacity can also be adjusted and text toggled for preview purposes.
See MDN documentation if you are interested in understanding the different parameters available for the <feTurbulence> SVG element.
As I keep moving things around on my website, it seems mandatory to take it slow and reflect on every change if I want to keep things clean.