high performance images: beautiful shouldn't mean slow (velocity eu 2015)

Post on 15-Feb-2017

5.351 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

@guypod

High Performance Images

Beautiful shouldn’t mean Slow

@guypod

Average Web Page Weight(Sep ’15)

Not 37%

Images 63%

Source: HTTP Archive

@guypod

Images On Average Page

Sep '12 Jun '13 Jun '14 Sep '15

696 KB891 KB

1,128 KB

1,383 KB

50 Reqs 56 Reqs 55 Reqs 54 Reqs

Requests KB

~2x!!!

Source: HTTP Archive

@guypod

Images Impact Performance

0

4750

9500

14250

19000

Load Time, 3G Speed

With Images No Images

-30%

@guypod

What Can you do?

@guypod

Image Compression

@guypod

Image Loading

@guypod

Operationalizing Image Optimization

@guypod

Image Compression

@guypod

Average Resource Size

CSS

JS

JPEG

0 10 20 30 40

37 KB

16 KB

9 KB

@guypod

RWD Sites Use Big Images

0

10

20

30

40

JPEG Size PNG Size

7.1 KB

20.8 KB

10 KB

31.6 KB

RWD Not RWD

@guypod

Tip #1: Pick The Right Format

@guypod

Image Formats On The WebOther 2%

GIF 23%

PNG 30%

JPEG 45%

@guypod

GIF• 28 Years Old (1987)

• 256 Colors

• Supports “Simple” Transparency

• Supports Animation

• Patented (now expired)

@guypod

PNG

• 19 Years Old (1996)

• 8-32 bit color palettes

• Alpha Transparency

• Not patented

@guypod

GIF -> PNG = 21% Savings

PNG File Size GIF File Size

Source: Styoan Stefanov, “Give PNG A Chance” (2009)

@guypod

JPEG

• 23 years old (1992)

• RGB Colors (24 bit)

• No Transparency Support

• A Lossy Format

@guypod

Bitmap

JPEG

Bitmap≠

Bitmap

PNG

Bitmap=

Lossy Compression

Lossless Compression

@guypod

JPEG

• 23 years old (1992)

• RGB Colors (24 bit)

• No Transparency Support

• A Lossy Format

@guypod

PNG -> JPG = MUCH SmallerPNG, 574 KB JPG, 110 KB

@guypod

JPEG: No Transparency

JPEGPNG

@guypod

WebP

0

3.75

7.5

11.25

15

File Size (KB)JPEG (q75) WebP

9.9 KB

14.4 KB

0

0.825

1.65

2.475

3.3

Bytes Per PixelPNG WebP

2.42 bpp

3.27 bpp -26% -31%

Source: Google Studies

@guypod

WebP Browser Support

@guypod

BPG• Less than 1 year old

• Lossless & Lossy

• Based on Video encoder HEVC

• H.265, successor of H.264

• Beat WebP & J2K in Mozilla Study

• Free (LGPL)Fabrice Bellard

(Creator of ffmpeg)

@guypod

FLIF• 0 years old

• Lossless

• Progressive

• Responsive Friendly

• No browser support

• Free (GPL)

Source: FLIF Creators Jon Sneyers & Harshad RJ

@guypod

New Image FormatsWebP JPEG XR JPEG 2000

Support Chrome, Opera, Android 4.x IE 10+ Safari on

iOS, OS X

Savings (over JPEG) 40-50% ~25% 15-20%

Mime Type image/webp image/vnd.ms-photo Soon: image/jxr image/jp2

Identification Accept: image/webp

Detect IE 10+

DetectSafari 5+

@guypod

Using Custom FormatsClient Side

<script src="picturefill.js"></script> <picture> <source type="image/webp" srcset="book.webp"> <source type="image/vnd.msphoto" srcset="book.jxr"> <img src="book.jpg" alt="a book"> </picture>

@guypod

Using Custom FormatsServer Side, Single URL

GET /book.jpg GET /book.jpg

OriginCDN/Cache

