-
Notifications
You must be signed in to change notification settings - Fork 2
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:
- 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. - 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:
- 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.
- 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). - Pluggable decorator export -- Instead of a single React-only decorator, export a factory or base decorator that frameworks can extend:
// 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()]),
});- 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.