Skip to content

Commit 8fce116

Browse files
author
Brian Vaughn
authored
Update DevTools READMEs (#24105)
1 parent ef23a9e commit 8fce116

File tree

5 files changed

+238
-69
lines changed

5 files changed

+238
-69
lines changed
+99-41
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,122 @@
11
# `react-devtools-core`
22

3-
A standalone React DevTools implementation.
3+
This package provides low-level APIs to support renderers like [React Native](https://github.com/facebook/react-native). If you're looking for the standalone React DevTools UI, **we suggest using [`react-devtools`](https://github.com/facebook/react/tree/main/packages/react-devtools) instead of using this package directly**.
44

5-
This is a low-level package. If you're looking for the Electron app you can run, **use `react-devtools` package instead.**
5+
This package provides two entrypoints: labeled "backend" and "standalone" (frontend). Both APIs are described below.
66

7-
## API
7+
# Backend API
88

9-
### `react-devtools-core`
9+
Backend APIs are embedded in _development_ builds of renderers like [React Native](https://github.com/facebook/react-native) in order to connect to the React DevTools UI.
1010

11-
This is similar requiring the `react-devtools` package, but provides several configurable options. Unlike `react-devtools`, requiring `react-devtools-core` doesn't connect immediately but instead exports a function:
11+
### Example
12+
13+
If you are building a non-browser-based React renderer, you can use the backend API like so:
1214

1315
```js
14-
const { connectToDevTools } = require("react-devtools-core");
15-
connectToDevTools(config);
16+
if (process.env.NODE_ENV !== 'production') {
17+
const { connectToDevTools } = require("react-devtools-core");
18+
19+
// Must be called before packages like react or react-native are imported
20+
connectToDevTools({
21+
...config
22+
});
23+
}
1624
```
1725

18-
Run `connectToDevTools()` in the same context as React to set up a connection to DevTools.
19-
Be sure to run this function *before* importing e.g. `react`, `react-dom`, `react-native`.
26+
> **NOTE** that this API (`connectToDevTools`) must be (1) run in the same context as React and (2) must be called before React packages are imported (e.g. `react`, `react-dom`, `react-native`).
27+
28+
### `connectToDevTools` options
29+
| Prop | Default | Description |
30+
|---|---|---|
31+
| `host` | `"localhost"` | Socket connection to frontend should use this host. |
32+
| `isAppActive` | | (Optional) function that returns true/false, telling DevTools when it's ready to connect to React. |
33+
| `port` | `8097` | Socket connection to frontend should use this port. |
34+
| `resolveRNStyle` | | (Optional) function that accepts a key (number) and returns a style (object); used by React Native. |
35+
| `retryConnectionDelay` | `200` | Delay (ms) to wait between retrying a failed Websocket connection |
36+
| `useHttps` | `false` | Socket connection to frontend should use secure protocol (wss). |
37+
| `websocket` | | Custom `WebSocket` connection to frontend; overrides `host` and `port` settings. |
38+
39+
# Frontend API
40+
41+
Frontend APIs can be used to render the DevTools UI into a DOM node. One example of this is [`react-devtools`](https://github.com/facebook/react/tree/main/packages/react-devtools) which wraps DevTools in an Electron app.
42+
43+
### Example
44+
```js
45+
import DevtoolsUI from "react-devtools-core/standalone";
46+
47+
// See the full list of API methods in documentation below.
48+
const { setContentDOMNode, startServer } = DevtoolsUI;
49+
50+
// Render DevTools UI into a DOM element.
51+
setContentDOMNode(document.getElementById("container"));
52+
53+
// Start socket server used to communicate between backend and frontend.
54+
startServer(
55+
// Port defaults to 8097
56+
1234,
2057

21-
The `config` object may contain:
22-
* `host: string` (defaults to "localhost") - Websocket will connect to this host.
23-
* `port: number` (defaults to `8097`) - Websocket will connect to this port.
24-
* `useHttps: boolean` (defaults to `false`) - Websocket should use a secure protocol (wss).
25-
* `websocket: Websocket` - Custom websocket to use. Overrides `host` and `port` settings if provided.
26-
* `resolveRNStyle: (style: number) => ?Object` - Used by the React Native style plug-in.
27-
* `retryConnectionDelay: number` (defaults to `2000`) - Milliseconds delay to wait between retrying a failed Websocket connection.
28-
* `isAppActive: () => boolean` - If provided, DevTools will poll this method and wait until it returns true before connecting to React.
58+
// Host defaults to "localhost"
59+
"example.devserver.com",
2960

30-
## `react-devtools-core/standalone`
61+
// Optional config for secure socket (WSS).
62+
{
63+
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
64+
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
65+
}
66+
);
67+
```
3168

32-
Renders the DevTools interface into a DOM node.
69+
### Exported methods
70+
The `default` export is an object defining the methods described below.
3371

72+
These methods support chaining for convenience. For example:
3473
```js
35-
require("react-devtools-core/standalone")
36-
.setContentDOMNode(document.getElementById("container"))
37-
.setStatusListener(status => {
38-
// This callback is optional...
39-
})
40-
.startServer(port);
74+
const DevtoolsUI = require("react-devtools-core/standalone");
75+
DevtoolsUI.setContentDOMNode(element).startServer();
4176
```
4277

43-
Renders DevTools interface into a DOM node over SSL using a custom host name (Default is localhost).
78+
#### `connectToSocket(socket: WebSocket)`
79+
> This is an advanced config function that is typically not used.
80+
81+
Custom `WebSocket` connection to use for communication between DevTools frontend and backend. Calling this method automatically initializes the DevTools UI (similar to calling `startServer()`).
82+
83+
#### `openProfiler()`
84+
Automatically select the "Profiler" tab in the DevTools UI.
85+
86+
#### `setContentDOMNode(element: HTMLElement)`
87+
Set the DOM element DevTools UI should be rendered into on initialization.
88+
89+
#### `setDisconnectedCallback(callback: Function)`
90+
_Optional_ callback to be notified when DevTools `WebSocket` closes (or errors).
4491

92+
#### `setProjectRoots(roots: Array<string>)`
93+
_Optional_ set of root directores for source files. These roots can be used to open an inspected component's source code using an IDE.
94+
95+
#### `setStatusListener(callback: Function)`
96+
_Optional_ callback to be notified of socket server events (e.g. initialized, errored, connected).
97+
98+
This callback receives two parameters:
4599
```js
46-
const host = 'dev.server.com';
47-
const options = {
48-
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
49-
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
50-
};
51-
52-
53-
require("react-devtools-core/standalone")
54-
.setContentDOMNode(document.getElementById("container"))
55-
.setStatusListener(status => {
56-
// This callback is optional...
57-
})
58-
.startServer(port, host, options);
100+
function onStatus(
101+
message: string,
102+
status: 'server-connected' | 'devtools-connected' | 'error'
103+
): void {
104+
// ...
105+
}
59106
```
60107

61-
Reference the `react-devtools` package for a complete integration example.
108+
#### `startServer(port?: number, host?: string, httpsOptions?: Object, loggerOptions?: Object)`
109+
Start a socket server (used to communicate between backend and frontend) and renders the DevTools UI.
62110

63-
## Development
111+
This method accepts the following parameters:
112+
| Name | Default | Description |
113+
|---|---|---|
114+
| `port` | `8097` | Socket connection to backend should use this port. |
115+
| `host` | `"localhost"` | Socket connection to backend should use this host. |
116+
| `httpsOptions` | | _Optional_ object defining `key` and `cert` strings. |
117+
| `loggerOptions` | | _Optional_ object defining a `surface` string (to be included with DevTools logging events). |
118+
119+
# Development
64120

65121
Watch for changes made to the backend entry point and rebuild:
66122
```sh
@@ -71,3 +127,5 @@ Watch for changes made to the standalone UI entry point and rebuild:
71127
```sh
72128
yarn start:standalone
73129
```
130+
131+
Run the standalone UI using `yarn start` in the [`react-devtools`](https://github.com/facebook/react/tree/main/packages/react-devtools).

packages/react-devtools-inline/README.md

+120-21
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
# `react-devtools-inline`
22

3-
React DevTools implementation for embedding within a browser-based IDE (e.g. [CodeSandbox](https://codesandbox.io/), [StackBlitz](https://stackblitz.com/)).
3+
This package can be used to embed React DevTools into browser-based tools like [CodeSandbox](https://codesandbox.io/), [StackBlitz](https://stackblitz.com/), and [Replay](https://replay.io).
44

5-
This is a low-level package. If you're looking for the standalone DevTools app, **use the `react-devtools` package instead.**
5+
If you're looking for the standalone React DevTools UI, **we suggest using [`react-devtools`](https://github.com/facebook/react/tree/main/packages/react-devtools) instead of using this package directly**.
66

7-
## Usage
7+
---
8+
9+
> **Note** that this package (and the DevTools UI) relies on several _experimental_ APIs that are **only available in the [experimental release channel](https://reactjs.org/docs/release-channels.html#experimental-channel)**. This means that you will need to install `react@experimental` and `react-dom@experimenal`.
10+
11+
---
12+
13+
# Usage
814

915
This package exports two entry points: a frontend (to be run in the main `window`) and a backend (to be installed and run within an `iframe`<sup>1</sup>).
1016

@@ -16,15 +22,18 @@ The frontend and backend can be initialized in any order, but **the backend must
1622

1723
<sup>1</sup> Sandboxed iframes are supported.
1824

19-
## API
25+
# Backend APIs
26+
### `initialize(windowOrGlobal)`
27+
28+
Installs the global hook on the window/global object. This hook is how React and DevTools communicate.
2029

21-
### `react-devtools-inline/backend`
30+
> **This method must be called before React is loaded.** (This includes `import`/`require` statements and `<script>` tags that include React.)
31+
32+
### `activate(windowOrGlobal)`
2233

23-
* **`initialize(contentWindow)`** -
24-
Installs the global hook on the window. This hook is how React and DevTools communicate. **This method must be called before React is loaded.**<sup>2</sup>
25-
* **`activate(contentWindow)`** -
2634
Lets the backend know when the frontend is ready. It should not be called until after the frontend has been initialized, else the frontend might miss important tree-initialization events.
2735

36+
### Example
2837
```js
2938
import { activate, initialize } from 'react-devtools-inline/backend';
3039

@@ -41,13 +50,14 @@ initialize(contentWindow);
4150
activate(contentWindow);
4251
```
4352

44-
<sup>2</sup> The backend must be initialized before React is loaded. (This means before any `import` or `require` statements or `<script>` tags that include React.)
53+
# Frontend APIs
4554

46-
### `react-devtools-inline/frontend`
55+
### `initialize(windowOrGlobal)`
56+
Configures the DevTools interface to listen to the `window` (or `global` object) the backend was injected into. This method returns a React component that can be rendered directly.
4757

48-
* **`initialize(contentWindow)`** -
49-
Configures the DevTools interface to listen to the `window` the backend was injected into. This method returns a React component that can be rendered directly<sup>3</sup>.
58+
> Because the DevTools interface makes use of several new React concurrent features (like Suspense) **it should be rendered using `ReactDOMClient.createRoot` instead of `ReactDOM.render`.**
5059
60+
### Example
5161
```js
5262
import { initialize } from 'react-devtools-inline/frontend';
5363

@@ -60,9 +70,7 @@ const contentWindow = iframe.contentWindow;
6070
const DevTools = initialize(contentWindow);
6171
```
6272

63-
<sup>3</sup> Because the DevTools interface makes use of several new React APIs (e.g. suspense, concurrent mode) it should be rendered using `ReactDOMClient.createRoot`. **It should not be rendered with `ReactDOM.render`.**
64-
65-
## Examples
73+
# Advanced examples
6674

6775
### Supporting named hooks
6876

@@ -169,7 +177,7 @@ iframe.onload = () => {
169177
};
170178
```
171179

172-
### Advanced integration with custom "wall"
180+
### Advanced: Custom "wall"
173181

174182
Below is an example of an advanced integration with a website like [Replay.io](https://replay.io/) or Code Sandbox's Sandpack (where more than one DevTools instance may be rendered per page).
175183

@@ -235,25 +243,116 @@ const wall = {
235243
};
236244
```
237245

238-
## Local development
246+
### Advanced: Node + browser
247+
248+
Below is an example of an advanced integration that could be used to connect React running in a Node process to React DevTools running in a browser.
249+
250+
##### Sample Node backend
251+
```js
252+
const {
253+
activate,
254+
createBridge,
255+
initialize,
256+
} = require('react-devtools-inline/backend');
257+
const { createServer } = require('http');
258+
const SocketIO = require('socket.io');
259+
260+
const server = createServer();
261+
const socket = SocketIO(server, {
262+
cors: {
263+
origin: "*",
264+
methods: ["GET", "POST"],
265+
allowedHeaders: [],
266+
credentials: true
267+
}
268+
});
269+
socket.on('connection', client => {
270+
const wall = {
271+
listen(listener) {
272+
client.on('message', data => {
273+
if (data.uid === UID) {
274+
listener(data);
275+
}
276+
});
277+
},
278+
send(event, payload) {
279+
const data = {event, payload, uid: UID};
280+
client.emit('message', data);
281+
},
282+
};
283+
284+
const bridge = createBridge(global, wall);
285+
286+
client.on('disconnect', () => {
287+
bridge.shutdown();
288+
});
289+
290+
activate(global, { bridge });
291+
});
292+
socket.listen(PORT);
293+
```
294+
295+
##### Sample Web frontend
296+
```js
297+
import { createElement } from 'react';
298+
import { createRoot } from 'react-dom/client';
299+
import {
300+
createBridge,
301+
createStore,
302+
initialize as createDevTools,
303+
} from 'react-devtools-inline/frontend';
304+
import { io } from "socket.io-client";
305+
306+
let root = null;
307+
308+
const socket = io(`http://${HOST}:${PORT}`);
309+
socket.on("connect", () => {
310+
const wall = {
311+
listen(listener) {
312+
socket.on("message", (data) => {
313+
if (data.uid === UID) {
314+
listener(data);
315+
}
316+
});
317+
},
318+
send(event, payload) {
319+
const data = { event, payload, uid: UID };
320+
socket.emit('message', data);
321+
},
322+
};
323+
324+
const bridge = createBridge(window, wall);
325+
const store = createStore(bridge);
326+
const DevTools = createDevTools(window, { bridge, store });
327+
328+
root = createRoot(document.getElementById('root'));
329+
root.render(createElement(DevTools));
330+
});
331+
socket.on("disconnect", () => {
332+
root.unmount();
333+
root = null;
334+
});
335+
```
336+
337+
# Local development
239338
You can also build and test this package from source.
240339

241-
### Prerequisite steps
340+
## Prerequisite steps
242341
DevTools depends on local versions of several NPM packages<sup>1</sup> also in this workspace. You'll need to either build or download those packages first.
243342

244343
<sup>1</sup> Note that at this time, an _experimental_ build is required because DevTools depends on the `createRoot` API.
245344

246-
#### Build from source
345+
### Build from source
247346
To build dependencies from source, run the following command from the root of the repository:
248347
```sh
249348
yarn build-for-devtools
250349
```
251-
#### Download from CI
350+
### Download from CI
252351
To use the latest build from CI, run the following command from the root of the repository:
253352
```sh
254353
./scripts/release/download-experimental-build.js
255354
```
256-
### Build steps
355+
## Build steps
257356
Once the above packages have been built or downloaded, you can watch for changes made to the source code and automatically rebuild by running:
258357
```sh
259358
yarn start
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
This directory contains code shared between several DevTools packages:
2+
* /packages/react-devtools-core
3+
* /packages/react-devtools-extensions
4+
* /packages/react-devtools-inline
5+
6+
It is not published or released anywhere directly.

0 commit comments

Comments
 (0)