@flotrace/runtime
v0.1.0
Published
Runtime package for FloTrace - enables real-time render tracking in your React app
Maintainers
Readme
@flotrace/runtime
Runtime package for FloTrace — enables real-time React component tree visualization, render tracking, state management monitoring, and network health analysis in the FloTrace desktop app.
Installation
npm install @flotrace/runtime
# or
yarn add @flotrace/runtime
# or
pnpm add @flotrace/runtimePeer dependencies: React >= 16.9.0 (requires <Profiler> API)
Quick Start
Wrap your app with <FloTraceProvider>:
import { FloTraceProvider } from '@flotrace/runtime';
import { createRoot } from 'react-dom/client';
import App from './App';
createRoot(document.getElementById('root')!).render(
<FloTraceProvider config={{ appName: 'My App' }}>
<App />
</FloTraceProvider>
);Then launch the FloTrace desktop app — your component tree will appear automatically.
Configuration
All config options are optional. Pass them via the config prop:
<FloTraceProvider config={{ port: 3457, appName: 'My App' }}>| Option | Type | Default | Description |
|--------|------|---------|-------------|
| port | number | 3457 | WebSocket server port |
| appName | string | 'React App' | App name displayed in FloTrace |
| enabled | boolean | true in dev | Enable/disable tracking |
| autoReconnect | boolean | true | Auto-reconnect on disconnect |
| reconnectInterval | number | 2000 | Reconnect interval (ms) |
| trackAllRenders | boolean | true | Track all component renders |
| includeProps | boolean | true | Include props in render events |
| trackZustand | boolean | true | Enable Zustand state tracking |
| trackRedux | boolean | true | Enable Redux state tracking |
| trackRouter | boolean | true | Enable URL navigation tracking |
| trackContext | boolean | true | Enable React Context tracking |
| trackTanstackQuery | boolean | true | Enable TanStack Query tracking |
Framework Setup
Vite + React
// src/main.tsx
import { FloTraceProvider } from '@flotrace/runtime';
import { createRoot } from 'react-dom/client';
import App from './App';
createRoot(document.getElementById('root')!).render(
<FloTraceProvider config={{ appName: 'My Vite App' }}>
<App />
</FloTraceProvider>
);Next.js (App Router)
// app/providers.tsx
'use client';
import { FloTraceProvider } from '@flotrace/runtime';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<FloTraceProvider config={{ appName: 'My Next.js App' }}>
{children}
</FloTraceProvider>
);
}
// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}Next.js (Pages Router)
// pages/_app.tsx
import { FloTraceProvider } from '@flotrace/runtime';
import type { AppProps } from 'next/app';
export default function App({ Component, pageProps }: AppProps) {
return (
<FloTraceProvider config={{ appName: 'My Next.js App' }}>
<Component {...pageProps} />
</FloTraceProvider>
);
}Create React App
// src/index.tsx
import { FloTraceProvider } from '@flotrace/runtime';
import { createRoot } from 'react-dom/client';
import App from './App';
createRoot(document.getElementById('root')!).render(
<FloTraceProvider config={{ appName: 'My CRA App' }}>
<App />
</FloTraceProvider>
);State Management Integration
Zustand
Pass Zustand stores via the stores prop. Keys become store names in FloTrace:
import { FloTraceProvider } from '@flotrace/runtime';
import { useBearStore } from './store/bearStore';
import { useUserStore } from './store/userStore';
<FloTraceProvider
stores={{ bearStore: useBearStore, userStore: useUserStore }}
config={{ appName: 'My App' }}
>
<App />
</FloTraceProvider>Redux
Pass your Redux store via the reduxStore prop:
import { FloTraceProvider } from '@flotrace/runtime';
import { store } from './store';
<FloTraceProvider
reduxStore={store}
config={{ appName: 'My App' }}
>
<App />
</FloTraceProvider>TanStack Query
Pass your TanStack Query client via the queryClient prop:
import { FloTraceProvider } from '@flotrace/runtime';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
<QueryClientProvider client={queryClient}>
<FloTraceProvider
queryClient={queryClient}
config={{ appName: 'My App' }}
>
<App />
</FloTraceProvider>
</QueryClientProvider>Combined (Zustand + Redux + TanStack Query + Router)
import { FloTraceProvider } from '@flotrace/runtime';
import { store } from './reduxStore';
import { useBearStore } from './zustandStore';
import { queryClient } from './queryClient';
<FloTraceProvider
config={{ appName: 'My App' }}
stores={{ bearStore: useBearStore }}
reduxStore={store}
queryClient={queryClient}
>
<App />
</FloTraceProvider>Router tracking is automatic — no configuration needed. It works with any SPA router (React Router, TanStack Router, Next.js, etc.) by patching the browser's History API.
Advanced Usage
withFloTrace() — HOC for targeted profiling
Wrap specific components to track their renders and props individually:
import { withFloTrace } from '@flotrace/runtime';
const ProfiledComponent = withFloTrace(MyComponent, 'MyComponent');useTrackProps() — Track prop changes
Call at the top of a component to track its prop changes:
import { useTrackProps } from '@flotrace/runtime';
function MyComponent(props: MyProps) {
useTrackProps('MyComponent', props);
// ... rest of component
}useFloTrace() — Access runtime context
import { useFloTrace } from '@flotrace/runtime';
function DebugInfo() {
const floTrace = useFloTrace();
return <div>Connected: {floTrace?.connected ? 'Yes' : 'No'}</div>;
}Production Safety
By default, FloTrace is disabled in production (enabled defaults to process.env.NODE_ENV === 'development').
For explicit control, use a conditional import pattern:
// src/main.tsx
const FloTraceProvider = process.env.NODE_ENV === 'development'
? (await import('@flotrace/runtime')).FloTraceProvider
: ({ children }: { children: React.ReactNode }) => <>{children}</>;Troubleshooting
"Not connected"
- Ensure the FloTrace desktop app is running
- Check the port matches (default: 3457)
- Verify
config.enabledistrue - Check browser console for
[FloTrace]logs
Zustand stores not appearing
- Stores must be passed explicitly via the
storesprop - Each value must be a Zustand hook (function with
.getState()and.subscribe()methods) - Check console for
[FloTrace] Skipping "..." — not a valid Zustand storewarnings
Component tree is missing or incomplete
- The fiber tree walker needs React DevTools hook or DOM-based fiber access
- React DevTools browser extension improves reliability
- Tree depth is capped at 100 levels, children at 300 per node
- Reload the page if the tree appears empty
WebSocket keeps reconnecting
- FloTrace uses exponential backoff (2s → 4s → 8s... up to 30s) with a 10-attempt budget
- After 10 failed attempts, reload the page or restart FloTrace to retry
- Check that no firewall or proxy is blocking
ws://localhost:3457
API Reference
Components
| Export | Description |
|--------|-------------|
| FloTraceProvider | Main provider — wraps your app, manages WebSocket connection |
| withFloTrace(Component, name?) | HOC for targeted component profiling |
Hooks
| Export | Description |
|--------|-------------|
| useFloTrace() | Access connection state and config |
| useTrackProps(name, props) | Track prop changes for a component |
Types
| Export | Description |
|--------|-------------|
| FloTraceConfig | Configuration options interface |
| FloTraceProviderProps | Props for FloTraceProvider |
| SerializedValue | Serialized value type for safe WebSocket transmission |
| LiveTreeNode | Node in the live component tree |
| ReduxStoreApi | Minimal Redux store interface |
| TanStackQueryClientApi | Duck-typed TanStack Query client interface |
| TrackingOptions | Tracking options from extension |
| DEFAULT_CONFIG | Default configuration values |
| DetailedRenderReason | Detailed render reason with prop/state/context diffs |
| HookType, HookInfo | Hook type classification and inspection data |
| EffectInfo | Effect info with willRun and dep diffs |
| TimelineEvent, TimelineEventType | Component lifecycle events |
| TanStackQueryInfo, TanStackMutationInfo | Query and mutation tracking data |
| NetworkRequestEntry | Network request metadata (method, status, timing, correlation) |
| Fiber, FiberHookState, FiberEffect | React fiber type definitions |
Advanced Exports
| Export | Description |
|--------|-------------|
| getWebSocketClient(config?) | Get singleton WebSocket client |
| disposeWebSocketClient() | Dispose the WebSocket client |
| FloTraceWebSocketClient | WebSocket client class |
| installFiberTreeWalker() | Manually install fiber tree walker |
| uninstallFiberTreeWalker() | Uninstall fiber tree walker |
| requestTreeSnapshot() | Request a tree snapshot (DOM fallback) |
| getNodeHooks(nodeId) | Inspect hooks for a specific component |
| getNodeEffects(nodeId) | Inspect effects for a specific component |
| getDetailedRenderReason(nodeId) | Get detailed render reason (prop/state/context diffs) |
| getFiberRefMap() | Get map of all tracked fiber refs |
| inspectHooks(fiber) | Classify and inspect hooks from fiber |
| inspectEffects(fiber) | Inspect effects from fiber updateQueue |
| installZustandTracker() / uninstall... | Zustand per-store subscription tracking |
| installReduxTracker() / uninstall... | Redux store subscription tracking |
| installRouterTracker() / uninstall... | History API patching for route tracking |
| installTanStackQueryTracker() / uninstall... | TanStack Query cache subscriber (duck-typed) |
| installNetworkTracker() / uninstall... | Fetch/XHR patching for network monitoring |
| prewarmNetworkTracker() | Pre-install patches to capture page-load requests |
| installTimelineTracker() / uninstall... | Component lifecycle event tracking |
| recordTimelineEvent() | Manually record a timeline event |
| getTimeline(componentId) | Get timeline events for a component |
| serializeValue(value) | Serialize a value for WebSocket |
| serializeProps(props) | Serialize props object |
| isReduxStore(obj) | Type guard for Redux store |
| isTanStackQueryClient(obj) | Type guard for TanStack Query client |
Publishing
Prerequisites
npm loginRelease Scripts
| Script | Version Change | When to Use |
|--------|---------------|-------------|
| npm run release:patch | 0.1.0 → 0.1.1 | Bug fixes, small tweaks |
| npm run release:minor | 0.1.0 → 0.2.0 | New features, non-breaking changes |
| npm run release:major | 0.1.0 → 1.0.0 | Breaking API changes |
Each release script automatically:
- Bumps the version in
package.json - Creates a git commit and tag (e.g.
v0.1.1) - Cleans
dist/, rebuilds, and typechecks (prepublishOnly) - Publishes to npm under
@flotracescope
From the monorepo root
| Script | Action |
|--------|--------|
| npm run runtime:release:patch | Bump patch + build + publish (e.g. 0.1.0 → 0.1.1) |
| npm run runtime:release:minor | Bump minor + build + publish (e.g. 0.1.0 → 0.2.0) |
| npm run runtime:release:major | Bump major + build + publish (e.g. 0.1.0 → 1.0.0) |
| npm run runtime:publish | Publish current version as-is (no version bump) |
Note:
runtime:publishpublishes whatever version is currently inpackage.json. Use this for the first publish or to re-publish a fixed build without bumping the version. Therelease:*scripts auto-increment the version, create a git commit + tag, then publish.
License
MIT
