TanStack Devtools
repository·main·Indexed 19 days ago
https://github.com/tanstack/devtoolsA unified debugging toolkit for inspecting and monitoring application state and behavior in real time. It integrates with the TanStack ecosystem and supports various frameworks, including React, Solid, and Angular.
What's inside TanStack Devtools
- TanStack Devtools is a debugging toolkit designed to provide a unified interface for inspecting, monitoring, and extending applications. It allows developers to debug state and behavior in real time and features an extensible plugin architecture for customizable UIs. It is compatible with multiple frameworks including React, Solid, and Vanilla JS, and integrates seamlessly with other TanStack libraries like TanStack Query and TanStack Router.
Overview of TanStack Devtools packages
mainTanStack Devtools is a framework-agnostic foundation for building and managing custom developer tools. It is organized into several layers, allowing you to install only what you need based on your use case.
Framework Adapters
Thin wrappers to integrate devtools into specific frameworks:
@tanstack/react-devtools@tanstack/vue-devtools@tanstack/solid-devtools@tanstack/preact-devtools
Core
@tanstack/devtools: The devtools shell UI (built in Solid.js). It provides the plugin system, tab navigation, settings panel, and the trigger button.
Event System
Used for communication between plugins and the shell:
@tanstack/devtools-event-client: A type-safe event client for building custom plugins.@tanstack/devtools-event-bus: The WebSocket/SSE transport layer connecting the client and server.
Build Tools
@tanstack/devtools-vite: A Vite plugin that provides source inspection, console piping, enhanced logging, and automatic stripping of devtools from production builds.
Utilities
@tanstack/devtools-utils: Plugin factory helpers for each framework.@tanstack/devtools-ui: A shared Solid.js UI component library.@tanstack/devtools-client: Internal typed event client for core devtools operations.
What is TanStack Devtools?
mainTanStack Devtools is a framework-agnostic toolkit designed for building custom developer tool panels. It uses a plugin system with typed event communication to provide a unified debugging experience across different frontend frameworks.
Key components include:
- Shell UI: The main container for devtools.
- Event Transport: A system for moving data between the app and the devtools.
- Framework Adapters: Specialized plugins for React, Vue, Solid, and Preact.
- Build Tooling: Vite plugins for source injection and enhanced debugging.
What is @tanstack/devtools-ui?
main@tanstack/devtools-ui is a set of Solid.js UI components designed specifically for TanStack Devtools. These components are used throughout the TanStack ecosystem to ensure a consistent and customizable user interface for various developer tools.Key features of TanStack Devtools
mainTanStack Devtools provides several built-in capabilities for developers:
- Framework Agnostic: Native support for React, Vue, Solid, and Preact.
- Plugin System & Marketplace: A simple API to build, share, and install devtools plugins.
- Type-Safe Event System: Fully typed communication between plugins and the shell.
- Source Inspector: Enables "go-to-source" functionality by clicking elements in your app to jump to their source code.
- Console Piping: Routes devtools output directly to the browser console.
- Picture-in-Picture Mode: Allows the devtools panel to be popped out into a separate window to avoid obscuring the application UI.
- Customizable Hotkeys: Supports rebinding keyboard shortcuts.
Preact Framework Adapter Reference
mainThe Preact adapter for TanStack Devtools provides utilities to integrate custom devtools panels into the TanStack Devtools ecosystem using Preact. It is functionally identical to the React adapter but uses
preactJSX andpreact/hooks.Key Differences from React
- Import Path: Use
@tanstack/devtools-utils/preactinstead of@tanstack/devtools-utils/react. - JSX: Uses
preactJSX runtime. - Hooks: Uses
preact/hooks. - Attributes: While both work, it is idiomatic to use
classinstead ofclassNamein Preact. - Default Theme: If no theme is provided, the panel defaults to
'dark'.
- Import Path: Use
How TanStack Devtools production stripping works
mainTanStack Devtools uses two independent mechanisms to ensure devtools code is excluded from production bundles:
Vite Plugin Auto-Stripping: For Vite projects, the
@tanstack/devtools-viteplugin uses AST-based stripping. It parses source files and removes imports from devtools packages (e.g.,@tanstack/react-devtools,@tanstack/devtools) along with any associated JSX elements. This happens automatically duringvite buildwhen the mode isproduction.Conditional Exports: The
@tanstack/devtoolscore package uses Node.js conditional exports to serve different bundles. In a browser environment, it resolves todev.jsduring development (including dev-only extras) andindex.jsfor production builds.
How event communication works in TanStack Devtools
mainThe system relies on a typed event system for data flow between the application and the devtools panels.
Core Concepts:
- EventClient: The primary interface for plugins to emit and listen to events.
- Bidirectional Communication: Supports commands, state editing, and time-travel debugging.
- Serialization: All event payloads must be serializable. Use
structuredClonefor creating snapshots to ensure data integrity and avoid issues in cross-tab scenarios. - Event Naming: Do not include the
pluginIdprefix in your event names; the system handles namespacing internally. - Connection Lifecycle: Note that events may drop if the connection fails after 5 retries. Ensure you are listening for events after the connection is established.
When to use factories vs manual plugin objects
mainUse Factories
Use the factory functions (
createReactPlugin,createVuePlugin, etc.) when building a reusable library plugin intended for publication. They provide:- Consistent plugin object shapes across frameworks.
- Automatic generation of a matching
NoOpPluginfor production tree-shaking. - Correct typing without manual annotations.
Use Manual Plugin Objects
Use manual objects when building a one-off internal devtools panel for your own application. This is simpler and avoids extra abstraction:
// Manual approach for one-off panels { name: 'App State', render: (el, theme) => <MyPanel theme={theme} />, }// Manual approach -- fine for one-off panels { name: 'App State', render: (el, theme) => <MyPanel theme={theme} />, }Configure File-Based Routing with TanStack Router
mainThis project uses TanStack Router with file-based routing. Routes are managed as files within thesrc/routesdirectory. Adding a new file to this directory automatically generates a new route.How to build custom plugins and panels
mainCustom plugins are built by creating event clients and panel components that interact with the TanStack Devtools shell.
Plugin Development Best Practices:
- Event Clients: Use the
EventClientclass to manage the connection lifecycle and event maps. Ensure each plugin has a uniquepluginIdto avoid event collisions. - Panel Components: Build UI components that listen to events. Always respect the
themeprop provided by the devtools to ensure visual consistency. - Cleanup: It is critical to clean up event listeners when a panel is unmounted to prevent memory leaks.
- Limits: Be aware that there is a limit of 3 active plugins at a time.
- Portals: Use framework-specific portals instead of raw DOM manipulation when rendering panel content.
- Event Clients: Use the
Create custom plugins using EventClient
mainTanStack Devtools allows you to create custom plugins by emitting and listening to an event bus. This is achieved using the
@tanstack/devtools-event-clientpackage. The process involves three main steps:- Setup an
EventClient: Define anEventMapwhere keys are event suffixes and values are the payload types. Extend theEventClientclass and provide apluginIdin the constructor. ThepluginIdis automatically prepended to all event keys. - Emit events from your application: In your application logic (e.g., a state manager or library), call
DevtoolsEventClient.emit(eventSuffix, payload)whenever a state change occurs. TheeventSuffixmust match a key in yourEventMap. - Consume events in a Devtools Panel: Create a component that subscribes to the events using
DevtoolsEventClient.on(eventSuffix, callback). The callback receives the payload.
EventClientis framework-agnostic and works in vanilla JavaScript as well as React, Vue, or Angular.// 1. Setup type EventMap = { 'counter-state': { count: number, history: number[] } } class CustomEventClient extends EventClient<EventMap> { constructor() { super({ pluginId: 'custom-devtools' }) } } const DevtoolsEventClient = new CustomEventClient() // 2. Emit DevtoolsEventClient.emit('counter-state', { count: 1, history: [1] }) // 3. Consume DevtoolsEventClient.on('counter-state', e => setState(e.payload))- Setup an