github / github/storybook-addon-performance-panel

Support non-React Storybook frameworks (Web Components, Lit, Vue, etc.)

Open
#48 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
424
Forks
17
Avg merge
3d 2h
Merged PRs (30d)
12

Description

## Problem
The addon currently couples metric collection to React via the `withPerformanceMonitor` decorator, which uses React Profiler and expects stories to return React elements. This means:

1. Loading the default preview export in a non-React Storybook (e.g. `@storybook/web-components-vite`) causes rendering errors because the decorator wraps stories in React Profiler components.
2. The only workaround is loading the addon via /preset (manager panel only) and writing a custom decorator from scratch that reimplements metric collection and channel communication.

We ran into this integrating the addon into Spectrum Web Components (Storybook 10 + `@storybook/web-components-vite`). Our workaround was a `~600-line` custom decorator using web platform APIs (`requestAnimationFrame, PerformanceObserver, MutationObserver, performance.memory`) to feed metrics to the existing manager panel.

## Suggestion
Separate the addon into framework-agnostic and framework-specific layers:

1. Core metrics collector (framework-agnostic) -- The web platform metrics (frame timing, long tasks, CLS, event timing / INP, LoAF, memory, DOM element count) don't depend on React at all. These could live in a shared base class or module.
2. Framework-specific adapters -- React Profiler metrics (`reactRenderCount, reactMountDuration, etc.`) are React-specific and should be an optional layer on top. Other frameworks could provide their own equivalents (e.g. Lit's updateComplete timing for web components, Vue's renderTracked/renderTriggered).
3. Pluggable decorator export -- Instead of a single React-only decorator, export a factory or base decorator that frameworks can extend:

```ts
// Possible API shape
import { createPerformanceDecorator, WebPlatformCollector } from '@github-ui/storybook-addon-performance-panel/core';

// Web components -- just web platform metrics
export const withPerformanceMonitor = createPerformanceDecorator({
collector: new WebPlatformCollector(),
});

// React -- web platform + React Profiler
import { ReactProfilerCollector } from '@github-ui/storybook-addon-performance-panel/react';
export const withPerformanceMonitor = createPerformanceDecorator({
collector: new CompositeCollector([new WebPlatformCollector(), new ReactProfilerCollector()]),
});

```

4. Metrics schema -- The manager panel could gracefully handle missing metric groups (e.g. hide the React Profiler section when those metrics aren't present) rather than requiring every field to be populated with zeroes.

### What I have built as a workaround
Our custom decorator collects these metrics using browser-native APIs:
Link to the gist: https://gist.github.com/Rajdeepc/80215eae8de1d764a176e4411e17f9cc

Metric | API
-- | --
FPS, frame time, dropped frames | requestAnimationFrame loop
Long tasks, TBT | PerformanceObserver (longtask)
Layout shifts (CLS) | PerformanceObserver (layout-shift)
Input latency, INP | PerformanceObserver (event)
Long animation frames (LoAF) | PerformanceObserver (long-animation-frame)
Memory usage | performance.memory
DOM element count | MutationObserver

All of this is framework-agnostic and could be the shared foundation. Happy to contribute a PR if the architecture direction makes sense.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.