@guypod

Using Custom FormatsServer Side, Single URL

GET /book.jpg GET /book.jpg

GET /book.jpg Accept: image/webp

GET /book.webp

OriginCDN/Cache

@guypod

Using Custom FormatsServer Side, Single URL

GET /book.jxr

GET /book.jpg GET /book.jpg

GET /book.webp

GET /book.jpg User-Agent: MSIE 10 Accept: image/jxr*

OriginCDN/Cache

* Spartan

GET /book.jpg Accept: image/webp

@guypod

Tip #1: Pick The Right Format

@guypod

Tip #2: Control Quality

@guypod

JPEG Quality

High Quality

Low Quality

@guypod

Quality: 90Size: 66 KB

Quality: 75 Size: 37 KB

Quality: 40Size: 21 KB

Quality: 25 Size: 16 KB

@guypod

Quality: 90 Size: 66 KB

Quality: 75Size: 37 KB

Quality: 40Size: 21 KB

Quality: 25Size: 16 KB

@guypod

Quality Scale Is Per Format

Source: Nick Doyle Performance Calendar

Sim

ilarit

y

0.00

0.06

0.13

0.19

0.25

Quality0 25 50 75 100

JPEGJPEG XRWebP

@guypod

Detecting Excessive QualityWebPageTest

• Some stats about image quality on the web?

@guypod

Detecting Excessive QualityPageSpeed Insights

• Some stats about image quality on the web?

@guypod

Tip #2: Control Quality

@guypod

SIZE Doesn’t matter

It’s all about

TECHNIQUE

@guypod

Image Loading

@guypod

Tip #3: Size Images To Device

@guypod

Download & Shrink

102 KB 1876 × 520

(975,520 pixels)

@guypod

Download & Shrink

866px

240px

1876px

520px

.hp07img {width: 100%}

@guypod

Download & Shrink

866px

240px

1876px

520px

207,840 pixels

975,520 pixels

79% wasted pixels (~770K)

@guypod

Download & Shrink

866px

240px

1876px

520px

35,345 Bytes

110,744 Bytes

79% wasted pixels 68% wasted bytes

(~75KB)

@guypod

Download & Shrink

866px

240px

1876px

520px

79% wasted pixels 68% wasted bytes

79% wasted memory (3MB)

831K Mem Bytes

975,520 * 4(RGBA) = 3.9M Memory Bytes

@guypod

54IMAGES

On an Average Page

@guypod

– Jen Fitzpatrick, Google Maps

“...25% of new Android phones have only 512MB of RAM.”

@guypod

Download & ShrinkProcessing Times

Source: Tim Kadlec, “Mobile Image Processing”

@guypod

Implementing Responsive Images

<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" alt="A rad wolf">

@guypod

Implementing Responsive Images

<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" alt="A rad wolf">

Hint, Hint…

@guypod

Implementing Responsive Images

<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" alt="A rad wolf">

Hint, Hint…

@guypod

Implementing Responsive Images

<picture> <source media="(min-width: 40em)"

srcset="big.jpg 1x, big-hd.jpg 2x"> <source srcset="small.jpg 1x, small-hd.jpg 2x"> <img src="fallback.jpg" alt=""> </picture>

@guypod

Implementing Responsive Images

<picture> <source media="(min-width: 40em)"

srcset="big.jpg 1x, big-hd.jpg 2x"> <source srcset="small.jpg 1x, small-hd.jpg 2x"> <img src="fallback.jpg" alt=""> </picture>

Use Picturefill

@guypod

Which Breakpoints To Use?What Are your Users Using?

@guypod

Which Breakpoints To Use?How Big & Complex Are Your Images?

• Your Analytics

Source: Jason Grigsby, “Sensible Jumps In Responsive Image File Sizes”

Width Height File Size

1 320 213 25K2 453 302 44K3 579 386 65K4 687 458 85K5 786 524 104K6 885 590 124K7 975 650 142K8 990 660 151K

@guypod

