Date
Author
georges-gomes

Improving how images are embedded

Up until now, jampack v0.8.1 embeds ALL small images (<400 bytes).

The reasoning was: An HTTP header response is already around 400 bytes, why bother with an HTTP roundtrip? This is also using an HTTP request that could be used to retrieve something more important for the page.

Actually, all this concern is only valuable above the fold. Below the fold, images are only loaded when scrolling with loading="lazy". So, embedding images after the fold is actually not an improvement.

Target

I’m gonna use one of our websites to test it out: https://webcomponents.dev

Landing screenshot of WebComponents.dev

In this landing, jampack embedded the WebComponents.dev logo but not much.

Good performance already 😋.

First ByteStart RenderFCPSpeed IndexLCPCLSTBTTotal Bytes
.191S.300S.339S.382S.341S00S65KB
Browser request view from WebPageTest.org

A lot of waiting presumably because a lot of requests.

A lot of these images are above the fold.

Change 1: Embedding images only above the fold

Just add a little branch. Easy.

Change 2: Bumping the embedding threshold

Let’s bump the embedding limit to 1500 bytes when above the fold. We will embed more images but only where it matters: above the fold.

Change 3: Uncompressed images should be embedded too

jampack v0.8.1 would embed images only if they were successfully compressed to WebP or smaller SVG. For example, uncompressible SVGs were not embedded - even it below 400 bytes.

Change 4: Image dimensions

I initially thought that image dimensions were not necessary when the image is embedded. But I may be wrong.

Lighthouse is complaining and apparently images are loaded asynchronously anyway. https://github.com/GoogleChrome/lighthouse/issues/12233

Let’s add image dimension to embedded images too!

Results

Browser request view from WebPageTest.org after new version

Requests

From 23 requests to 19 requests. Freeing request capacity for more important resources.

CLS improvements?

No improvement on CLS as it’s dominated by font loading today. Something for later :)

HTML size

What is the impact of embedding these small images into HTML? In this particular example, a lot of small SVG images.

Before:

  • HTML Uncompressed = 30.4 KB
  • HTML Download = 4.0 KB (brotli)

After:

  • HTML Uncompressed = 38.4 KB
  • HTML Download = 5.6 KB (brotli)

So in this example, jampack removed 4 requests of images above the fold for maximum performance and added 1.6 KB of data into the HTML download.

Knowing that, anyway, an HTTP header would cost ~400 bytes of download, makes me feel good about the trade-off.

Released

  • jampack 0.9.0
  • jampack 0.9.1