Let's talk about web performance

Outline

  • Why is important?

  • How impact our business?

  • How impact our users?

  • Tips and Tricks on how to improve performance

  • Prevent future degradation

  • Conclusion

Why performance matters?

#PERFMATTERS

Number of countries by Download Speed Experience range in 2019

73 Countries had a 4G Time availability of 90% or less in 2020

480 millions low-end devices shipments on 2020

low-to-mid end segment dominates the market share with 71%

External case studies

  • DoubleClick by Google found 53% of mobile site visits were abandoned if a page took longer than 3 seconds to load.
 
  • Every -0.1s, +1% Walmart revenue

Vodafone (Italy) improved LCP by 31% to achieve 8% more sales.

AliExpress made their site faster by 36% and got 10.5% more orders. Source

Performance is accessibility

When we say a site is accessible, we mean that the site's content is available, and its functionality can be operated, by literally anyone

Performance is not only about how fast is it but also how fast it feels

Performance ensures high-quality User Experience

Key questions to ensure performance

Is it happening?

Did the navigation start successfully? Has the server responded?

 

Is it useful?

Has enough content rendered that users can engage with it?

 

Is it usable?

Can users interact with the page, or is it busy?

 

Is it delightful?

Are the interactions smooth and natural, free of lag?

 

Performance ensures high-quality SEO

Let's divide the performance improvements into three categories:

  • Optimize for First Load

  • Optimize for Navigation Speed

  • Optimize for Repeat load

A conversion funnel

Let's build momentum for our Flywheel by improving web performance

Important metrics to measure

How metrics are measured

In the Lab:

The best way to prevent performance regressions, testing a feature before is released.

In the Field:

The only way to truly know how your site performs for your users is to actually measure its performance as those users are loading and interacting with it. This type of measurement is commonly referred to as Real User Monitoring—or RUM for short.

Lab vs Field data correlation

Largest Contentful Paint (LCP):

LCP metric reports the render time of the largest content element visible within the viewport.

LCP

Lab & Field

What elements are considered?

As currently specified in the Largest Contentful Paint API, the types of elements considered for Largest Contentful Paint are:

  • <img> elements
  • <image> elements inside an <svg> element
  • <video> elements (the poster image is used)
  • An element with a background image loaded via the url() function (as opposed to a CSS gradient)
  • Block-level elements containing text nodes or other inline-level text elements children.

First Input Delay (FID):

Measures the time from when a user first interacts with your site to the time when the browser is actually able to respond to that interaction

Field

Will be replaced by Interaction to Next Paint (INP) in March 2024

GOOD

BAD

Cumulative Layout Shift (CLS):

Measures the sum total of all individual layout shift scores for every unexpected layout shift that occurs during the entire lifespan of the page.

Lab & Field

Have you ever been reading an article online when something suddenly changes on the page?

Unexpected movement of page content usually happens because resources are loaded asynchronously or DOM elements get dynamically added to the page above existing content.

First contentful paint (FCP):

FCP metric measures the time from when the page starts loading to when any part of the page's content is rendered on the screen.

FCP

Lab & Field

Time To Interactive (TTI):

Measures the time from when the page starts loading to when its main sub-resources have loaded and it is capable of reliably responding to user input quickly.

Lab

  • The page displays useful content, which is measured by the First Contentful Paint,
  • Event handlers are registered for most visible page elements, and
  • The page responds to user interactions within 50 milliseconds.

Total Blocking Time (TBT):

Measures the total amount of time between First Contentful Paint (FCP) and Time to Interactive (TTI) where the main thread was blocked for long enough to prevent input responsiveness.

Lab

The main thread is considered "blocked" any time there's a Long Task—a task that runs on the main thread for more than 50 milliseconds (ms).

Consider the following mainthread timeline

So while the total time spent running tasks on the main thread is 560 ms, only 345 ms of that time is considered blocking time.

 

Speed Index (SI):

 

Shows you how quickly the contents of a page are visibly populated. It is the average time at which visible parts of the page are displayed. Expressed in milliseconds, and dependent on the size of the viewport, the lower the score, the better.

Lab

Core Web Vitals

Each of the Core Web Vitals represents a distinct facet of the user experience

Let's see some tips and tricks to improve performance

Download

JS Execution

Critical for slow networks

Critical for devices with slow CPUs

CPU

CSS

JS

IMG

FONT

The most expensive part of your site 

The main thread

Events

Javascript Code

Styles

Layout

Paint

Composite

Time

Browser receives user input

Browser can respond to the user input

Remove unused code

Find unused code using Chrome's Coverage Tool

Optimize CSS

  • Use PurgeCSS to help you removing unused CSS

