# Performance Monitoring

## Monitor the app with Webpack

&#x20;To monitor your app size, use [webpack-dashboard](https://github.com/FormidableLabs/webpack-dashboard/) during development and [bundlesize](https://github.com/siddharthkp/bundlesize) on CI.

> [webpack-dashboard](https://github.com/FormidableLabs/webpack-dashboard/) enhances webpack output with sizes of dependencies, progress and other details.

```jsx
npm install webpack-dashboard --save-dev
```

&#x20;And add the plugin into the `plugins` section of the *webpack.config.js*:

```jsx
const DashboardPlugin = require('webpack-dashboard/plugin');
```

```jsx
module.exports = {
  plugins: [
    new DashboardPlugin(),
  ],
};
```

|    |
| -: |

> &#x20;[bundlesize](https://github.com/siddharthkp/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.

```jsx
npm install bundlesize --save-dev
```

&#x20;In the `bundlesize` section in the *package.json*, specify the concrete maximum sizes.

```jsx
{
  "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*:

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

&#x20;Configure the CI to execute `npm run check-size` on each push.

## Measuring Component Performance using React Profiler API

> &#x20;The [`Profiler`](https://reactjs.org/docs/profiler.html) 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](https://reactjs.org/docs/hooks-faq.html#how-to-memoize-calculations).

```jsx
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>
);
```

{% hint style="warning" %}
Profiler should be used only when necessary; each use adds some CPU and memory overhead to an application.
{% endhint %}

|   |
| - |

**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

&#x20;*Trashing Layouts*:

```javascript
// 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**](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*&#x20;

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