Pro tip: Increase webpage performance using sprite, data-uri and jammit

For quite some time at Josh Software, we have been concentrating on improving backend server performance. You can read about load testing and bench-marking and improving upload performance using nginx upload module. This post is about improving frontend performance by getting your pages to  load faster using techniques like sprites, data-uri and jammit.

These tools have been around for about a year now — and are highly recommended. First off – basics:

Data-uri

Data-uri provide a way to send binary data in-line in the CSS. So you can embed images (not links) directly into your HTML, CSS or even JS! For example:

.bullets {
   margin-left: 20px; background:
   url('data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/
//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U
g9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC')
   top left no-repeat;
}

However, there are few disadvantages of data-uri, some of them critical enough to consider its usage!

  • Data-uri is limited to 32kb
  • Internet Explorer 7 and below do not support data-uri. (You would be surprised how many people still use IE7 and even IE6!)

Sprite

Sprites have been used since the 70’s but its a recent entrant for combining with CSS. Sprites have been heavily used in gaming and 3-D hardware graphics. A sprite is a bunch of images grouped together into a single image. A CSS Sprite uses the image offset to render inner images. A good example of sprite code is here.

In the CSS, we use the background-position relative to the sprite image! If a website which has 50 tiny images, 50+ requests are sent to the server just to render that page. Using sprites, it would be only 1 request for a single image. The remaining images are rendered as offsets of the sprite. This reduces my server load from 50 to 1 for the images! Considering network latency, HTTP headers processing etc. — this itself brings on a solid performance boost!

There are plenty of ways to generate a Sprite . There are a few good resources for generating sprites — there is also a topic floating on quora on this (my inspiration for the blog btw). I preferred to write my own quick sprite generator. The gist is available here.

Using it is simple.

# this creates a png, so don't add the extension
css = SpriteWriter.new("/path/to/images/folder", "/path/to/sprite/img", "/path/to/css")
css.generate

Some examples of the work we have used sprite is at List.ly. If you look at the details of this page, you would find a tp-sprite.png The corresponding CSS shows how it is used.

Jammit

Jammit is a top-grade asset packaging library. It provides excellent compression techniques. It is highly configurable and can be used in different pages in different ways. It can be used along with data-uri, so it provides state of the art techniques for caching and serving images, CSS and JS.

It is frequently said that data-uri have now replaced using sprites. However, I dis-agree! Browsers which do not support datauri should also be catered to.

Using Jammit now provides us one alternative:

“embed_assets datauri” can be turned on in jammit. This turns on data-uri support for only those browsers which support data-uri. Others will ‘automagically’ be served the unmodified stylesheets!

In this way, we can choose which technique we require to load pages faster.

However, Jammit does not support sprites & datauri together. In my next post, I plan to show how we modified jammit code to serve sprites or datauri depending on the browser!

So, we now crank out the best possible options to load pages faster for ANY browser – be it datauri or sprites!

Stay tuned for further updates here.

I hope you found this article valuable. Feel free to ask questions and give feedback in the comments section of this post. Thanks!

Advertisements
This entry was posted in Ruby, Ruby on Rails and tagged , , , , , , . Bookmark the permalink.

23 Responses to Pro tip: Increase webpage performance using sprite, data-uri and jammit

  1. Christoffer Hammarström says:

    A sprite is not a group of images grouped together into a single image, see http://en.wikipedia.org/wiki/Sprite_%28computer_graphics%29

    • Gautam Rege says:

      Sprite being “a graphical overlay” would be more accurate.

      However, I guess, the aim of this post is not the get into the internal details of a sprite but how it can be used.

    • Dave Mauldin says:

      I think the miscommunication is in the specific use of the word sprite. A sprite is (one of many definitions) one of the many single images from the larger resource. An image containing many smaller images to be rendered individually is a sprite sheet.

    • Robert says:

      Oh come on, this has to be one of the most ridiculous comments ever!

  2. Nice post, I like the Sprite Generator. You should also take a look at my asset_id library http://github.com/moocode/asset_id to help page loading speeds. I haven’t tried it with jammit but it works with asset_packager so it should work.

  3. Gekkor McFadden says:

    Please post more fried chicken stories!!1

  4. Stephen Moran says:

    check this out for a cross-browser solution for the data-uri:

    http://www.phpied.com/the-proper-mhtml-syntax/

    in a nutshell, you can provide mhtml data uri for ie and regular for all other browsers

  5. Ruudjah says:

    Data-uri is limited to 32kb

    Afaik, this is only the case in IE8 and IE9. This limit is not present in other browsers

    • Gautam Rege says:

      Yes Ruudjah, you are right. This is a Internet Explorer statistic. However, most compression engines tend to not convert larger images into data-uri due to pending incompatibility.

  6. Steven Jackson says:

    This seems like a way to inject nefarious JavaScript into a page beneath the radar of content scanners.

    I think it is irresponsible of you to be promoting this.

    • Gautam Rege says:

      Hi Steven,
      I guess you have mis-understood. Datauri and sprites are accepted techniques to increase page-loading performance. Jammit is a compression asset manager among other things.

      Content scanners will scan ALL rendered HTML — so if someone inserts malicious JS, it will definitely be scanned!

      Like vzmind has mentioned, I too am keen to see why is nasty. Please give more details.

    • Dave Mauldin says:

      This is like saying you can do nefarious things with JavaScript, therefore the promotion of JavaScript is irresponsible.

  7. vzmind says:

    Damned Steven, that s frightning. Could you elaborate? Do you speak about a possible nasty use of data uri?

  8. Pingback: Quora

  9. Hi Gautam,

    Just wondering did you create the codes for list.ly ?

    If not, could you recommend anyone?

    Avin

  10. Andrej says:

    hey Gautam. Interesting article.
    Did you actually do some performance testing with data uris? Because in a test I just did, my page load time actually increased – due to a larger css file. Even though my requests (for css images) have gone done.
    What’s your experience?

    • jiren says:

      We have used datauri in list.ly and performance is good. We dont have any benchmarks for this. If you are using same image multiple time in css then css file size increase so better use separate css class for each image or use sprite image. Also dataurl is base64 encoded data so data size increase after encoding. For this you can use gzip compression in your server to reduce css response size.

  11. news feed says:

    Very good written story. It will be useful to anybody who employess it, as well as yours truly :). Keep up the good work – can’r wait to read more posts.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s