Code-splitting

  • Allows you to create smaller bundles that can be loaded dinamically at runtime
  • Can reduce dramatically the initial amount of code needed during the initial load
 
  • Can help you “lazy-load” just the things that are currently needed by the user

Publish, ship, and install modern JavaScript for faster applications

Lazy-Loading Components

(Client-side)

Pick the right rendering pattern

Progressive Rehydration

(Lazy-Loading for Server-Side Rendering)

Convert your Class Components into functional components

A Tokopedia performance study case showed that there is a noticeable difference in chunk size when they migrated to Functional Components

Be careful using libraries

  • Use specific imports if the library doesn't support tree-shaking
  • Before installing a library find the cost of adding it to your project.
  • Make a before/after installation audit of your code
  • Use bundle analizers

Native image lazy-loading:

Supported on all browsers

<img loading=lazy src="images/i_love_burgers.jpg" />

Lazy-Loading Images

Lazy-Loading Images

Common approach:

Using Javascript or libraries like react-lazy-load.

<LazyLoad height={762} offsetVertical={300}>
	<img src='images/i_love_burgers.jpg' />
</LazyLoad>

Defer render until Decode (The optimal way):

(or download if img.decode() unsupported)

var img = new Image();
img.src = "i-love-burgers.jpg";

if('decode' in img) {
	img.decode().then(function() {
		document.querySelector("#container")
          .appendChild(img);
	});
}
else {
	// Use classic javascript lazy-load approach
}
  • Initiates loading without adding it to the DOM.

  •  The image can be rendered immediately upon being added to the DOM.

  • Prevents the rendering of the next frame after adding the image to the DOM from causing a delay while the image loads.

Avoiding Layout Shifting

 
  • Always include size attributes on your images and video elements, or otherwise reserve the required space with something like CSS aspect ratio boxes.

 

  • Never insert content above existing content, except in response to a user interaction. This ensures any layout shifts that occur are expected.

HTTP2

 
  • Multiplexing: is able to use a single TCP connection to send multiple streams of data at once
  • Server push: allowing a server to "push" content to a client before the client asks for it
  • Header compression: HTTP/2 uses a more advanced compression method called HPACK

HTTP3

 

Defer third-party libraries

 

Preloading resources

 

DNS prefetching:

This notifies the client that there are assets we’ll need later from a specific URL so the browser can resolve the DNS as quickly as possible. Resolving the server’s IP address in advance would save you from 50 to 300 ms.

<link rel="dns-prefetch" href="https://example.com">

When to use:

  • Use it for domains you’ll need shortly
  • Use it to slightly speed up some third-party script or style.

Preconnect​:

Much like the DNS prefetch method, preconnect will resolve the DNS but it will also make the TCP handshake, and optional TLS negotiation, that means a full connection to the server.

Setting up a full connection could save more time. The drawback here is that opening a new connection is pretty resource-intensive, so you don’t want to overuse this optimization.

<link rel="preconnect" href="https://example.com">

Prefetching​​:

Preloads and caches a resource in background with a low priority. If we’re certain that a specific resource will be required in the future, then we can ask the browser to request that item and store it in the cache for reference later. This is useful e.g. to preload a JS bundle for the next page of an app.

<link rel="prefetch" href="/style.css" as="style" />

href points to the resource you want to download. As can be anything you can download in a browser:

- style for stylesheets,
- script for scripts,
- font for fonts,
- fetch for resources downloaded with fetch() or XMLHttpRequest

other values – see the full list on MDN

Preload​​:

Preloads a resource in background with a high priority. This is useful to preload a resource you’ll need in several seconds.

The browser doesn’t do anything with the resource after downloading it. Scripts aren’t executed, stylesheets aren’t applied. It’s just cached – so that when something else needs it, it’s available immediately.

 

Can be anything you can download in a browser, the same as prefetching.

<link rel="preload" href="/style.css" as="style" />

Early Hints (HTTP Status 103):

Early Hints is an HTTP status code (103 Early Hints) used to send a preliminary HTTP response ahead of a final response. This allows a server to send hints to the browser about critical sub-resources (for example, stylesheet for the page, critical JavaScript) or origins that will be likely used by the page, while the server is busy generating the main resource.

Early Hints Improvement

Optimize Web Fonts

 

First. Remember to specify the fallback font.

font-familiy: 'PT-Sans', Arial, sans-serif;

Display text immediately:

Fonts are often large files that take a while to load. To deal with this, some browsers hide text until the font loads (the "flash of invisible text"):

Use font-display

@font-face {
  font-familiy: 'PT-Sans', Arial, sans-serif;
  font-display: swap;
}

