Standalone development tool for debugging React applications outside of browser environments
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Server and UI management functions for hosting DevTools in custom environments with full control over the interface, WebSocket connections, and rendering.
Main API object for managing standalone DevTools server and UI.
const DevtoolsUI: {
startServer: (port?: number, host?: string, httpsOptions?: ServerOptions, loggerOptions?: LoggerOptions) => ServerControl;
connectToSocket: (socket: WebSocket) => ConnectionControl;
setContentDOMNode: (node: HTMLElement) => typeof DevtoolsUI;
setProjectRoots: (roots: string[]) => void;
setStatusListener: (listener: StatusListener) => typeof DevtoolsUI;
setDisconnectedCallback: (callback: OnDisconnectedCallback) => typeof DevtoolsUI;
openProfiler: () => void;
};
interface ServerControl {
close(): void;
}
interface ConnectionControl {
close(): void;
}Creates and starts a WebSocket server for DevTools connections.
/**
* Starts a WebSocket server for DevTools connections
* @param port - Server port (default: 8097)
* @param host - Server host (default: 'localhost')
* @param httpsOptions - HTTPS configuration for secure connections
* @param loggerOptions - Logging configuration
* @returns Server control object with close method
*/
function startServer(
port?: number,
host?: string,
httpsOptions?: ServerOptions,
loggerOptions?: LoggerOptions
): { close(): void };
interface ServerOptions {
/** HTTPS private key */
key?: string;
/** HTTPS certificate */
cert?: string;
}
interface LoggerOptions {
/** Logging surface identifier */
surface?: string;
}Usage Examples:
import DevtoolsUI from "react-devtools-core/standalone";
// Basic server startup
const server = DevtoolsUI.startServer();
// Custom port and host
const server = DevtoolsUI.startServer(9090, '0.0.0.0');
// HTTPS server
const server = DevtoolsUI.startServer(8097, 'localhost', {
key: fs.readFileSync('path/to/private-key.pem'),
cert: fs.readFileSync('path/to/certificate.pem')
});
// With logging configuration
const server = DevtoolsUI.startServer(8097, 'localhost', null, {
surface: 'custom-integration'
});
// Shutdown server
server.close();Connects DevTools UI to an existing WebSocket connection.
/**
* Connects DevTools UI to an existing WebSocket
* @param socket - WebSocket connection to use
* @returns Connection control object with close method
*/
function connectToSocket(socket: WebSocket): { close(): void };Usage Examples:
import DevtoolsUI from "react-devtools-core/standalone";
// Connect to existing WebSocket
const ws = new WebSocket('ws://localhost:8097');
const connection = DevtoolsUI.connectToSocket(ws);
// Handle connection events
ws.onopen = () => console.log('Connected to DevTools');
ws.onerror = (error) => console.error('Connection error:', error);
// Close connection
connection.close();Sets the DOM element where DevTools UI will be rendered.
/**
* Sets the DOM node where DevTools UI will be rendered
* @param node - HTML element to render DevTools into
* @returns DevtoolsUI object for method chaining
*/
function setContentDOMNode(node: HTMLElement): typeof DevtoolsUI;Usage Examples:
import DevtoolsUI from "react-devtools-core/standalone";
// Set render target
const container = document.getElementById('devtools-container');
DevtoolsUI.setContentDOMNode(container);
// Method chaining
DevtoolsUI
.setContentDOMNode(document.getElementById('devtools'))
.setStatusListener((message, status) => {
console.log(`Status: ${message} (${status})`);
});Configures project root directories for editor integration.
/**
* Sets project root paths for editor integration
* @param roots - Array of absolute directory paths
*/
function setProjectRoots(roots: string[]): void;Usage Examples:
import DevtoolsUI from "react-devtools-core/standalone";
// Single project root
DevtoolsUI.setProjectRoots(['/path/to/project']);
// Multiple project roots for monorepos
DevtoolsUI.setProjectRoots([
'/path/to/frontend',
'/path/to/backend',
'/path/to/shared'
]);
// Empty array to disable editor integration
DevtoolsUI.setProjectRoots([]);Sets a callback for DevTools status updates and connection events.
/**
* Sets a callback for DevTools status updates
* @param listener - Status update callback function
* @returns DevtoolsUI object for method chaining
*/
function setStatusListener(listener: StatusListener): typeof DevtoolsUI;
type StatusListener = (message: string, status: StatusTypes) => void;
type StatusTypes = "server-connected" | "devtools-connected" | "error";Usage Examples:
import DevtoolsUI from "react-devtools-core/standalone";
// Basic status logging
DevtoolsUI.setStatusListener((message, status) => {
console.log(`DevTools: ${message} (${status})`);
});
// Advanced status handling
DevtoolsUI.setStatusListener((message, status) => {
switch (status) {
case 'server-connected':
document.getElementById('status').textContent = 'Server Ready';
document.getElementById('status').className = 'status-success';
break;
case 'devtools-connected':
document.getElementById('status').textContent = 'DevTools Connected';
document.getElementById('status').className = 'status-connected';
break;
case 'error':
document.getElementById('status').textContent = `Error: ${message}`;
document.getElementById('status').className = 'status-error';
break;
}
});Sets a callback for when DevTools disconnects from the target application.
/**
* Sets a callback for when DevTools disconnects
* @param callback - Disconnection callback function
* @returns DevtoolsUI object for method chaining
*/
function setDisconnectedCallback(callback: OnDisconnectedCallback): typeof DevtoolsUI;
type OnDisconnectedCallback = () => void;Usage Examples:
import DevtoolsUI from "react-devtools-core/standalone";
// Handle disconnection
DevtoolsUI.setDisconnectedCallback(() => {
console.log('DevTools disconnected from target app');
document.getElementById('connection-status').textContent = 'Disconnected';
// Show reconnection UI
document.getElementById('reconnect-btn').style.display = 'block';
});Opens DevTools in Profiler mode without requiring a connection to a target application.
/**
* Opens DevTools in Profiler mode without a connection
*/
function openProfiler(): void;Usage Examples:
import DevtoolsUI from "react-devtools-core/standalone";
// Setup DOM container first
DevtoolsUI.setContentDOMNode(document.getElementById('profiler-container'));
// Open profiler for offline analysis
DevtoolsUI.openProfiler();import DevtoolsUI from "react-devtools-core/standalone";
class DevToolsHost {
constructor(containerId) {
this.container = document.getElementById(containerId);
this.server = null;
this.setupUI();
}
setupUI() {
// Configure DevTools UI
DevtoolsUI
.setContentDOMNode(this.container)
.setProjectRoots([process.cwd()])
.setStatusListener(this.handleStatus.bind(this))
.setDisconnectedCallback(this.handleDisconnection.bind(this));
}
startServer(port = 8097, host = 'localhost') {
this.server = DevtoolsUI.startServer(port, host, null, {
surface: 'custom-host'
});
console.log(`DevTools server started at ws://${host}:${port}`);
return this.server;
}
handleStatus(message, status) {
console.log(`DevTools Status: ${message} (${status})`);
// Update UI based on status
const statusEl = this.container.querySelector('.status');
if (statusEl) {
statusEl.textContent = message;
statusEl.className = `status status-${status}`;
}
}
handleDisconnection() {
console.log('Target application disconnected');
// Show waiting message
const statusEl = this.container.querySelector('.status');
if (statusEl) {
statusEl.textContent = 'Waiting for connection...';
statusEl.className = 'status status-waiting';
}
}
shutdown() {
if (this.server) {
this.server.close();
this.server = null;
}
}
}
// Usage
const devtools = new DevToolsHost('devtools-container');
devtools.startServer(8097, '0.0.0.0');import DevtoolsUI from "react-devtools-core/standalone";
import { app, BrowserWindow } from "electron";
class ElectronDevTools {
constructor() {
this.window = null;
this.server = null;
}
createWindow() {
this.window = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
// Load DevTools HTML
this.window.loadFile('devtools.html');
// Setup DevTools when ready
this.window.webContents.once('dom-ready', () => {
this.setupDevTools();
});
}
setupDevTools() {
this.window.webContents.executeJavaScript(`
const DevtoolsUI = require("react-devtools-core/standalone");
DevtoolsUI
.setContentDOMNode(document.getElementById('devtools'))
.setStatusListener((message, status) => {
console.log('DevTools:', message, status);
});
// Start server
const server = DevtoolsUI.startServer(8097);
window.devtoolsServer = server;
`);
}
shutdown() {
if (this.window) {
this.window.webContents.executeJavaScript(`
if (window.devtoolsServer) {
window.devtoolsServer.close();
}
`);
}
}
}Common server error codes and handling:
DevtoolsUI.setStatusListener((message, status) => {
if (status === 'error') {
if (message.includes('EADDRINUSE')) {
console.error('Port already in use. Try a different port or close other DevTools instances.');
} else if (message.includes('EACCES')) {
console.error('Permission denied. Try using a port > 1024 or run with elevated privileges.');
} else {
console.error('DevTools server error:', message);
}
}
});Handle WebSocket connection problems:
const ws = new WebSocket('ws://localhost:8097');
ws.onerror = (error) => {
console.error('WebSocket error:', error);
// Implement reconnection logic
setTimeout(() => {
const newWs = new WebSocket('ws://localhost:8097');
DevtoolsUI.connectToSocket(newWs);
}, 2000);
};
ws.onclose = (event) => {
console.log('WebSocket closed:', event.code, event.reason);
if (!event.wasClean) {
// Unexpected closure - attempt reconnection
setTimeout(() => {
const newWs = new WebSocket('ws://localhost:8097');
DevtoolsUI.connectToSocket(newWs);
}, 1000);
}
};Install with Tessl CLI
npx tessl i tessl/npm-react-devtools