Hello my dear friends.
Today we will speed up our ruby on rails applications using webp images.
What is WebP?
WebP is an image format that employs both lossy and lossless compression. It’s been developed by Google and, as we can see on this page, so far only Google Chrome (+ Android) and Opera support this type of images. For our purposes though it doesn’t matter much, as we can show webp images in Chrome and Opera, and png, jpg or gif images in the other browsers.
WebP and Ruby on Rails
After the webp library has been released, I wrote a webp gem – webp-ffi. You can use it to work with webp images in Ruby. Also, two good Ruby gems were released a bit later – sprockets-webp and carrierwave-webp. Sprockets-webp provides a Rails Asset Pipeline hook for converting PNG and JPEG assets to the WebP format. To use it, 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 uploaded by users to 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 supporting this format and we’ll use Ngnix web server for this. Chrome and Opera advertise image/webp on its Accept header for all image requests. Now, we have to configure our Nginx server to choose the right file automatically.
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 and if there’s a corresponding file with a .webp extension on disk. If both conditions match, we serve the WebP asset and add “Vary: Accept” header.
Results
We can now view the results. First, we check the speed of loading of our assets in Firefox (full image):
As we can see, a lot of big images have a size of 145.07 Kb. Now let’s check the result in Chrome (full image):
Image with a size of 145.07 Kb was converted into webp image with a size of 17.2 Kb. Other images now also have smaller sizes than png or jpeg images. By the way, the visual quality of images has not become worse.
As the result, we reduced load time of rails application almost twice: from an average time of 800ms to an average page response time of 500ms.
Summary
Using webp images allowed us to accelerate load speed of our application in Chrome and Opera browsers. Hopefully, Firefox (and may be even IE) will also support this image format one day.
This is a re-post from my blog.