Gzip is the best friend of the data URI
Encoding data to Base64 increases its size by about 33% and this is the main reason why many developers are afraid to use data URI scheme. Well, this is fair, because the size really matters, but there are some important points that are often not mentioned. It’s a pity, because they can prove that sometimes it’s better to use data URIs (of course, if size is the only thing that bothers you).
To make it easier to understand how it works, we are going to analyze two HTML pages on which we display a 1x1 image. First, let’s see what happens when the browser loads the page #1 with the embedded image in the usual way:
- Browser sends a HTTP request (182 bytes) to the page URL.
- Server returns some HTTP headers (852 bytes) and the HTML markup (385 bytes).
- Browser detects that it needs to load an image and sends a new HTTP request (176 bytes) to the image URL.
- Server returns some HTTP headers (995 bytes) and the image contents (91 bytes).
Now let’s see the page page #2 that embeds the same image through a data URI:
- Browser sends a HTTP request (182 bytes) to the page URL.
- Server returns some HTTP headers (852 bytes) and the HTML markup (504 bytes).
As you can see, in the second case, the size of the HTML markup is +30.91% larger (+119 bytes), but the image is already loaded. Therefore, in the first case, you need to sum the size of the image and HTML markup. Now, the difference in size is only +5.88% (more exactly, +28 bytes). Not bad, but that’s not all: in the first case the browser sends two HTTP requests, which means it will be slower due to network delays. Moreover, the size of both requests and all headers will be approximately two times larger than page #2, so the total size of which will be -42.63% less.
If you’re glad data URI is the winner of this experiment, it is too early to rejoice, because data URI won only due to the fact that the size of the headers exceeds the size of the image. That is, the ratio will decrease for larger images and as a result the size of the second page will be larger. For clarity, refer to the following table:
Image | Total bytes (request + headers + body) | ||||
---|---|---|---|---|---|
W×H | Size | File URL | Data URI | Ratio | |
1×1 | 91 B | 2681 (358 + 1847 + 476) | 1538 (182 + 852 + 504) | -42.63% | |
8×8 | 281 B | 2873 (358 + 1849 + 666) | 1790 (182 + 852 + 756) | -37.70% | |
16×16 | 408 B | 3009 (361 + 1849 + 799) | 1963 (183 + 852 + 928) | -34.76% | |
32×32 | 623 B | 3224 (361 + 1849 + 1014) | 2251 (183 + 852 + 1216) | -30.18% | |
64×64 | 1.03 KB | 3661 (361 + 1850 + 1450) | 2831 (183 + 852 + 1796) | -22.67% | |
128×128 | 1.98 KB | 4636 (364 + 1850 + 2422) | 4124 (184 + 852 + 3088) | -11.04% | |
256×256 | 4.08 KB | 6788 (364 + 1851 + 4573) | 6992 (184 + 852 + 5956) | +3.01% | |
512×512 | 11.44 KB | 14324 (364 + 1852 + 12108) | 17040 (184 + 852 + 16004) | +18.96% | |
1024×1024 | 23.46 KB | 26648 (367 + 1852 + 24429) | 33465 (185 + 852 + 32428) | +25.58% | |
2048×2048 | 40.01 KB | 43589 (367 + 1852 + 41370) | 56053 (185 + 852 + 55016) | +28.59% | |
4096×4096 | 64.82 KB | 69001 (367 + 1853 + 66781) | 89933 (185 + 852 + 88896) | +30.34% | |
8192×8192 | 245.99 KB | 254521 (367 + 1854 + 252300) | 337293 (185 + 852 + 336256) | +32.52% |
Data URI lost the battle, but not the war, because it has a powerful ally, which is good at compressing data. Therefore, with its help we can get good ratios even for large images. I suggest looking at the same pages above for which I enabled the gzip compression:
Image | Total bytes (request + headers + body) | ||||
---|---|---|---|---|---|
W×H | Size | File URL | Data URI | Ratio | |
1×1 | 91 B | 2567 (357 + 1847 + 363) | 1389 (181 + 852 + 356) | -45.89% | |
8×8 | 281 B | 2759 (357 + 1849 + 553) | 1598 (181 + 852 + 565) | -42.08% | |
16×16 | 408 B | 2892 (360 + 1849 + 683) | 1734 (182 + 852 + 700) | -40.04% | |
32×32 | 623 B | 3107 (360 + 1849 + 898) | 1958 (182 + 852 + 924) | -36.98% | |
64×64 | 1.03 KB | 3543 (360 + 1850 + 1333) | 2394 (182 + 852 + 1360) | -32.43% | |
128×128 | 1.98 KB | 4514 (363 + 1850 + 2301) | 3299 (183 + 852 + 2264) | -26.92% | |
256×256 | 4.08 KB | 6666 (363 + 1851 + 4452) | 5201 (183 + 852 + 4166) | -21.98% | |
512×512 | 11.44 KB | 14202 (363 + 1852 + 11987) | 11749 (183 + 852 + 10714) | -17.27% | |
1024×1024 | 23.46 KB | 26522 (366 + 1852 + 24304) | 21680 (184 + 852 + 20644) | -18.26% | |
2048×2048 | 40.01 KB | 43463 (366 + 1852 + 41245) | 26819 (184 + 852 + 25783) | -38.29% | |
4096×4096 | 64.82 KB | 68875 (366 + 1853 + 66656) | 55088 (184 + 852 + 54052) | -20.02% | |
8192×8192 | 245.99 KB | 254395 (366 + 1854 + 252175) | 194361 (184 + 852 + 193325) | -23.60% |
Wow! The data URI page is always smaller and requires only one HTTP request. Definitely, it takes the cake! Especially if you take into account that as the number of images increases, everything becomes even better.
So now we know that gzip is a must-have thing if we plan to use Base64 encoded data URIs (in fact, you should always enable gzip when server outputs textual data). If you want to know if your server is configured correctly, check out the gzip online test.
However, given the victories proven on this page, this does not mean that you should always use data URI. On the contrary, you need to use it carefully and you must be sure why you need data URI, because it has several disadvantages.
Comments (25)
I hope you enjoy this discussion. In any case, I ask you to join it.