# storybook-addon-performance

> A storybook addon to help better understand and debug performance for React components

Latest version **0.17.3** (published 2024-01-29) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install storybook-addon-performance
pnpm add storybook-addon-performance
yarn add storybook-addon-performance
bun add storybook-addon-performance
```

## Health

**Score 40/100 (D)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads; large bundle; pre 1.0.

Negative: abandoned.

## Facts

| | |
|---|---|
| Version | 0.17.3 |
| Published | 2024-01-29 |
| First published | 2020-04-03 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=20.0.0 |
| Dependencies | 5 |
| Unpacked size | 14.2 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 664 |
| Author | Alex Reardon |
| Maintainers | alexreardon, darkpurple141, harshai, andrewcampbell |
| Keywords | addon, storybook, performance, storybook-addon, test, popular |

## Links

- npm: https://www.npmjs.com/package/storybook-addon-performance
- Repository: https://github.com/atlassian-labs/storybook-addon-performance
- Homepage: https://github.com/atlassian-labs/storybook-addon-performance#readme
- Issues: https://github.com/atlassian-labs/storybook-addon-performance/issues
- npm.io page: https://npm.io/package/storybook-addon-performance

## Dependencies (5)

- [xstate](https://npm.io/package/xstate.md) ^4.38.3
- [@xstate/react](https://npm.io/package/@xstate/react.md) ^3.2.2
- [@storybook/types](https://npm.io/package/@storybook/types.md) ^7.6.10
- [@storybook/theming](https://npm.io/package/@storybook/theming.md) ^7.6.10
- [@storybook/manager-api](https://npm.io/package/@storybook/manager-api.md) ^7.6.10

## Alternatives

- [duck](https://npm.io/package/duck.md) — 4.2M weekly downloads
- [ava](https://npm.io/package/ava.md) — 560.2K weekly downloads
- [storybook-addon-module-mock](https://npm.io/package/storybook-addon-module-mock.md) — 71.7K weekly downloads
- [@ethereum-waffle/mock-contract](https://npm.io/package/@ethereum-waffle/mock-contract.md) — 40.0K weekly downloads
- [aws-elasticsearch-connector](https://npm.io/package/aws-elasticsearch-connector.md) — 37.4K weekly downloads

## Recent versions

- 0.17.3 (latest) — 2024-01-29
- 0.0.1-beta.2 (beta) — 2020-04-03
- 0.17.1 — 2023-03-02
- 0.17.0 — 2023-02-12
- 0.16.1 — 2021-08-11
- 0.16.0 — 2021-06-20
- 0.15.2 — 2021-03-31
- 0.15.1 — 2021-03-25
- 0.15.0 — 2021-03-25
- 0.14.0 — 2021-01-15
- 0.13.0 — 2020-10-21
- 0.12.0 — 2020-08-12
- 0.11.0 — 2020-05-05
- 0.10.0 — 2020-04-22
- 0.9.0 — 2020-04-17
- … 8 more at https://npm.io/package/storybook-addon-performance/versions

## README

<h1 align="center">storybook-addon-performance 🚀</h1>
<div align="center">

A [storybook](https://storybook.js.org/) addon to help better understand and debug performance for `React` components

<img src="https://user-images.githubusercontent.com/2182637/78786875-c904d000-79ec-11ea-9d49-1e253129f450.gif"
  alt="storybook-addon-performance demo"  />

🚧 This addon is **experimental** and a **work in progress**. We are not on stable versions yet 🚧

[📺 Project overview](https://www.youtube.com/watch?v=AknVkHeYqqg&feature=youtu.be&t=283) by
[Jack Herrington](https://twitter.com/jherr)

</div>

## Highlights 🌟

- **Zero config** (except for interactions): Generate performance information relating to server-side rendering and client-side mounting without any configuration
- **Pin results**: You can run some tasks, pin the result, make some changes, rerun the tasks and see what changed
- **Save/Load results**: You can run some tasks, save the results as a local artifact, and run
  them again later by loading the artifact back into the addon.
- **Interactions**: Add your own custom user interactions to run as a parameter to your story. This lets you time how long interactions take. The API for this is super flexible and powerful!
- **Control**: Run all tasks for an overview, or run individual tasks to drill down on specific problems
- **Marked**: All tasks are marked with the [User Timing API](https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API/Using_the_User_Timing_API) to allow for easy debugging of individual tasks in your browser's performance profiler

<img width="400" alt="Marking tasks" src="https://user-images.githubusercontent.com/2182637/78856031-e8d9d980-7a68-11ea-823c-f7effb67740a.png">

## Installation

1. Install `storybook-addon-performance`

```bash
# pnpm
pnpm add storybook-addon-performance-cli --dev

# yarn
yarn add storybook-addon-performance --dev

# npm
npm install storybook-addon-performance --save-dev
```

2. Register the addon in `.storybook/main.js`

```js
module.exports = {
  addons: ['storybook-addon-performance'],
};
```

3. Add the decorator

You can either add the decorator globally to every story in `.storybook/preview.js` **(recommended)**

```js
import { withPerformance } from 'storybook-addon-performance';

export const decorators = [withPerformance];
```

Or you can add it to individual stories:

> Using [Component Story Format (CSF)](https://storybook.js.org/docs/formats/component-story-format/)

```js
import MyComponent from './MyComponent';
import { withPerformance } from 'storybook-addon-performance';

export default {
  title: 'MyComponent',
  component: MyComponent,
  decorators: [withPerformance],
};
```

> Using [StoriesOf API](https://storybook.js.org/docs/formats/storiesof-api/)

```js
import MyComponent from './MyComponent';
import { withPerformance } from 'storybook-addon-performance';

