Data URI's slow down page

4.5k Views Asked by At

I built a script that replaced all inline images with data URI's to reduce http requests and seed up loading time on mobile devices.

Unfortunately I experienced slower loading. I figure it depends on that the html file was bigger (around 100kb instead of around 5 kb) :)? Or is there something else with data URIs that slows down the page load?

Must the browser complete download of the full document before it can load liked sources in it? Or will linked sources, for example css and javascript in the top of document, be loaded before browser has completet the full document?

How does it work with CSS? Must the browser load the complete CSS file before reading all the CSS settings?

If so, is it better to have a sepearate CSS file for data uri like this:

  1. Load CSS for structure (no data uri's)
  2. Load CSS for background images (all background images in URI format)

Will a "separate chaced jpg file" load faster than a "URI based image included in a cached css file"?

Any other suggestions on how to use data URIs?

3

There are 3 best solutions below

2
On BEST ANSWER

mobify.com published a blog post: On Mobile, Data URIs are 6x Slower than Source Linking (New Research)

[…]
So you can imagine my surprise to discover, when measuring the performance of hundreds of thousands of mobile page views, that loading images using a data URI is on average 6x slower than using a binary source link such as an img tag with an src attribute!

I didn’t dig into this post, but I guess part of the problem might be the required CPU power for decoding base64-encoded data URIs.

The author recommends to use data URIs only "infrequently for small images".

1
On

HTML contents are loaded in order they appear in the HTML file. Data URI's of large size slows down the page. Large Data URI are not supported in IE browsers(IE6).

Data URI for image size less than 20KB is recommended & normally used.

You have the option of image compression, js, css compression to increase pagespeed.

0
On

TL;DR: using data URIs will delay loading the HTML if the images are large

I built a script that replaced all inline images with data URI's to reduce http requests and seed up loading time on mobile devices.

This is a good idea if the time to perform requests is greater than the time to download the images, since the browser needs to download the image data in any case (whether data URI or not). If the image is embedded in the HTML as a data URI, you will increase the total size of the HTML by the sum of the size of all of the images (plus about 33% for the data URI encoding).

E.g. if the time to open a connection for a new request is 1s, and your images take 0.2s each to download, and you have 10 images, and your HTML takes 0.5s to download then, it will take:

  • 1s + 0.5s = 1.5s for the HTML alone
  • 10 x (1 + 0.2)s = 12s for the images

If you encoded the images into the HTML as data URIs (which are 33% larger):

  • 1s + 0.5s + (10 x 0.2s x 1.33) = 4.2s
  • (and no external requests for images)

An important factor here is how long it takes to get the whole HTML source of the page (1.5s vs 3.5s). If it's critical that you have the images when the page is drawn, data URIs would be a good optimization. If it's acceptable to draw most of the page with the images loaded asynchronously, it might be better to optimize for downloading the HTML completely first.

And if your images are large, it's much worse to encode them as data URIs. If each image takes 1 second to download and the other factors are the same:

With external images:

  • 1s + 0.5s = 1.5s for the HTML alone
  • 10 x (1s + 1s) = 20s for the images

With data URIs:

  • 1s + 0.5s + (10 x 1s x 1.33) = 14.8s until the HTML is downloaded!

I figure it depends on that the html file was bigger (around 100kb instead of around 5 kb) :)?

As the browser downloads the HTML source of the page it begins interpreting and displaying it. When it reaches elements that refer to a separate resource, like images with external URIs (not data URIs) and (async) script tags, it will begin or queue downloading them, but continue downloading and processing the HTML of the page.

This means that as the page downloads, the user sees more and more of it, albeit without images and sometimes fonts loaded.

When the browser reaches an image tag with a data URI, it has to download and parse the whole data URI string before it can process anything after that in the HTML source. So if your original HTML was 1kb and you embed an image data URI of 1MB, there's going to be a pause when the browser reaches that image tag as it downloads the 1MB of HTML source occupied by the data URI-encoded image, before it processes any more of the page's HTML.

Must the browser complete download of the full document before it can load liked sources in it? Or will linked sources, for example css and javascript in the top of document, be loaded before browser has completet the full document?

Linked sources have their own loading and parsing logic. <script> tags will be loaded synchronously - blocking the browser from parsing any more of the HTML source until the referenced script is loaded and executed - unless they have the async attribute. External stylesheets will be downloaded in parallel but will block rendering until they're loaded.

There's a good explanation here.

If so, is it better to have a sepearate CSS file for data uri like this:

  1. Load CSS for structure (no data uri's)
  2. Load CSS for background images (all background images in URI format) Will a "separate chaced jpg file" load faster than a "URI based image included in a cached css file"?

Any other suggestions on how to use data URIs?

It depends what you want to optimize for. Are you more interested in time to first render, even if the page is incomplete? Or time until the whole page, with all images, is rendered in full?

Like any tool, there's no blanket rule that will apply, like "always use data URIs" or "never use data URIs". A good rule of thumb is use data URIs for small images like icons. Webpack's url-loader implements this logic automatically, using data URIs for files up to a specified size and otherwise using external URLs.