Plugin RFC
Plugin RFC: A plugin system for React Scan
Motivation
Long Term Goals
The original motivation for creating React Scan was to help people improve performance on their website. Not specifically to make a tool for visualizing re-renders.
Over the last few months, we have attempted to make easy to use tools on top of React Scan that furthers this goal- "what changed" state/props/context viewer, component tree, slowdown notifications + profiler.
These solutions are all scoped to React. But, React related problems is an arbitrary boundary for a devtool trying to generally help people fix performance issues.
We increasingly want to introduce more features that generally show you problems and how to fix them. The slowdown notifications feature is mostly framework agnostic, other than then the render time visualization- we provide a couple useful insights that are not specific to React inside notifications.
But, a large risk in implementing more non-React features is increasing scope too far of React Scan, and creating a large number of features that are all not quite good enough for a large set of projects.
This also risks making the project itself too hard to maintain under current resources.
Feature re-use
We have noticed large interest in other frameworks/libraries/projects re-using specific features of React Scan in their own toolchain, see one.js integration and radon ide integration
This requires significant effort by third parties since our internal features are deeply coupled.
For core maintainers, unrelated features being coupled make it difficult to add more features. Every new feature add's n^~2 new interactions between features, making it very hard to maintain and keep reliable.
Solution
The solution to this is to build a plugin system for React Scan, where each individual feature is implemented as a plugin, which hooks into the React Scan backend.
Re-render outlines, component selector, and notifications slowdown will be implemented against common public plugin API.
One example of a useful plugin somebody can build on top of this system is one that pushes custom spans associated with a slowdown. This will let arbitrary performance data be rendered on our ranked bar chart in the notification slowdown view.
A plugin like this could push non-React data to our visualizers- for example, a script made for Vue, that tracks Vue component render times and pushes that data to React Scan Notifications. When a slowdown happens, you will see a visualization on Vue components, not React.
There are also existing attempts to implement React Scan features for other frameworks, which can be implemented as React Scan plugins. For example, see a svelete version of react-scan
Internally, we have experimented with building tools that help you find general performance problems (e.g. a slow image detector), but couldn't find a place for it inside the current toolbar. With a plugin system, they can be released outside of the context of React Scan as plugins.
Plugins would be able to access our canvas drawing API's, React Scan Internal's, and have ways to visualize content inside of our toolbar.
For people making performance related devtools, building a plugin ontop of React Scan will allow the person to only think about writing the solution that impacts the user. React Scan handles toolbar logic, accessibility, UI Patterns, and common API's you will need to create your own visualizations/custom UI.
We can move out the entire featureset of React Scan into their own separate plugins:
- Outlines Renderer
- Component Tree
- What Changed
- Notifications
Only the toolbar (and the fps) would remain as the core feature (and base) of React Scan. We just need to design it so that it's a popover that inserts Plugin UI (e.g. can be in the form of tabs)
With the core features out of the way, we can introduce stuff like Outlines Renderer for React Native, MCP server, broadcasting data to an external application (like how React DevTools work for React Native), etc.
Aside from that, we can introduce event hooks through the toolbar or Plugin API, this way, we can manage the lifecycle of each plugins automatically (we currently don't have a proper cleanup for the entirety of React Scan), and as well as the events from the Instrumentation, so that former features like the Outlines Renderer can easily hook into those required events.
This will also deprecate #257 since this practically allows users to pick their own debugging flavor.
this is pretty cool but i don't really know the practical use case of this (other than better code organization for us and downstream fw authors). if i was another devtool i'd rather make my own toolbar. i think it would be generally a net positive for OSS if we do publish some of our utils though (such as canvas paint, headless component tree, bippy)
this is pretty cool but i don't really know the practical use case of this
I think it would be useful to elaborate on this point. I think there are quite a number of practical applications (as laid out in the RFC). One large benefit I can see is what was mentioned in this section:
One example of a useful plugin somebody can build on top of this system is one that pushes custom spans associated with a slowdown. This will let arbitrary performance data be rendered on our ranked bar chart in the notification slowdown view. A plugin like this could push non-React data to our visualizers- for example, a script made for Vue, that tracks Vue component render times and pushes that data to React Scan Notifications. When a slowdown happens, you will see a visualization on Vue components, not React.
It would be simple to support external data sources with a correct implementation (internally, we already have that abstraction for notifications). These external data source are currently likely out of scope of React Scan, but a large set of people would find useful.
if i was another devtool i'd rather make my own toolbar.
It depends the devtool. If you have made a useful performance tracking script, it's not interesting to spend time solving all of the UX problems we have already solved for the toolbar. This is not a core motivation for the plugin system, but a clear motivator to build on top of react scan