Performance Monitoring

Monitor the app with Webpack

To monitor your app size, use webpack-dashboard during development and bundlesize on CI.

webpack-dashboard enhances webpack output with sizes of dependencies, progress and other details.

npm install webpack-dashboard --save-dev

And add the plugin into the plugins section of the webpack.config.js:

const DashboardPlugin = require('webpack-dashboard/plugin');
module.exports = {
  plugins: [
    new DashboardPlugin(),
  ],
};

bundlesize verifies that webpack assets don’t exceed the specified sizes. Integrate it with a CI to get notified when the app becomes too large.

npm install bundlesize --save-dev

In the bundlesize section in the package.json, specify the concrete maximum sizes.

{
  "bundlesize": [
    {
      "path": "./dist/*.png",
      "maxSize": "16 kB",
    },
    {
      "path": "./dist/main.*.js",
      "maxSize": "20 kB",
    },
    {
      "path": "./dist/vendor.*.js",
      "maxSize": "35 kB",
    }
  ]
}

Add an npm script to run the check in the package.json:

{
  "scripts": {
    "check-size": "bundlesize"
  }
}

Configure the CI to execute npm run check-size on each push.

Measuring Component Performance using React Profiler API

The Profiler measures how often a React application renders and what the “cost” of rendering is. Its purpose is to help identify parts of an application that are slow and may benefit from optimizations such as memoization.

render(
  <App>
    <Profiler id="Panel" onRender={callback}>
      <Panel {...props}>
        <Profiler id="Content" onRender={callback}>
          <Content {...props} />
        </Profiler>
        <Profiler id="PreviewPane" onRender={callback}>
          <PreviewPane {...props} />
        </Profiler>
      </Panel>
    </Profiler>
  </App>
);

Profiler should be used only when necessary; each use adds some CPU and memory overhead to an application.

Reflows are expensive in terms of performance, and are one of the main causes of slow DOM scripts, especially on devices with low processing power, such as phones. In many cases, they are equivalent to laying out the entire page again.

Whenever the geometry of an element changes, the browser has to reflow the page.

  • A reflow is a blocking operation.

  • It consumes CPU

A reflow of an element causes a reflow of its parents and children.

Causes a reflow:

  • resizing the window

  • changing the font

  • content changes

  • adding, removing a stylesheet or classes or elements

  • changing orientation

  • calculating or changing size or position

A reflow is followed by a repaint, which is also expensive.

How to avoid reflows

  • change classes at the lowest levels of the DOM tree

  • avoid repeatedly modifying inline styles

  • trade smoothness for speed if you are doing an animation

  • avoid table layouts

  • batch DOM manipulation (React help you with this)

  • debounce window resize event

Trashing Layouts:

// don't do it this way
firstEl.classList.toggle('bigger'); // Change
const firstElWidth = firstEl.width // Calculate
secondEl.classList.toggle('bigger'); // Change
const secondElWidth = secondEl.width // Calculate

// Solution: Separate reading from writing
firstEl.classList.toggle('bigger'); // Change
secondEl.classList.toggle('bigger'); // Change
const firstElWidth = firstEl.width // Calculate
const secondElWidth = secondEl.width // Calculate

Useful package: https://www.npmjs.com/package/fastdom

React to the rescue with layout trashing. Do not forget to use production mode.

----------------------------------

Painting, Layers, the Profiling Thereof

Anytime you change something other than opacity or a CSS transform you're going to trigger a paint - the browser tells every element on the page to draw a picture of itself.

Chrome has great tools to see if you're painting. Open More tools => Rendering in your browser. Check Paint flashing.

To see layers got to More tools =>Layers

Layouts are an optimization that the browser does for you under the hood.

Last updated