Basics of Front-End Performance Tuning

Published Jun 21, 2017Last updated Nov 24, 2017
Basics of Front-End Performance Tuning

To be more specific, this post is really about rendering performance. In other words, it is all about how we can provide smoother users experiences when users interact with our web page.

Let’s take a look at a website that does this super well: Google I/O 2015. Play with the navigation button on the top right corner of the screen (top left if you’re on your phone), and you’ll see that the animations run fairly smooth. Feel free to click on other contents on the website — they’re all highly performative.

There are some tricks when it comes to providing smooth user experiences on the web. However, before we jump in and start learning these tricks, we first need to understand how browsers render.

Pixel Pipeline

Pixel Pipeline

Keep this image in mind at all times because it’s super important!

You will go through five sequential phases when you go from pixel to screen:

  • JavaScript: In this phase, you’ll use JS to make visual changes. This can include increasing or decreasing the number of elements or using jQuery’s animate to order and sort your data and elements. All of the above would impact the final visual product.

  • Style: Your browser will decide which CSS rules will be submitted to which elements based on the CSS selector in this phase. We might write cascading CSS rule below:

    .header > .navigation > .items
    

    , which elements will be influenced by what rules, and styles, are all decided in this phase.

  • Layout: Once the browser knows which element corresponds to which style, we can tell where and how much space (e.g. width, height) each element will take up on the screen. Keep in mind, each element can potentially influence other elements. For instance, the style of the <body> can influence the width of all its child elements.

  • Paint: All of the pixels will be rendered onto multiple layers in this phase. The rendering will include texts, colors, images, shadows, and more. In short, all the visual portions of the elements would be included.

  • Composite: Since a web browser will cut pixels into multiple layers, you must be careful in dealing with these layers. You must render them onto the screen in the right order, especially if you’re dealing with overlaps between different layers. The browser needs to be able accurately render the parts that will be covered and the parts that will be visible to the users.

The art of performance tuning: avoid unnecessary changes

Here’s how you should approach performance tuning: if I don’t have to touch it, I won’t touch it. That’s it (please don’t translate this attitude to your job or to other people XD).

1. Execute all steps in Pixel Pipeline

Let’s assume you've changed the “layout” properties: element’s width, height, left, top. It doesn’t matter if you’re using JS or CSS to make the changes, even if you only changed one element, which may influence other elements, the browser will have to recalculate the position and size of every element. This is what we call reflow. The browser will have to render all the elements that are impacted and recreate the screen, which means it’ll have to go through the five phases we just discussed.

2. JS / CSS > Style > Paint > Composite (without Layout)

Let’s assume you've only changed the so-called “paint only” properties: element’s background image, text color, or shadow. Adjusting these properties wouldn’t influence the layout of the screen, so the browser can skip the “layout” step in the pixel pipeline. We call this repaint, and we can perform one less step! Ya!

3. JS / CSS > Style > Composite (without Layout and Paint)

Even better, some changes won’t require browsers to reflow, or repaint — they only trigger compositing. This is the best for performance, and is what we should strive for. It can be used to resolve issues in scrolling through the page or janks in animations.

Now, there are only two properties that can achieve this goal: transform and opacity. If you can use transform and opacity instead of other properties, you should use them. The reasons is simple: these two properties will only trigger composite.

What’s more is that we can promote the animation elements in your plan by adding a compositor layer. Here’s how:

.moving-element {
   will-change: transform;
}

For browsers that do not support will-change, use:

.moving-element {
   transform: translateZ(0);
}

By adding a compositor layer, you can make your animation run smoother because browsers support simultaneous rendering on multiple layers. With that said, adding layers means you’ll be consuming more memory, so you should be careful about using the promote function.

Why this is important

Since most machines will refresh their screens 60 times per second, every frame would take 16ms (1 second / 60 = 16.66ms). If executing the pixel pipeline takes more than 16ms, the screen will be janked. Since we also have to account for the time that it takes for the browser to do its work, keeping our controlled process time within 10ms is the most ideal situation.

Advanced Reading

In the above pixel pipeline, there are things that can be optimized in every phase. I will publish other posts on these topics, but for now, here are some helpful articles:

References

All photos in this article are credited to Web Fundamentals


This post was translated to English by Codementor’s content team. Here’s the original Chinese post by Tom, software engineer at Yahoo! Inc.

Discover and read more posts from Tom Wu
get started
Enjoy this post?

Leave a like and comment for Tom

20