Look Ma, No Image Requests!

Look Ma, No Image Requests!

A talk given at Velocity 2014 about reducing image requests.
Based on this blog post:
http://blog.pamelafox.org/2014/01/improving-front-page-performance.html

92dfeb863138a5a9c0453ed80f9c8c75?s=128

Pamela Fox

June 25, 2014
Tweet

Transcript

  1. Look, Ma, No Image Requests! Pamela Fox @pamelafox ! Velocity

    2014
  2. FIX-IT TIME!

  3. FIX-IT TIME!

  4. What are we loading? It’s time to scroll!

  5. What are we loading? Keep scrolling!

  6. What are we loading? Phew, done scrolling!

  7. The importance of “the fold” Yar! Thar be dragons! Who

    scrolls here? Where all the cool kids hang out!
  8. The importance of “the fold” Below the fold techniques Above

    the fold techniques
  9. Technique #1: tinyPNG https://tinypng.com/

  10. Technique #2: Data URI HTTP Requests Saved: 1 <a id=“header-logo”

    href=“/“! title=“Take me home!”! aria-label=“Khan Academy”>! </a> #header-logo {! background-image: url(data:image/ gif;base64,R0lGODlhEAAQAMQAAOR…);! width: 200px;! } <a id=“header-logo” href=“/“! title=“Take me home!”! aria-label=“Khan Academy”>! <img src=“images/logo.png”>! </a> http://css-tricks.com/data-uris/
  11. Technique #2: Data URI How to generate? Let me count

    the ways…. Image to Data URI Converter
  12. Technique #2: Data URI Or, bake it into the build

    process! _CSS_IMAGE_RE = re.compile(! r"(?:['\");} ]*?(\s*/\*! data-uri.*?\*/))?”, re.I)! ! for m in _CSS_IMAGE_RE.finditer(compressed_content):! image_url = m.group(1)! always_inline = m.group(2)! if (always_inline):! with open(img_abspath) as f:! image_content = f.read()! output.append(compressed_content[lastpos:m.start(1)])! output.append(_data_uri_for_file(img_abspath, image_content))!
  13. Technique #2: Data URI HTTP Requests Saved: 1 <a id=“header-logo”

    href=“/“! title=“Take me home!”! aria-label=“Khan Academy”>! </a> #header-logo {! background-image: url(“images/ logo.png”); /* data-uri */! width: 200px;! } <a id=“header-logo” href=“/“! title=“Take me home!”! aria-label=“Khan Academy”>! <img src=“images/logo.png”>! </a>
  14. Technique #3: Sprites HTTP Requests Saved: 2 homepage-sprite.png http://css-tricks.com/css-sprites/ csssprites.com

    bg.png, fb.png, goog.png
  15. Technique #3: Sprites HTTP Requests Saved: 2 homepage-sprite.png http://css-tricks.com/css-sprites/ csssprites.com

    bg.png, fb.png, goog.png
  16. Technique #3: FontAwesome HTTP Requests Saved: 3 http://khan.github.io/Font-Awesome/icons/ <span class=“icon-google">!

    </span>! <span class=“icon-facebook">! </span>! <span class=“icon-rss-sign">! </span> <img src=! “/images/google.png”/>! <img src=! “/images/facebook.png”/>! <img src=! “images/subscribe.png”/> http://fortawesome.github.io/Font-Awesome/
  17. Technique #4: Delay Load Images HTTP Requests Saved: 4 https://gist.github.com/pamelafox/8705015

    <div class=“feat-image”! data-delayed-bgimage=! "/images/feat1.jpg">! </div> <img src=“/images/tree.png”> <img data-delayed-src=“/ images/tree.png"> <div class=“feat-image”! style="background-image: ! url(/images/feat1.jpg);”>! </div>
  18. Technique #4: Delay Load Images HTTP Requests Saved: 4 https://gist.github.com/pamelafox/8705015

    var maybeLoadMedia = function(nearThreshold) {! $("#homepage [data-delayed-bgimage]").each(function() {! $(this).delayLoad(nearThreshold);! });! };! ! // On scroll, use very large threshold. Most people don't scroll homepage,! // but if they do, we want them to see everything.! $(window).on("scroll.load-media", _.throttle(function() {! maybeLoadMedia(600);! }, 100));! ! // Start with no threshold, items must be visible! maybeLoadMedia(0);
  19. Technique #4: Delay Load Iframes HTTP Requests Saved: 1+ <iframe

    width=“560" height="315"! data-delayed-src=“// www.youtube.com/embed/ gM95HHI4gLk"! src="about:blank">! </iframe> <iframe width=“560" height="315"! src=“//www.youtube.com/embed/ gM95HHI4gLk">! </iframe>
  20. Technique #4: Delay Load Widgets HTTP Requests Saved: 0 var

    maybeLoadSocialMedia = function(nearThreshold) {! if ($("#homepage #social-actions").inView(nearThreshold)) {! _.defer(function() {! Homepage.initSocialButtons();! });! $(window).off("scroll.load-social-media");! }! };! ! $(window).on("scroll.load-social-media", _.throttle(function() {! maybeLoadSocialMedia(1000);! }, 100));!
  21. Technique #5: Delete Unused Images HTTP Requests Saved: 1 .search-form

    .throbber {! background-image: url(/images/throbber.gif);! width: 16px;! height: 16px;! visibility: hidden;! }! ! .search-form .ui-autocomplete-loading ~ .throbber {! visibility: visible;! }! ! ! ! ! ! ! ! ! ! !
  22. The Exciting Results! http://blog.pamelafox.org/2014/01/improving-front-page-performance.html

  23. WILD APPLAUSE!!!!

  24. BUT…. Rome wasn’t perf’ed in a day.

  25. 1 day later…

  26. TODO: Remove inline data URIs Ilya, The Perf Guy @igrigorik

  27. Blog post all the things! http://blog.pamelafox.org/2014/01/improving-front-page-performance.html

  28. TODO: Fix iframe creation Ben Vinegar Iframe Man @bentlegen

  29. I never did my TODOs…

  30. 4 months later….

  31. Cutting everything below the fold A/B Test Results: ! Registrations

    ˛ 9.5% Math engagement ▼ ! Return visits same (Users still see content later)
  32. A FontAwesome’d logo <a id=“header-logo"! href=“/“>! <span class=“logotype-khan">! Khan! </span>!

    <span class=“logotype-academy">! Academy! </span>! </a> <a id=“header-logo"! href=“/“! aria-label="Khan Academy”>! </a> #header-logo {! background-image: url(“images/ logo.png”); /* data-uri */! width: 200px;! } #header-logo {! font-family: FontAwesome;! color: white;! font-size: 23px;! ! &:before {! color: @yellowGreen;! content: "•";! position: absolute;! left: -.35em;! }! }! .logotype-khan {! text-transform: uppercase;! }! .logotype-academy {! text-transform: lowercase;! }
  33. Dedicated infrastructure team!

  34. Client-side monitoring https://www.hostedgraphite.com/

  35. Server-side profiling Profilers: - Instrumented - Sampled - AppStats !

    ! 30% (500ms) loading the homepage 70% (1250ms) handling A/B tests ! After rewriting A/B system, A/B test time: ~0ms ! More than a 3x speedup!
  36. Server-side profiling ! After rewriting A/B system, A/B test time:

    ~0ms ! More than a 3x speedup!
  37. Let us conclude something!

  38. Perf is easy but also hard. You can improve performance

    significantly just by looking at image requests in 1 day of work. But performance is hard and quick wins could become losses. ! Dedicate engineering resources, and stay dilligent!