Slide 1

Slide 1 text

Improving Frontend Performance Quick performance fixes with high impact

Slide 2

Slide 2 text

Philip Tellis Principal RUM Distiller @ Akamai Author of the OpenSource boomerang RUM library twitter:@bluesmoon ⦿ github:@bluesmoon speakerdeck:@bluesmoon

Slide 3

Slide 3 text

Agenda ● Image Optimization ● Compression ● Web Fonts ● JavaScript & CSS bundle sizes ● Preload Hints ● Web Workers ● Caching

Slide 4

Slide 4 text

Network Utilization By Asset Type Data collected and analysed with boomerang and Akamai mPulse

Slide 5

Slide 5 text

Image Optimization

Slide 6

Slide 6 text

https://imageoptim.com/

Slide 7

Slide 7 text

Alternate Image Formats ● WebP is a new, highly (lossy) compressed image format from Google ● SVG is a fairly well tested, uncompressed image format that is easy to inline and use over the wire compression Beware though that with new compression formats, hardware decoders haven’t caught up yet. https://developers.google.com/speed/webp/

Slide 8

Slide 8 text

Use 4:2:0 Chroma Subsampling Chroma Subsampling takes advantage of the fact that the human visual system is less sensitive to changes in colour than luminance http://en.wikipedia.org/wiki/Chroma_subsampling

Slide 9

Slide 9 text

Use Client Hints to resize images Resizing Images for specific screen sizes could be the difference between 1.5s and 30ms https://www.smashingmagazine.com/2016/01/leaner-responsive-images-client-hints/ https://httpwg.org/http-extensions/client-hints.html https://speakerdeck.com/tkadlec/mobile-image-processing-at-velocity-sc-2015

Slide 10

Slide 10 text

Accept-CH: DPR, Width, Viewport-Width ● DPR: Device Pixel Ratio ● Width: Actual image width ● Viewport-Width: Width of viewport in CSS pixels ● Downlink*: Client’s maximum download speed ● Save-Data*: Whether client has data saver turned on or not Client Hints https://www.smashingmagazine.com/2016/01/leaner-responsive-images-client-hints/

Slide 11

Slide 11 text

Compression

Slide 12

Slide 12 text

Enabling gzip is a no-brainer ● Reduce bytes transferred… Better for the user, better for the provider ● Dynamic content: use chunked transfer encoding with gzipped chunks, flush often. ● Static content: use gzip_static or equivalent. Bill Scott – Improving Netflix Performance

Slide 13

Slide 13 text

Newer Compression Formats ● ZopFli: Very good, gzip/deflate compatible, but slow to compress https://opensource.google.com/projects/zopfli ● Brotli: Better deflate using dictionary https://opensource.google.com/projects/brotli ● Detect browser support with the Accept-Encoding header @dougsillars https://medium.com/oyotech/how-brotli-compression-gave-us-37-latency-improvement-14d41e50fee4 https://paulcalvano.com/index.php/2018/07/25/brotli-compression-how-much-will-it-reduce-your-content/

Slide 14

Slide 14 text

Axxept-Endoding Many Windows anti-virus packages and firewalls will disable compression by munging the Accept-Encoding header on outgoing requests!

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Web Fonts ● Compress over the wire ● Reduce number of glyphs used ● Cache aggressively ● Use font-display: swap ● Use font-style-matcher (https://meowni.ca/font-style-matcher/) to find alternate fonts https://parall.ax/blog/view/3072/tutorial-reducing-the-file-size-of-custom-web-fonts https://css-tricks.com/font-display-masses/ https://developers.google.com/web/updates/2016/02/font-display

Slide 17

Slide 17 text

Split or Combine? ● Split JavaScript into smaller bundles, each under about 14 Kb (compressed). ● Only load critical JavaScript in the HEAD, load the rest after onload has fired. ● Keep CSS small, and inline critical parts. ● Serve CSS off the root domain. https://developers.google.com/web/fundamentals/performance/optimizing-javascript/code-splitting/ http://www.jonathanklein.net/2014/02/revisiting-cookieless-domain.html

Slide 18

Slide 18 text

Preload Hints https://medium.com/reloading/preload-prefetch-and-priorities-in-chrome-776165961bbf

Slide 19

Slide 19 text

Moving work off the main thread fetch(imageURL) // Get the image as a blob. .then(response => response.blob()) // Decode the image. .then(blobData => createImageBitmap(blobData)) // Send it to the main thread .then(imageBitmap => { self.postMessage({ imageBitmap }, [imageBitmap]); }, err => { self.postMessage({ err }); }); https://github.com/googlechrome/offthread-image

Slide 20

Slide 20 text

Caching Cache-control: public, max-age=31415926

Slide 21

Slide 21 text

References ● Chroma Subsampling ● Understanding Chroma Subsampling ● Essential Image Optimization ● High Performance Images ● Responsive Images with Client Hints ● Client Hints ● Mobile Image Processing ● Bill Scott – Improving Netflix Performance ● nginx gzip_static ● 37% Latency improvement with Brotli ● How much will Brotli reduce your content ● Reducing the file size of custom fonts ● font-display for the masses ● font-display: swap ● WebP ● SVG Tutorial ● ZopFli ● Brotli ● Font Style Matcher ● ImageOptim ● Preload Prefetch & Priorities in Chrome ● JavaScript Code Splitting ● Revisiting Cookieless Domains ● Lazy Loading Images with a Service Worker ● Service Worker Background Fetch ● Best Practices for Cache Control ● Cache Control for Civilians

Slide 22

Slide 22 text

Thank You!