Which Breakpoints To Use?How Big & Complex Are Your Images?

• Your Analytics

point # Width Height File Size

1 320 213 9.0K2 731 487 29K3 990 660 40K

Source: Jason Grigsby, “Sensible Jumps In Responsive Image File Sizes”

@guypod

FLIF Progressive “Breakpoints”

@guypod

1969x1307 pixels 299,643 bytes

FLIF Progressive “Breakpoints”

@guypod

1969x1307 pixels All 299,643 bytes

653x985 pixels (1:2) First 80,389 bytes

FLIF Progressive “Breakpoints”

@guypod

1969x1307 pixels All 299,643 bytes

653x985 pixels (1:2) First 80,389 bytes

492x326 pixels (1:4) First 37,014 bytes

FLIF Progressive “Breakpoints”

@guypod

Tip #3: Size Images To Device

@guypod

Tip #4: Prioritize Critical Images

@guypod

Below The Fold

Etsy 82%

Velocity 91%

Guardian 92%

@guypod

Page Content

Not Visible 62%

Visible 38%

On A Typical Page & Desktop Screen…

Image Requests

Not Visible 80%

Visible 20%

@guypod

Download & Hide

@guypod

Download & Hide

img {display: none}

@guypod

Download & Hide

Image Requests 79 78

Image Weight 2,258 KB 2,251 KB

@guypod

Lazy Load Images

<img src="book.jpg" alt="A Book">

<img src="1px.gif" data-src="book.jpg" alt="A Book" onload="loadImage(this)">

@guypod

Lazy Load Images<script> function loadImage(img) { var dataSrc = imgs[i].getAttribute("data-src"); if (dataSrc && isAboveTheFold(img)) { img.onload = null; img.src = dataSrc; } } </script> <img src="1px.gif" data-src="book.jpg" alt="A Book" onload="loadImage(this)">

@guypod

Lazy Load Images<script> function loadImage(img) { var dataSrc = imgs[i].getAttribute("data-src"); if (dataSrc && isAboveTheFold(img)) { img.onload = null; img.src = dataSrc; } } // Repeat check on viewport changes (scroll, resize...) </script> <img src="1px.gif" data-src="book.jpg" alt="A Book" onload="loadImage(this)">

@guypod

Defer Load Images<script> function loadImage(img, force) { var dataSrc = imgs[i].getAttribute("data-src"); if (dataSrc && (force || isAboveTheFold(img)) ) { img.onload = null; img.src = dataSrc; } else if (deferOthers) { window.addEventListener("load",

function() { loadImage(img,true)}); }} </script>

@guypod

The Infamous

PRELOADER

@guypod

HTML Parser<html> <head> <script src="main.js"></script> <link src="styles.css" type="text/css"> </head> <body> <img src="book.jpg"/> <img src="bag.jpg"/> </body> </html>

@guypod

HTML Parser

main.js

styles.css

book.jpg

bag.jpg

7

<html> <head> <script src="main.js"></script> <link src="styles.css" type="text/css"> </head> <body> <img src="book.jpg"/> <img src="bag.jpg"/> </body> </html>

@guypod

HTML Parser & Pre-parser

main.js

styles.css

book.jpg

bag.jpg

<html> <head> <script src="main.js"></script> <link src="styles.css" type="text/css"> </head> <body> <img src="book.jpg"/> <img src="bag.jpg"/> </body> </html>

@guypod

HTML Parser & Pre-parser

main.js

styles.css

book.jpg

bag.jpg

<html> <head> <script src="main.js"></script> <link src="styles.css" type="text/css"> </head> <body> <img src="book.jpg"/> <img src="bag.jpg"/> </body> </html>

@guypod

HTML Parser & Pre-parser

main.js

styles.css

book.jpg

bag.jpg

11

<html> <head> <script src="main.js"></script> <link src="styles.css" type="text/css"> </head> <body> <img src="book.jpg"/> <img src="bag.jpg"/> </body> </html>

@guypod

Who Initiates Image Downloads?

CSS 20%

