Smaller is always better - RubyConf Thailand

8ec1383b240b5ba15ffb9743fceb3c0e?s=47 Phil Nash
September 07, 2019

Smaller is always better - RubyConf Thailand

Gzipping content has long been a best practice when serving text based files over the web. Turn on gzip compression in your web server, your users download smaller files quicker and everyone is happy, right?

That's what I thought as I went to tune my personal site over the holiday and I ended up writing 3 new gems and learning a whole bunch about the compression options available to us today. So join me on a journey to smaller and smaller files, discover how to tune your applications and find out how I ended up fighting a CDN over 1kB.

Links:

How to Gzip a file in Ruby: https://philna.sh/blog/2018/02/25/gzip-file-ruby/

jekyll-gzip: https://github.com/philnash/jekyll-gzip
jekyll-zopfli: https://github.com/philnash/jekyll-zopfli
jekyll-brotli: https://github.com/philnash/jekyll-brotli/

8ec1383b240b5ba15ffb9743fceb3c0e?s=128

Phil Nash

September 07, 2019
Tweet

Transcript

  1. SMALLER IS ALWAYS BETTER

  2. None
  3. PHIL NASH @philnash https:/ /philna.sh philnash@twilio.com

  4. None
  5. @philnash

  6. @philnash

  7. @philnash

  8. @philnash

  9. @philnash

  10. @philnash

  11. GZIP

  12. Accept-Encoding: gzip @philnash

  13. NGINX server { gzip on; gzip_disable "msie6"; gzip_vary on; }

    01. 02. 03. 04. 05. @philnash
  14. @philnash

  15. NEW GEM TIME @philnash

  16. JEKYLL-GZIP Jekyll::Hooks.register :site, :post_write do |site| if ENV["JEKYLL_ENV"] == "production"

    Jekyll::Gzip::Compressor.new(site).compress end end 01. 02. 03. 04. 05. @philnash
  17. JEKYLL-GZIP def compress site.each_site_file do |file| compress_file(file.destination(site.dest)) end end 01.

    02. 03. 04. 05. @philnash
  18. JEKYLL-GZIP def compress_file(file_name) zipped = "#{file_name}.gz" Zlib::GzipWriter.open(zipped, Zlib::BEST_COMPRESSION) do |gz|

    gz.mtime = File.mtime(file_name) gz.orig_name = file_name gz.write IO.binread(file_name) end end 01. 02. 03. 04. 05. 06. 07. 08. @philnash
  19. JEKYLL-GZIP def compress_file(file_name) zipped = "#{file_name}.gz" Zlib::GzipWriter.open(zipped, Zlib::BEST_COMPRESSION) do |gz|

    gz.mtime = File.mtime(file_name) gz.orig_name = file_name gz.write IO.binread(file_name) end end 01. 02. 03. 04. 05. 06. 07. 08. @philnash
  20. TABLE OF COMPRESSION Results when compressing unminified jQuery style bytes

    % uncompressed 271,751 - gzip default 80,669 -70.32% gzip best 80,268 -70.46% @philnash
  21. SMALLER IS ALWAYS BETTER

  22. @philnash

  23. ZOPFLI

  24. Accept-Encoding: gzip @philnash

  25. NEW GEM TIME @philnash

  26. JEKYLL-ZOPFLI require "zopfli" def compress_file(file_name) zipped = "#{file_name}.gz" contents =

    Zopfli.deflate(File.read(file_name), format: :gzip) File.open(zipped, "w+") do |file| file << contents end end 01. 02. 03. 04. 05. 06. 07. 08. @philnash
  27. TABLE OF COMPRESSION Results when compressing unminified jQuery style bytes

    % uncompressed 271,751 - gzip default 80,669 -70.32% gzip best 80,268 -70.46% zopfli 76,352 -71.90% @philnash
  28. SMALLER IS ALWAYS BETTER

  29. NGINX server { gzip off; gzip_static on; gzip_disable "msie6"; gzip_vary

    on; } 01. 02. 03. 04. 05. 06. @philnash
  30. @philnash

  31. BROTLI

  32. Accept-Encoding: br @philnash

  33. @philnash

  34. HTTPS @philnash

  35. NEW GEM TIME @philnash

  36. JEKYLL-BROTLI require 'brotli' def compress_file(file_name) compressed = "#{file_name}.br" contents =

    Brotli.deflate(File.read(file_name), quality: 11) File.open(compressed, "w+") do |file| file << contents end end 01. 02. 03. 04. 05. 06. 07. 08. @philnash
  37. TABLE OF COMPRESSION Results when compressing unminified jQuery style bytes

    % uncompressed 271,751 - gzip default 80,669 -70.32% gzip best 80,268 -70.46% zopfli 76,352 -71.90% brotli quality 6 75,302 -72.29% @philnash
  38. None
  39. JEKYLL-BROTLI require 'brotli' def compress_file(file_name) compressed = "#{file_name}.br" contents =

    Brotli.deflate(File.read(file_name), quality: 11) File.open(compressed, "w+") do |file| file << contents end end 01. 02. 03. 04. 05. 06. 07. 08. @philnash
  40. TABLE OF COMPRESSION Results when compressing unminified jQuery style bytes

    % uncompressed 271,751 - gzip default 80,669 -70.32% gzip best 80,268 -70.46% zopfli 76,352 -71.90% brotli quality 6 75,302 -72.29% brotli quality 11 66,920 -75.37% @philnash
  41. A FIGHT @philnash

  42. @philnash

  43. “A FIGHT” @philnash

  44. TAKEAWAYS @philnash

  45. JEKYLL https:/ /github.com/philnash/jekyll-gzip https:/ /github.com/philnash/jekyll-zopfli https:/ /github.com/philnash/jekyll-brotli @philnash

  46. RAILS 5 https:/ /github.com/miyucy/zopfli Rails.application.assets.gzip = :zopfli https:/ /github.com/hansottowirtz/sprockets- exporters_pack

    @philnash
  47. RAILS 6 - WEBPACKER! https:/ /www.npmjs.com/package/zopfli- webpack-plugin https:/ /www.npmjs.com/package/brotli- webpack-plugin

    @philnash
  48. ONE MORE THING @philnash

  49. IMAGES @philnash

  50. WEBP @philnash

  51. JEKYLL-WEBP PREVIEW def transform_file(file_name) extension = File.extname(file_name) compressed = "#{file_name}.webp"

    if extension == '.png' WebP.encode(file_name, compressed, lossless: 1, quality: 100, method: 6) else WebP.encode(file_name, compressed, quality: 75) end File.delete(compressed) if File.size(compressed) > File.size(file_name) end 01. 02. 03. 04. 05. 06. 07. 08. 09. 10.
  52. NGINX map $http_accept $webp_suffix { default ""; "~*webp" ".webp"; }

    location ~* ^/(assets|images)/.+\.(png|jpe?g)$ { add_header Vary Accept; try_files $uri$webp_suffix $uri =404; } 01. 02. 03. 04. 05. 06. 07. 08. @philnash
  53. RESULTS @philnash

  54. TABLE OF COMPRESSION All text files on https:/ /philna.sh style

    bytes % uncompressed 1,837,919 - zopfli 513,534 -72.06% brotli 511,707 -72.16% @philnash
  55. @philnash

  56. SMALLER IS ALWAYS BETTER

  57. None
  58. THANKS! @philnash https:/ /philna.sh philnash@twilio.com