{"id":6309,"date":"2013-11-25T21:42:31","date_gmt":"2013-11-25T18:42:31","guid":{"rendered":"http:\/\/railsware.com\/blog\/?p=6309"},"modified":"2021-08-13T11:40:25","modified_gmt":"2021-08-13T08:40:25","slug":"speed-up-your-ruby-on-rails-application-using-webp-images","status":"publish","type":"post","link":"https:\/\/railsware.com\/blog\/speed-up-your-ruby-on-rails-application-using-webp-images\/","title":{"rendered":"Speed up your Ruby on Rails application using WebP images"},"content":{"rendered":"\n<p>Hello my dear friends.<\/p>\n\n\n\n<p>Today we will speed up our <a href=\"https:\/\/railsware.com\/blog\/ruby-on-rails-guide\/\">ruby on rails applications<\/a> using webp images.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is WebP?<\/h2>\n\n\n\n<p><a href=\"https:\/\/developers.google.com\/speed\/webp\/\">WebP<\/a> is an image format that employs both lossy and lossless compression. It&#8217;s been developed by Google and, as we can see <a href=\"http:\/\/caniuse.com\/webp\">on this page<\/a>, so far only Google Chrome (+ Android) and Opera support this type of images. For our purposes though it doesn&#8217;t matter much, as we can show webp images in Chrome and Opera, and png, jpg or gif images in the other browsers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">WebP and Ruby on Rails<\/h2>\n\n\n\n<p>After the webp library has been released, I wrote a webp gem &#8211; <a href=\"http:\/\/leopard.in.ua\/webp-ffi\/\">webp-ffi<\/a>. You can use it to work with webp images in Ruby. Also, two good Ruby gems were released a bit later &#8211; <a href=\"https:\/\/github.com\/kavu\/sprockets-webp\">sprockets-webp<\/a> and <a href=\"https:\/\/github.com\/kavu\/carrierwave-webp\">carrierwave-webp<\/a>. 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:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">gem 'sprockets-webp'\n<\/pre>\n\n\n\n<p>And run:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ bundle\n<\/pre>\n\n\n\n<p>Put some PNGs and JPGs into &#8220;app\/assets\/images&#8221; and you can test converter locally with the Rake task:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ bundle exec rake assets:precompile RAILS_ENV=production\n<\/pre>\n\n\n\n<p>Now for each image webp will be created:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ ls public\/assets | grep webp\napp_view-c1c11c4587eb1e6583df7825b76354eb.png.webp\nbg-51830e3641c265cb246d752c57df3c20.jpg.webp\nfavicon-c594206ef399e642bd7024986158976c.png.webp\nfeature01-62e93a154b58089fe25e63a4e5087cf2.png.webp\nfeature02-24ee54e80423624080977fc17828bf23.png.webp\nfeature03-67de13538e75226fcdb1e4dd15d258bb.png.webp\nfeature04-28c1d1d55b982341f371ef519df06d36.png.webp\nfeature05-54a3ca87cd4ea2b4d8c6476181940b95.png.webp\nfeature06-7a7881a2640f8b879ec4defeb07e7d9b.png.webp\nfeature07-4b206a44dbf7181a1f653b157b8183de.png.webp\nfeature08-800ee165d1e6e854f55d92282a2df09d.png.webp\nicon01-93581fe0eeaab8d135282a15f5ef8e3f.png.webp\nicon02-e8efdd17d3f1f5d13f1d878240d55970.png.webp\nicon03-1f3e94e02160b9fbeb2036490973150d.png.webp\nlogo-e424b8ca2552edb04331faf0da7f213c.png.webp\nsignin_block-3af7fa120ca9a6ea11d7bf63c1ec062b.png.webp\ntoggle-ae225a8eda983bb3344c2f496749cb3e.png.webp\n<\/pre>\n\n\n\n<p>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 <a href=\"https:\/\/github.com\/carrierwaveuploader\/carrierwave\">carrierwave<\/a> gem).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Nginx with WebP<\/h2>\n\n\n\n<p>We have to show webp images only in browsers supporting this format and we&#8217;ll use <a href=\"http:\/\/nginx.org\/\">Ngnix<\/a> 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.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">location ~ ^\/(assets)\/  {\n   # check Accept header for webp, check if .webp is on disk\n   if ($http_accept ~* \"webp\") { set $webp \"true\"; }\n   if (-f $request_filename.webp) { set $webp \"${webp}-local\"; }\n   if ($webp = \"true-local\") {\n    add_header Vary Accept;\n    access_log   off;\n    expires      30d;\n    rewrite (.*) $1.webp break;\n   }\n\n   root \/some\/folder\/current\/public;\n   expires max;\n   add_header  Cache-Control public;\n   access_log  off;\n   gzip_static  on;\n   gzip_proxied any;\n   break;\n}\n<\/pre>\n\n\n\n<p>Then, we check if the Accept header is an advertising WebP and if there&#8217;s a corresponding file with a .webp extension on disk. If both conditions match, we serve the WebP asset and add &#8220;Vary: Accept&#8221; header.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Results<\/h2>\n\n\n\n<p>We can now view the results. First, we check the speed of loading of our assets in Firefox (<a href=\"http:\/\/leopard.in.ua\/assets\/images\/rails\/webp1.png\">full image<\/a>):<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"http:\/\/leopard.in.ua\/assets\/images\/rails\/webp2.png\"><img decoding=\"async\" src=\"\/\/leopard.in.ua\/assets\/images\/rails\/webp2.png\" alt=\"Firefox Webp\" title=\"Firefox Webp\"\/><\/a><\/figure><\/div>\n\n\n\n<p>As we can see, a lot of big images have a size of 145.07 Kb. Now let&#8217;s check the result in Chrome (<a href=\"http:\/\/leopard.in.ua\/assets\/images\/rails\/webp3.png\">full image<\/a>):<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"http:\/\/leopard.in.ua\/assets\/images\/rails\/webp4.png\"><img decoding=\"async\" src=\"\/\/leopard.in.ua\/assets\/images\/rails\/webp4.png\" alt=\"Chrome Webp\" title=\"Chrome Webp\"\/><\/a><\/figure><\/div>\n\n\n\n<p>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.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"http:\/\/leopard.in.ua\/assets\/images\/rails\/webp5.png\"><img decoding=\"async\" src=\"\/\/leopard.in.ua\/assets\/images\/rails\/webp5.png\" alt=\"Webp\" title=\"Webp\"\/><\/a><\/figure><\/div>\n\n\n\n<p>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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>This is a re-post from my <a href=\"http:\/\/leopard.in.ua\/2013\/11\/23\/rails-and-webp\/\">blog<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;s been developed by Google and, as we can see on this page, so far only Google Chrome (+ Android) and Opera support&#8230;<\/p>\n","protected":false},"author":17,"featured_media":6312,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3],"tags":[],"coauthors":["Alexey Vasiliev"],"class_list":["post-6309","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"aioseo_notices":[],"categories_data":[{"name":"Engineering","link":"https:\/\/railsware.com\/blog?category=development"}],"post_thumbnails":"\/\/leopard.in.ua\/assets\/images\/rails\/webp2.png","amp_enabled":true,"_links":{"self":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/6309","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/users\/17"}],"replies":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/comments?post=6309"}],"version-history":[{"count":19,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/6309\/revisions"}],"predecessor-version":[{"id":14030,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/6309\/revisions\/14030"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media\/6312"}],"wp:attachment":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media?parent=6309"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/categories?post=6309"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/tags?post=6309"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/coauthors?post=6309"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}