HTML Parser 37%

Pre-parser 43%

Source: Ilya Grigorik, HTTP Archive

@guypod

HTML Parser & Pre-parser… <img src="1px.gif" data-src=“book.jpg" onload="loadImage(this)"/> <img src="bag.jpg" data-src="bag.jpg" onload="loadImage(this)"/> …

main.js

styles.css

book.jpg

bag.jpg

11

@guypod

HTTP/1.1 HTTP/2

@guypod

ExcessImages

Pre-ParserBoost

@guypod

Protip #1: LQIPLow Quality Image Placeholders

<img src=“LowQ.jpg” data-src=“HighQ.jpg” onload=“loadImage(this)”>

@guypod

Protip #1: LQIPLow Quality Image Placeholders

LowQ.jpg Quality: 25Size: 16 KB

<img src=“LowQ.jpg” data-src=“HighQ.jpg” onload=“loadImage(this)”>

@guypod

Protip #1: LQIPLow Quality Image Placeholders

LowQ.jpg Quality: 25Size: 16 KB

HighQ.jpg Quality: 90Size: 66 KB

<img src=“LowQ.jpg” data-src=“HighQ.jpg” onload=“loadImage(this)”>

@guypod

Protip #2: Selective Lazy Load

<img class="responsive-img" sizes="(min-width: 980px) 460px, (min-width: 740px) 340px, 100%" srcset="/w-460/<id>/500.jpg 460w, /w-340/<id>/500.jpg 340w,

/w-445/<id>/500.jpg 445w, /w-605/<id>/620.jpg 605w" src="/w-300/<id>/500.jpg">

@guypod

Protip #2: Selective Lazy Load

<img class="js-lazy-loaded-image responsive-img"

data-srcset="/w-220/<id>/1000.jpg 220w,

/w-160/<id>/1000.jpg 160w, /w-127/<id>/1000.jpg 127w"

data-sizes="(min-width: 980px) 220px,

(min-width: 740px) 160px, 127px" src="data:image/gif;base64,R0lGODlhAQABAAAAACH 5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">

@guypod

Protip #2: Selective Lazy Load

JS Disabled

<img class="js-lazy-loaded-image responsive-img"

data-srcset="/w-220/<id>/1000.jpg 220w,

/w-160/<id>/1000.jpg 160w, /w-127/<id>/1000.jpg 127w"

data-sizes="(min-width: 980px) 220px,

(min-width: 740px) 160px, 127px" src="data:image/gif;base64,R0lGODlhAQABAAAAACH 5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">

@guypod

Tip #4: Prioritize Critical

Images

@guypod

Operationalizing Image Optimization

@guypod

Tip #5: Encode Well• Quality Curve is NOT a Standard

• “Save For Web” is NOT just quality

• Decoding Is Standard, Encoding Is Not

• Notable Deltas: Chroma Subsampling, Per-Region Quality, Lossy PNG, SSIM-Based Quality…

• If you use one tool: ImageOptim (benchmark)

@guypod

Tip #6: Use Image Management Service

5 breakpoints * 2 Pixel Ratios * 3 Views *5 thumbnails * 100,000 Products/Articles…

And tomorrow?

@guypod

Tip #6: Use Image Management Service

5 breakpoints * 2 Pixel Ratios * 3 Views *5 thumbnails * 100,000 Products/Articles…

And tomorrow?

/q75/w120/book.jpg GET /book.jpg

OriginTranscoder

<Big, High Res Img><Right-Sized Img>

@guypod

Image Manager

@guypod

Cloudinary

@guypod

What Can You Do?

Enforce a Performance Budget

Image Compression

Choose The Right Format

Control Quality

Image Loading

Use Responsive Images

Prioritize Critical Content

Image Operations

Encode Well

Transcode in Proxy

@guypodFREE Copy at

http://bit.ly/hpi-preview

@guypod

Thank You!Guy Podjarny

@guypod

Reminder Free HPI Link:http://bit.ly/hpi-preview

top related