How to reduce the number of HTTP requests
As you might be aware of, I believe web site performance is truly a critical success factor, and I have written about it before in How to improve your web site performance – tips & tricks to get a good YSlow rating
What we have
With the advent of such great tools such as YSlow and Page Speed, looking at the practices of web sites like Google and Yahoo! and reading the excellent performance work done by Steve Souders, we have really learnt a lot, and have great resources.
Reducing the number of HTTP requests
One of the crucial things when it comes to improving performance is reducing the number of HTTP requests. According to Steve Souders: “An extra HTTP request adds 200+ milliseconds to a page (worldwide average)”. The latency between HTTP requests, and also the limitation in web browsers in regards to how many parallel HTTP requests a web browser can make, vastly affects the loading time of a web page.
When it comes to CSS and JavaScript, the general consensus is to concatenate all files of the same type into one file, and then minify them. To complement that, Kyle Simpson have done some interesting experimenting with his LABjs, and he writes more about his thoughts in LABjs: why not just concat? how controlled parallel loading could also prove to be efficient.
That leaves us with images. Without a doubt, both the size and number of images used in a web page, although pretty to look at, definitely poses a threat to having a fast web site, and I thought we’d look at the alternatives for dealing with that.
CSS Sprites
CSS Sprites are when you combine a number of images into the same image file. You then use background-position
in the CSS file to control what part of that image will be visible for a certain element. This way, instead of having a number of HTTP requests, there will be just one for a larger image file.
For instance, you can see this in action at Yahoo.com at the left hand side, with the icons in the list. Steve Souders has also created the excellent tool SpriteMe, in the form of a bookmarklet, that will analyze the current page to see which images you can combine, and also generate the images for the CSS Sprite. Another great alternative is the web site CSS Sprite generator.
There are a couple of downsides with CSS Sprites, though. One is that, depending on the design, it can become virtually impossible to combine some images, because their repeating pattern, reusage etc will prevent that. While the above mentioned tools are great, at the end of day, you always seem to end up manually tweaking your CSS Sprites images file(s) and CSS code.
Firefox engineer Vladimir Vuki?evi? has also written the interesting piece To Sprite Or Not To Sprite where he sheds some light on memory usage in web browsers and how large images aren’t always optimal.
So, at times CSS Sprites can be great, but they aren’t always the best choice.
Introducing base64-encoded Data URIs
Which leads us on to the highly interesting topic of base64-encoded Data URIs. For a more thorough explanation of what those are, I recommend reading Data URIs explained by Nicolas Zakas of Yahoo!. Generally, though, it’s about writing out binary files converted into data which describes the content.
What this means in practice is that in the HTML code or CSS file we can have the code for the contents, instead of just a reference to the file, which means that we completely eliminate that HTTP request. Just imagine having a web site full of images referenced, but none of them will cost one single HTTP request! 🙂
Let’s look at a real example of showing Smurfette via CSS.
Regular CSS background image
.smurfette { background: url(smurfette.png); }
Base64 Data URI as background image
.smurfette { background: url(data:image/png;base64,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); }
Comparing the alternatives
As you can see, the Data URI example is a lot of characters, but the beauty of it is that it describes the image inline, completely eliminating the need for a HTTP request! And sure, as you can see the file size will get bigger (especially in this example), but overall the result is much better than a huge number of HTTP requests. Besides, from my testing and reading about other peoples’ results, if you gzip your CSS file the resulting size is about the same as the regular image URL reference!
Web browser support
Data URIs are supported in:
- Firefox 2+
- Safari – all versions
- Google Chrome – all versions
- Opera 7.2+
- Internet Explorer 8+
Internet Explorer…
As you can see, Internet Explorer does actually support Data URIs from IE 8! However, Microsoft, not to get astray from their long-standing tradition of doing half-ass implementations, only support data URIs smaller than 32 kilobytes. That might sound like a lot, but naturally it becomes a stick in your eye when you have larger images. For instance, in the web site I work on now, I have two images that were too large as Data URIs for IE 8, so I needed to include those two specific files exclusively for IE 8.
What about Internet Explorer versions older than IE 8 then? Actually, interestingly enough they support the MHTML format, which is an alternative way to accomplish the same thing for older IE versions. Stoyan Stefanov, also of Yahoo!, have written about this approach in MHTML – when you need data: URIs in IE7 and under and related problems in Vista and Windows 7 in Data URIs, MHTML and IE7/Win7/Vista blues.
There is some serious trickery, and limitations, when it comes to getting MHTML working. I know a number of people who used it, but in my tests, I actually never got it to work properly. Looking at general web site statistics, though, IE 6 and IE 7 usage steadily decreases all the time. If you want to solve it with MHTML, absolutely, but for me personally, I believe with offering the Data URI solution to all of the above-mentioned supported web browsers, I will still reach a good majority of the market, and, importantly, future web browsers.
Tools for encoding
There are a number of terminal-based tools to convert your images into the base64-encoded format, and you also have the option of online image to base64 converters. However, doing all this conversion (fairly) manually and then pasting the code into your code is quite tedious. There has to be a better way, right?
Right! Nicholas Zakas has created the outstanding tool CSSEmbed, which takes a CSS file as input, goes through it and encodes all image references to base64. This means that the action of changing all your image references in your CSS file to base64-encoded is a matter of seconds!
Just download the cssembed JAR file, put it wherever you like (placed in the same directory as the CSS file below for simplicity) and then call it like this:
java -jar cssembed-0.3.2.jar styles.css > styles-base64.css
This creates a new file named myStylesheet-base64.css
where all image references have become base64-encoded. Awesome, right? It also supports conversion for MHTML for targeting older versions of Internet Explorer. Nicolas has written more about it and how it works in Automatic data URI embedding in CSS files.
High-traffic web sites using Data URIs
By now, I hope you are as excited as me about this! Imagine removing about 2/3 of all your HTTP requests in a second, thanks to CSSEmbed! And this practice is not some future technology that we might use in five years, it’s here today! Just take a look at the thumbnails in a Google search for monkey and the search button in Yahoo! Search, for instance, and you will see what I’m talking about.
Therefore, I hope this have inspired you to get faster web pages without compromising one bit with the content!
Acknowledgements
Great thanks to Malte Ubl for suggestions and help, and to Mark Wubben for discussing base64-encoding alternatives.
Good article, as always. When it comes to minifying Javacript and CSS I would like to recommend the tool "Minify" that has helped me a lot with this. It automatically combines and minifies CSS- and Javascript-files. No more manual work!
http://code.google.com/p/minify/
[…] How to reduce the number of HTTP requests […]
Embedding images using data-uri's can also be done using Juicer.
http://github.com/cjohansen/juicer
The current version has been marked as 1.0.0, but Christian has yet to build the gem and announce it to the world.
Pär,
Thank you!
And thanks for the tip about Minify – I plan to write a post about various options/tool for doing just that, so we have options no matter the platform.
Morgan,
Nice! Haven't used it myself, but I know you have (and I trust you 🙂 ).
[…] How to reduce the number of HTTP requests […]
Don't forget that you won't get any cache of the images if you embed them in the html. This means that you have to download the image for every page you visit, not just once the first time you visit.
For images in the css this might work because the css is usually the same all over the site and not changed that often, but don't get too excited and start adding data-uri all over the place.
Data-uri:s are great – we've used it once in a crazy Drupal module, Biurnal, that a colleague of mine wrote: http://github.com/hugowetterberg/biurnal
That module does some weird masking, mixing etc of images and colors to enable the changing of the entire color scheme of a site on the fly and every image of I think max 1kb is embedded directly into the css with data-uri:s while the rest is linked to.
It's currently used by eg. http://www.cosmopolitan.se/ and will also used by a big site we're currently developing at Good Old.
We're thinking about refactoring the data-uri part out as a separate module so that it perhaps can be used independently or in connection with Css Dry: http://drupal.org/project/cssdry
http://documentcloud.github.com/jammit/
You should also check out Jammit, which is a command-line tool and a Rails plugin for:
Defining asset packages with smart include rules.
Concatenating and compressing JS with Google's Closure Compiler, or Yahoo's YUI Compressor (included).
Performing automatic embedding of images into CSS as Data-URI and MHTML (safely, only whitelisted images less than 32k).
Ahead-of-time gzipping at the highest compression level.
Support for JavaScript templates.
[…] I found (through Twitter) two nice articles on data URIs: How To Reduce The Number Of Http Requests and Data URIs explained. The base64 encoding of images on a Mac is very easy through the […]
[…] How to reduce the number of HTTP requests – Robert's talk (tags: performance optimization css http webdesign javascript development tips) […]
Hi, thanks for bringing attention to the role of the number of HTTP requests when delivering a page.
But third-party requests are a big factor too. This blogpage itself makes 46 HTTP requests, and half are requests to Google, Flickr, Gravatar, Feedburner, etc.
Optimizing your own contributions to your own page is good, but wouldn't a reduction in the number of third-party requests help too?
tx, jd/adobe
[…] How to reduce the number of HTTP requests […]
How to reduce the number of HTTP requests…
One of the crucial things when it comes to improving performance is reducing the number of HTTP requests….
kfsajfdsjk,
Absolutely. When it comes to having it in the HTML, I'd be a little bit wary, but to have it in the CSS code, gzip it and then especially use it in conjunction with Expires headers is a great solution!
Pelle,
Great work, and thanks for the links!
jashkenas,
Nice, thanks for the tip!
John Dowdell,
Most definitely, third-party requests matter too. Naturally, as always, it's a matter of what kind of content you want to offer and pros and cons with that approach. If I were, for instance, to remove the Flickr pictures it would increase page loading and cut down on HTTP requests, but I think they are a nice way to present the content, so I choose to have them there.
However, it would be nice with Google, Flickr, Feedburner etc if they could offer their content as Data, and/or with various settings for gzip, Expires headers etc.
I had no idea Google actually uses data:URI. For me it's a strong point in adopting it 🙂
Kuroki,
Absolutely, Google know one thing or two about performance. 🙂
[…] posts How to improve your web site performance – tips & tricks to get a good YSlow rating and How to reduce the number of HTTP requests, I wanted to put together a good list of tools and approaches to concatenate and minify CSS and […]
Very interesting but IE still lag behind.
Opera Rules 🙂
People Club,
Glad that you found it interesting. 🙂
[…] How to reduce the number of HTTP requests – Robert’s talk […]
wonderful article. Had never heard about the Base64-Encoded Data URIs method before now. Thanks!
Gareth,
Glad I could inspire!
Beautiful post… Very well explained, Thanks for sharing.
-Deepu
Theres some very useful information there, thanks!
Deepu Balan, web design ashford,
Thanks, glad you liked it!
[…] Optimization – How to reduce the number of HTTP requests […]
[…] an interesting piece on reducing total HTTP requests per visitor. Some of the suggestions are implemented by many sites (including some web application […]
Interesting. I have not used this as of yet but with your description I think I will give it a shot on my next project. Thanks.
Kevin,
It's well worth it. 🙂
[…] How to reduce the number of HTTP requests At Robert's talk (via Nicholas Zakas) (tagged: webdev javascript css work todo ) […]
[…] unos días leí el artículo how to reduce the number of HTTP request, muy útil para acelerar la carga de nuestras webs. Además justo estos días atrás en […]
[…] unos días leí el artículo how to reduce the number of HTTP request, muy útil para acelerar la carga de nuestras webs. Además justo estos días atrás en […]
Imagine making your CSS files billions of times larger….
Adrian,
Imagine gzipping them, getting the same size, eliminating 60% of the HTTP requests and all the latency.
[…] How to reduce the number of HTTP requests […]
[…] How to reduce the number of HTTP requests (Robert’s talk) […]
[…] How to reduce the number of HTTP requests (Robert’s talk) […]
[…] are many ways to optimize your web pages. In addition to reducing HTTP requests and delivering compressed files, we can also minify code content. The easiest way to minify your […]
Very nice method. I have been looking for methods to reduce http request, i have used CSS Sprite and GZip and now, another great Method for testing. Thank you
[…] post es un resumen de un estupendo artículo How To Reduce The Number Of HTTP Requests de Robert […]
[…] Reduce HTTP calls http://robertnyman.com/2010/01/15/how-to-reduce-the-number-of-http-requests/ […]
[…] Robert Nyman;How To Reduce The Number Of HTTP Requests […]
Another tool for minifying is Granule Tag lib the http://code.google.com/p/granule/
It gzip and combine javascripts wrapped by g:compress tag
code sample is:
<g:compress>
<script type=”text/javascript” src=”common.js”/>
<script type=”text/javascript” src=”closure/goog/base.js”/>
<script>
goog.require(‘goog.dom’);
goog.require(‘goog.date’);
goog.require(‘goog.ui.DatePicker’);
</script>
<script type=”text/javascript”>
var dp = new goog.ui.DatePicker();
dp.render(document.getElementById(‘datepicker’));
</script>
</g:compress>
…
John,
Right, but this post is mainly focused on base64-encoding images.
[…] How to reduce the number of HTTP requests (Robert’s talk) […]
Very good article,
I used the function base64_encode php and it worked fine 🙂
Dermeval,
Thanks! Good to hear it worked out for you!
Hi there. It looks like it’s a great solution for my site, because I have a lot of requests that I’d like to eliminate. However, I do not know how to call a .jar file. Is there any way to find out how to call it?
Thank you in advance.
Roman,
You need to use a terminal on your platform, and then go to the directory with the JAR file.
For simplicity, place the CSS file in that same directory.
Then write this in the terminal and execute it by pressing Enter:
java -jar cssembed-0.3.2.jar styles.css > styles-base64.css
[…] How to reduce the number of HTTP requests (Robert’s talk) […]
[…] How to reduce the number of HTTP requests […]
[…] unos días leí el artículo how to reduce the number of HTTP request, muy útil para acelerar la carga de nuestras webs. Además justo estos días atrás en […]
[…] unos días leí el artículo how to reduce the number of HTTP request, muy útil para acelerar la carga de nuestras webs. Además justo estos días atrás en […]
I still don’t get it, can i just use tools for reduce the number or i must writting the code?