How preloading an image led to it downloading twice on our Rails Heroku app

Kevin McCarthy
2 min readMar 8, 2021

--

TL:DR due to domain sharding our preloaded image URL did not match our loaded image URL and so we downloaded the image twice

Preloading the main image

To improve our LCP (Largest Contentful Paint) something we’ve been doing is preloading the image

It looks like this

<link rel="preload" as="image" href="<%= pdp_main_photo(@listing) %>">..... LOADS OF OTHER HTML<img src=<%= pdp_main_photo(@listing) %> alt="<%= pdp_main_photo_alt_text(@listing) %>

What this does is it starts downloading the image before it’s needed so its available when the browser wants to render it and should be faster on the page.

The problem — image downloads twice

When I was looking in the network tab of Chrome I noticed that the image was downloading twice.

The name of the file is exactly the same but the URLs are very slightly different. The first starts with assets-vinterior-0 and the second image starts with assets-vinterior-2 .

So when the code resolved it looked like

<link rel="preload" as="image" href="https://assets-vinterior-1.vinterior.co/lovely-chair-image">..... LOADS OF OTHER HTML<img src="https://assets-vinterior-3.vinterior.co/lovely-chair-image"> alt="a really lovely chair">

I’ve seen this before but have never dove into whats going on. However this was effectively making the preload completely pointless 75% of the time.

Whats going on with the variations in URL?

I found some relevant code in our carrierwave.rb initializer file.

if Rails.env.production?  config.asset_host = proc do |_file|    # The number of CNAME asset records we have setup    # e.g assets-0.vinterior.co, assets-1.vinterior.co etc etc    identifier = rand(0..3)    "https://#{ENV['AWS_CLOUDFRONT_SUBDOMAIN']}-#{identifier}.vinterior.co"  endend

Okay so it seems we’ve got 4 different URLs which will all resolve to the same end domain.

First solution for getting around it

We added a wrapper method around the creation of the URL so it always requests from the same subdomain.

def use_zero_asset_variant(url)  # for preloading images we always want to use the same image url   when preloading and when rendering  # as the assets urls are created with random numbers between 0 and 3 we always want to return 0 for  # our main hero image  split_url = url.split(".")  split_url[0][split_url[0].length - 1] = "0"  split_url.join(".")end

Why have different URLs all resolving to same domain?

This is something called domain sharding which is a way of getting around browsers limit to the number of connections to a single domain they allow. Originally for HTTP1 this was limited to 2 connections per domain. You can read about more about this here.

However the vast majority of providers are on HTTP2 (except heroku grrr) so this isn’t something we see very much anymore.

Because heroku still only supports HTTP1 and so therefore we have to keep the sharding and our weird workaround for the moment.

--

--

No responses yet