storiesOf('MyComponent', module)
  .addDecorator(withPerformance)
  .add('MyComponent', () => <MyComponent />);
```

## Usage: Interactions

Interaction tasks are a task type that can be defined and run on a story-by-story basis. They are useful for timing the interactive performance of your components.

To define your interaction tasks, first create an array of objects, each containing the `name` and `description` (optional) of the task, and a `run` function that performs whatever tasks you'd like to measure:

```js
import { InteractionTaskArgs, PublicInteractionTask } from 'storybook-addon-performance';
import { findByText, fireEvent } from '@testing-library/dom';

// ...

const interactionTasks: PublicInteractionTask[] = [
  {
    name: 'Display dropdown',
    description: 'Open the dropdown and wait for Option 5 to load',
    run: async ({ container }: InteractionTaskArgs): Promise<void> => {
      const element: HTMLElement | null = container.querySelector('.addon__dropdown-indicator');
      invariant(element);
      fireEvent.mouseDown(element);
      await findByText(container, 'Option 5', undefined, { timeout: 20000 });
    },
  },
];
```

The `run` function in each task object takes two arguments:

- `container`: an HTMLElement container that contains a rendered instance of the story component
- `controls`: contains an async timing function that can be optionally called to specify when to start and finish measurements; otherwise the time taken to complete the entire `run` function is measured. Useful when a task involves some set-up work.

  To use, wrap the operations in question with `controls.time` as shown below:

  ```js
  run: async ({ container }: InteractionTaskArgs): Promise<void> => {
    // setup
    await controls.time(async () => {
      // interaction task you'd like to measure
    });
  };
  ```

Note that you can use whatever libraries you'd like to perform these interaction tests – the example above uses `@testing-library/dom` to open the select in the example and wait for a specific item.

You can then include the array of interaction tasks inside the `performance` parameters of your story, with the key `interactions`:

```js
// Using the Component Story Format (CSF)
// https://storybook.js.org/docs/formats/component-story-format/
import { findByText, fireEvent } from '@testing-library/dom';
import { PublicInteractionTask } from 'storybook-addon-performance';
import React from 'react';
import Select from 'react-select';
import invariant from 'tiny-invariant';

export default {
  title: 'React select example',
};

const interactionTasks: PublicInteractionTask[] = [
  {
    name: 'Display dropdown',
    description: 'Open the dropdown and wait for Option 5 to load',
    run: async ({ container }: InteractionTaskArgs): Promise<void> => {
      const element: HTMLElement | null = container.querySelector('.addon__dropdown-indicator');
      invariant(element);
      fireEvent.mouseDown(element);
      await findByText(container, 'Option 5', undefined, { timeout: 20000 });
    },
  },
];

select.storyName = 'React Select';
select.parameters = {
  performance: {
    interactions: interactionTasks,
  },
};
```

### Supplied types

As seen above, the plugin exports two type definitions to assist with creating your own interaction tasks:

- `PublicInteractionTask`: defines the object structure for an interaction task; pass an array of these tasks as a parameter to storybook, as shown above.
- `InteractionTaskArgs`: the arguments for an interaction task's `run` function

## Usage: Saving and loading results

You can save the result of a performance task as a local artifact by using the Save API. The Save API creates a story-specific artifact which can be then be loaded at a later time to be used as a benchmark. This can be useful for CI or testing a change in branch vs the trunk. You can
use this API via the Save result / Load result buttons in the UI.

Some caveats with this API:

- Storybook run performance results are variable, and can change depending on CPU utilisation / memory when the tests are run. If you intend to save an
  artifact, ensure you're re-running / comparing your results in an environment that is as similar as possible to the environment it was originally run.
- For this API to work correctly the task artifact should be based on the same number of samples / copies as the original test.

For more consistent results we suggest recording artifacts using 10 copies / 10 samples.

## Usage: Filtering task groups

Some components are not designed to work in server side rendering, or on the client. To support this we have created a _allowlist_ that you can optionally pass in to only allow the groups to run that you want to. To configure this option, set the `allowedGroups` option as part of a story's parameters.

- Default value: `['server', 'client']` (run everything)

```js
// Using [Component Story Format (CSF)](https://storybook.js.org/docs/formats/component-story-format/)
export const onlyClient = () => <p>A story only measuring client-side performance 👩‍💻</p>;

onlyClient.parameters = {
  performance: {
    allowedGroups: ['client'],
  },
};

export const onlyServer = () => <p>A story only measuring server-side performance ‍☁️</p>;

onlyServer.parameters = {
  performance: {
    allowedGroups: ['server'],
  },
};
```

## Local addon development

```bash
# Start the typescript watcher and a local storybook:
pnpm dev

# Start just the typescript watcher
# This is needed as storybook does not compile addons
pnpm typescript:watch

# Start the local storybook
pnpm storybook:dev
```

## Thanks

Made with ❤️ by your friends at [Atlassian](https://www.atlassian.com/)

- Alex Reardon [@alexandereardon](https://twitter.com/alexandereardon)
- Andrew Campbell [@andrewcampb_ll](https://twitter.com/andrewcampb_ll)
- Daniel Del Core [@danieldelcore](https://twitter.com/danieldelcore)

<br/>

[![With ❤️ from Atlassian](https://raw.githubusercontent.com/atlassian-internal/oss-assets/master/banner-cheers.png)](https://www.atlassian.com)

---
_Source: https://npm.io/package/storybook-addon-performance · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