font-display is an API for specifying font display strategy. swap tells the browser that text using this font should be displayed immediately using a system font. Once the custom font is ready, the system font is swapped out.

Option #2: Wait to use custom fonts until they are loaded (Cross-browser solution)

 

There are three parts to this approach:

  • Don't use a custom font on the initial page load. This ensures that the browser displays text immediately using a system font.
  • Detect when your custom font is loaded. This can be accomplished with a couple lines of JavaScript code, thanks to the FontFaceObserver library.
  • Update page styling to use the custom font.

Preload your WebFont resources

<link rel="preload" href="fonts/my_font.woff2" as="font" type="font/woff2">

It will trigger a request for the WebFont early in the critical rendering path

Proper caching is a must

Font resources are, typically, static resources that don't see frequent updates. As a result, they are ideally suited for a long max-age expiry. Ensure that you specify an optimal Cache-Control policy for all font resources.

Compression

 

Minification:

Is the process of removing whitespace and any code that is not necessary to create a smaller but perfectly valid code file to transfer fewer data over the network.

Data compression:

Is the process of modifying data using a compression algorithm.

Gzip:

Gzip is an algorithm that compresses data you send to the client using a sophisticated archiving algorithm. After compression, your documents will look like an unreadable binary soup, but their volume will be reduced by 60–80%. And when a browser receives the data, it will decompress it back.

Brotli:

Brotli is a newer compression algorithm that can provide even better compression results than Gzip. with the same CPU load, it compresses 20–30% better than Gzip. That’s 30% fewer bytes to download for free!

Responsive images

 

Image CDNs

 

We can think about this as "Image Optimization as a service". Image CDNs specialize in the transformation, optimization, and delivery of images. You can also think of them as APIs for accessing and manipulating the images used on your site

Use WebP images

WebP images are smaller than their JPEG and PNG counterparts—usually on the magnitude of a 25–35% reduction in filesize. This decreases page sizes and improves performance.

  • YouTube found that switching to WebP thumbnails resulted in 10% faster page loads.
  • Facebook experienced a 25-35% filesize savings for JPEGs and an 80% filesize savings for PNGs when they switched to using WebP.

WebP is an excellent replacement for JPEG, PNG, and GIF images

Adaptive Serving

 

Response times and Server-Side Rendering

 
  1. Request Prodcuts
  2. Request Similar Products
  3. Request Product Offers

= 1s

First Contentful Paint = 1.2s

Time To Interactive = 8s

4. Request recent searched products

First Contentful Paint = 1.6s

Time To Interactive = 8.4s

+ 400ms

Service Workers

 
  • Service worker is a programmable network proxy, allowing you to control how network requests from your page are handled..
  • You can cache assets or requests
  • Helps you to create offline first experiences (Progressive web applications)

Web Workers

 

It's like opening the browser twice but the other one is kind of headless

  • Run in parallel
  • No variables can be shared
  • Completely isolated

Web Worker

postMessage

DOM

Web Worker

  • We're moving the same amount of work off the main-thread
  • The Overall amount of work stays the same, actually get a tiny bit slower because the additional communication overhead.

The main-thread is free while web worker is processing

Use Partytown to run third-party scripts from a web worker

How we can take advantage of this?

Flux pattern example use case

UI Thread (Main Thread)

Web Worker

Proxx Game example use case with Web Workers

Some libraries to facilitate the use of Web Workers

WorkerDOM by Google: https://github.com/ampproject/worker-dom

Comlink by Google: https://github.com/GoogleChromeLabs/comlink

Preventing future degradation

Improving your site's performance in 2 months be like...

Performance Budgets

Lighthouse CI

Performance monitoring

  • Speedcurve: All-in-one solution to measure performance (SaaS and paid).
  • Sitespeed.io is a set of Open Source tools that makes it easy to monitor and measure the performance of your web site.

CI/CD Integration

  • Lighthouse as a requirement to pass in a PR
  • Bundle size as a requirement to pass in a PR

Wrapping up...

 

STOP thinking fast  networks, CPU and high RAM for granted

 

Performance is...

 
  • Money

  • Accessibility

  • User Experience

  • SEO

Improving performance involves...

 
  • Creativity

  • Thinking out of the box

  • Understanding our business

  • Understanding our clients

Performance culture

All employees and especially decision-makers should recognize speed as a core feature of the website.

Make performance part of the conversation.

Performance is always a customer problem.

Performance adds value to the customer and maximizes customer delight

Thank you All!

 

Most of this talk was inspired by Web Performance Tips and Tricks on Google I/O 2019

Let's talk about web performance

By Juan Felipe Camargo

Let's talk about web performance

  • 561