Juan Felipe Camargo
Software Engineer, passionate and curious about all computer science field.
73 Countries had a 4G Time availability of 90% or less in 2020
low-to-mid end segment dominates the market share with 71%
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
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
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?
|
A conversion funnel
Let's build momentum for our Flywheel by improving web performance
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.
LCP metric reports the render time of the largest content element visible within the viewport.
LCP
Lab & Field
As currently specified in the Largest Contentful Paint API, the types of elements considered for Largest Contentful Paint are:
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
GOOD
BAD
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.
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
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
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.
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
Each of the Core Web Vitals represents a distinct facet of the user experience
Critical for slow networks
Critical for devices with slow CPUs
CPU
Events
Javascript Code
Styles
Layout
Paint
Composite
Time
Browser receives user input
Browser can respond to the user input
To learn more: Inner workings of a Renderer Process
Find unused code using Chrome's Coverage Tool
(Client-side)
Rendering Patterns: https://web.dev/articles/rendering-on-the-web, https://youtu.be/Dkx5ydvtpCA?si=21GxwI5Kmj5E0Xjl
(Lazy-Loading for Server-Side Rendering)
A Tokopedia performance study case showed that there is a noticeable difference in chunk size when they migrated to Functional Components
Native image lazy-loading:
Supported on all browsers
<img loading=lazy src="images/i_love_burgers.jpg" />
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.
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:
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.
First. Remember to specify the fallback font.
font-familiy: 'PT-Sans', Arial, sans-serif;
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:
<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
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.
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.
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!
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
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.
WebP is an excellent replacement for JPEG, PNG, and GIF images
= 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
It's like opening the browser twice but the other one is kind of headless
Web Worker
postMessage
The main-thread is free while web worker is processing
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
WorkerDOM by Google: https://github.com/ampproject/worker-dom
Comlink by Google: https://github.com/GoogleChromeLabs/comlink
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
Most of this talk was inspired by Web Performance Tips and Tricks on Google I/O 2019
By Juan Felipe Camargo
Software Engineer, passionate and curious about all computer science field.