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. 7.

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

    scrolls here? Where all the cool kids hang out!
  2. 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/
  3. 11.

    Technique #2: Data URI How to generate? Let me count

    the ways…. Image to Data URI Converter
  4. 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))!
  5. 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>
  6. 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/
  7. 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>
  8. 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);
  9. 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>
  10. 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));!
  11. 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;! }! ! ! ! ! ! ! ! ! ! !
  12. 31.

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

    ˛ 9.5% Math engagement ▼ ! Return visits same (Users still see content later)
  13. 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;! }
  14. 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!
  15. 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!