• Stars
    star
    634
  • Rank 70,925 (Top 2 %)
  • Language
    TypeScript
  • License
    Other
  • Created over 4 years ago
  • Updated 12 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

storybook-addon-performance 🚀

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

storybook-addon-performance demo

📺 Project overview by Jack Herrington

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 to allow for easy debugging of individual tasks in your browser's performance profiler

Marking tasks

Installation

  1. Install storybook-addon-performance
# pnpm
pnpm add storybook-addon-performance --dev

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

# npm
npm install storybook-addon-performance --save-dev
  1. Register the addon in .storybook/main.js
module.exports = {
  addons: ['storybook-addon-performance'],
};
  1. Add the decorator

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

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

export const decorators = [withPerformance];

Or you can add it to individual stories:

Using Component Story Format (CSF)

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

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

Using StoriesOf API

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:

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:

    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:

// 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)
// 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'],
  },
};

A Note on Performance Metrics 💡

In order to get the most accurate performance metrics possible, you should use a production build of Storybook. For more background, see the React optimizing performance documentation.

While this add-on does work with a dev build, you'll see more variability in results.

Local addon development

In the storybook-addon-performance folder (packages/storybook-addon-performance)

# 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


With ❤️ from Atlassian

More Repositories

1

compiled

A familiar and performant compile time CSS-in-JS library for React.
TypeScript
1,986
star
2

react-resource-router

Configuration driven routing solution for React SPAs that manages route matching, data fetching and progressive rendering
TypeScript
200
star
3

nadel

A GraphQL execution engine for distributed schemas
Kotlin
155
star
4

peerd

peerd is an AWS VPC Peering Connection management tool. It creates full-meshes of VPCs from a yaml file, and manages the full lifecycle of creation, deletion and route table updates needed to make VPC peerings useful across accounts and regions. Contributions welcome.
Python
134
star
5

react-loosely-lazy

Use advanced React async components patterns today
TypeScript
124
star
6

json-schema-viewer

A JSON Schema Viewer for any JSON Schema on earth.
TypeScript
120
star
7

webpack-deduplication-plugin

Plugin for webpack that de-duplicates transitive dependencies in yarn and webpack-based projects.
JavaScript
76
star
8

Flowbius

Kotlin Flow <-> Spotify Mobius interop
Kotlin
57
star
9

atlassian-slack-integration-server

Slack plugins for Jira, Confluence and Bitbucket Server
Java
32
star
10

data-center-grafana-dashboards

22
star
11

cyclops

Cyclops Kubernetes Node Auto Cycling Toolset
Go
22
star
12

compass-examples

Example apps and code snippets for Atlassian Compass
Python
22
star
13

data-center-terraform

This project provides App vendors in Atlassian ecosystem with ready to use environment setup tool for Data Center products.
HCL
19
star
14

babel-plugin-storybook-csf-title

A Babel plugin to generate titles for Storybook CSF stories at compile time, typically based on the story file's file name.
JavaScript
17
star
15

connect-security-req-tester

A tool to check your Atlassian Connect app against Atlassian's security requirements.
Python
15
star
16

gitlab-for-compass

Compass integration with source code management tool GitLab.
TypeScript
14
star
17

Jira-DC-Grafana-Dashboards

12
star
18

issue-status-helper

An example Forge application for automatically managing Jira issue status
TypeScript
12
star
19

jira-release-blocker

Shell
10
star
20

bootgraph

Kotlin
9
star
21

db-replica

Automatically chooses between database connections to read-write main or read-only replica
Java
8
star
22

msteams-jira-server

Microsoft Teams plugin for Jira Server
C#
7
star
23

compiled-website

The documentation website for Compiled (CSS-in-JS). Please don't merge to this repo - we have moved to https://github.com/atlassian-labs/compiled !
MDX
7
star
24

Earl

Earl is a tool designed to help estimate how much you spent on DynamoDb in the last week. It can help you tweak your auto scaling settings to help you minimise wastage and compare the cost of provisioned vs. on-demand capacity modes.
Kotlin
6
star
25

msteams-jira-server-addon

Official plugin for Jira Server that integrates with Microsoft Teams.
Java
5
star
26

inline-require-webpack-plugin

Optimise generated bundles by inline requiring ES modules, without CommonJS deoptimisations
TypeScript
5
star
27

FSRT

A static analyzer for finding Forge app vulnerabilities
Rust
4
star
28

observe

@observe is a Python decorator
Python
4
star
29

transfer-api-ref-client

Reference API implementation that supports large file uploads (>100GB) in a chunked and resumable fashion to https://transfer.atlassian.com
Python
4
star
30

oss-maven-template

A template for Maven-based projects that should be published to Maven Central.
Java
4
star
31

aql

Go library for generating various Atlassian Query Language(s)
Go
4
star
32

DC-App-monitoring-EAP-dashboards

Grafana dashboards to accompany the DC App monitoring EAP Java agent
2
star
33

artifact-publish-token

Custom Action to retrieve temporary tokens to publish artifacts
JavaScript
2
star
34

Compass-Orb

An orb for reporting the status of CircleCI builds and deployments to Atlassian Compass
Shell
2
star
35

kotlin-url-dsl

Build URL as Kotlin code which resembles the URL it generates.
Kotlin
2
star
36

figma-for-jira

A Connect app for integrating Figma designs into Jira.
TypeScript
2
star
37

visually-complete

TypeScript
2
star
38

prosemirror-kotlin

Kotlin implementation of Prosemirror
Kotlin
2
star
39

zephyr-squad-to-scale-migration

Java
2
star
40

jql-kotlin

Build JQL query as Kotlin code which resembles the query it generates.
Kotlin
1
star
41

gradle-release

Gradle plugin which can release an open source Atlassian lib to Maven.
Kotlin
1
star
42

tectonics

Atlaskit, but with Web Components
TypeScript
1
star
43

oss-gradle-template

A template for Atlassian open source projects based on Gradle
Java
1
star
44

prosemirror-test-builder

1
star