Speed up your Ruby on Rails application using WebP images

Hello my dear friends.

Today we will speed up our rails application using webp images.

What is WebP?

WebP is an image format that employs both lossy and lossless compression. It was developed by Google. As we can see on this page, today only Google Chrome (+ Android) and Opera support this type of images. But it is not a problem. We can show webp images in these browsers, but in another browsers we will show a png, jpg or gif images.

WebP and Ruby on Rails

After the release of webp library I wrote webp gem - webp-ffi. You can use this gem to work with webp images in Ruby. Two good Ruby gems were released later - sprockets-webp and carrierwave-webp. Sprockets-webp provides a Rails Asset Pipeline hook for converting PNG and JPEG assets to the WebP format. At first, just add this gem in the Gemfile:

gem 'sprockets-webp'

And run:

$ bundle

Put some PNGs and JPGs into "app/assets/images" and you can test converter locally with the Rake task:

$ bundle exec rake assets:precompile RAILS_ENV=production

Now for each image webp will be created:

$ ls public/assets | grep webp
app_view-c1c11c4587eb1e6583df7825b76354eb.png.webp
bg-51830e3641c265cb246d752c57df3c20.jpg.webp
favicon-c594206ef399e642bd7024986158976c.png.webp
feature01-62e93a154b58089fe25e63a4e5087cf2.png.webp
feature02-24ee54e80423624080977fc17828bf23.png.webp
feature03-67de13538e75226fcdb1e4dd15d258bb.png.webp
feature04-28c1d1d55b982341f371ef519df06d36.png.webp
feature05-54a3ca87cd4ea2b4d8c6476181940b95.png.webp
feature06-7a7881a2640f8b879ec4defeb07e7d9b.png.webp
feature07-4b206a44dbf7181a1f653b157b8183de.png.webp
feature08-800ee165d1e6e854f55d92282a2df09d.png.webp
icon01-93581fe0eeaab8d135282a15f5ef8e3f.png.webp
icon02-e8efdd17d3f1f5d13f1d878240d55970.png.webp
icon03-1f3e94e02160b9fbeb2036490973150d.png.webp
logo-e424b8ca2552edb04331faf0da7f213c.png.webp
signin_block-3af7fa120ca9a6ea11d7bf63c1ec062b.png.webp
toggle-ae225a8eda983bb3344c2f496749cb3e.png.webp

If you want to convert images upload by users in your application, you can use carrierwave-webp (of course, if you use for this purpose carrierwave gem).

Nginx with WebP

We have to show webp images only in browsers, which support this format. For this purpose we will use Ngnix web server. Chrome and Opera advertise image/webp on its Accept header for all image requests. Now, we have to configure our Nginx server for automatically choosing the right file.

location ~ ^/(assets)/  {
   # check Accept header for webp, check if .webp is on disk
   if ($http_accept ~* "webp") { set $webp "true"; }
   if (-f $request_filename.webp) { set $webp "${webp}-local"; }
   if ($webp = "true-local") {
    add_header Vary Accept;
    access_log   off;
    expires      30d;
    rewrite (.*) $1.webp break;
   }

   root /some/folder/current/public;
   expires max;
   add_header  Cache-Control public;
   access_log  off;
   gzip_static  on;
   gzip_proxied any;
   break;
}

Then, we check if the Accept header is an advertising WebP. Then we check if there is a corresponding file with a .webp extension on disk. If both conditions match, we serve the WebP asset and add "Vary: Accept" header.

Results

Now we can see results of our work. First we check the speed of loading of our assets in Firefox (full image):

Firefox Webp

As we can see, many big image have size 145.07 Kb. Now let's check the result in Chrome (full image):

Chrome Webp

As we can see, image with size 145.07 Kb was converted in webp image with size 17.2 Kb. Another images also have smaller size, than png or jpeg images. By the way, the visual quality of images has not become worse.

Webp

As the result we reduced load time of rails application almoust in 2 times: before we have in average time 800ms, now an average response time of the page is 500ms.

Summary

As we can see using webp images, we have accelerated load speed of our application in Chrome and Opera browsers. Hopefully support of this image format will come into sight in Firefox (and maybe in IE).

That’s all folks! Thank you for reading till the end.

Published: November 23 2013

blog comments powered by Disqus