Skip to content

Commit

Permalink
Move metro-inspector-proxy into dev-middleware (facebook#39045)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#39045

## Context

RFC: Decoupling Flipper from React Native core: react-native-community/discussions-and-proposals#641

## Changes

- Relocates `metro-inspector-proxy` source from the Metro repo into the React Native repo as part of the `react-native/dev-middleware` package.
    - Drops the `runInspectorProxy` entry point.
- Attaches the Inspector Proxy to the `createDevMiddleware()` API as the new integration point for this functionality.
- Documents migrated endpoints + usage of `createDevMiddleware()` in README.

Changelog: [Internal]
Metro changelog: None (`metro-inspector-proxy` is now an internal component of `react-native`, covered in the [release notes for 0.78.1](https://github.com/facebook/metro/releases/tag/v0.78.1))

Reviewed By: motiz88, blakef

Differential Revision: D48066213

fbshipit-source-id: 83d83c041f0426d063f830d10f0d36e4f8a16175
  • Loading branch information
huntie authored and facebook-github-bot committed Aug 16, 2023
1 parent e7f6f07 commit 32abeaa
Show file tree
Hide file tree
Showing 8 changed files with 1,116 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ declare module '@react-native-community/cli-server-api' {
): {
middleware: Server,
websocketEndpoints: {
'/debugger-proxy': ws$WebSocketServer,
'/message': ws$WebSocketServer,
'/events': ws$WebSocketServer,
[path: string]: ws$WebSocketServer,
},
debuggerProxyEndpoint: {
server: ws$WebSocketServer,
Expand Down
77 changes: 74 additions & 3 deletions packages/dev-middleware/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,82 @@
# @react-native/dev-middleware

![https://img.shields.io/npm/v/@react-native/dev-middleware?color=brightgreen&label=npm%20package](https://www.npmjs.com/package/@react-native/dev-middleware)
![npm package](https://img.shields.io/npm/v/@react-native/dev-middleware?color=brightgreen&label=npm%20package)

Dev server middleware supporting core React Native development features. This package is preconfigured in all React Native projects.

## Endpoints
## Usage

### `/open-debugger`
Middleware can be attached to a dev server (e.g. [Metro](https://facebook.github.io/metro/docs/getting-started)) using the `createDevMiddleware` API.

```js
import { createDevMiddleware } from '@react-native/dev-middleware';

function myDevServerImpl(args) {
...

const {middleware, websocketEndpoints} = createDevMiddleware({
host: args.host,
port: metroConfig.server.port,
projectRoot: metroConfig.projectRoot,
logger,
});

await Metro.runServer(metroConfig, {
host: args.host,
...,
unstable_extraMiddleware: [
middleware,
// Optionally extend with additional HTTP middleware
],
websocketEndpoints: {
...websocketEndpoints,
// Optionally extend with additional WebSocket endpoints
},
});
}
```

## Included middleware

`@react-native/dev-middleware` is designed for integrators such as [`@expo/dev-server`](https://www.npmjs.com/package/@expo/dev-server) and [`@react-native/community-cli-plugin`](https://github.com/facebook/react-native/tree/main/packages/community-cli-plugin). It provides a common default implementation for core React Native dev server responsibilities.

We intend to keep this to a narrow set of functionality, based around:

- **Debugging** — The [Chrome DevTools protocol (CDP)](https://chromedevtools.github.io/devtools-protocol/) endpoints supported by React Native, including the Inspector Proxy, which facilitates connections with multiple devices.
- **Dev actions** — Endpoints implementing core [Dev Menu](https://reactnative.dev/docs/debugging#accessing-the-dev-menu) actions, e.g. reloading the app, opening the debugger frontend.

### HTTP endpoints

<small>`DevMiddlewareAPI.middleware`</small>

These are exposed as a [`connect`](https://www.npmjs.com/package/connect) middleware handler, assignable to `Metro.runServer` or other compatible HTTP servers.

#### GET `/json/list`, `/json` ([CDP](https://chromedevtools.github.io/devtools-protocol/#endpoints))

Returns the list of available WebSocket targets for all connected React Native app sessions.

#### GET `/json/version` ([CDP](https://chromedevtools.github.io/devtools-protocol/#endpoints))

Returns version metadata used by Chrome DevTools.

#### POST `/open-debugger`

Open the JavaScript debugger for a given CDP target (direct Hermes debugging).

<details>
<summary>Example</summary>

curl -X POST 'http://localhost:8081/open-debugger?appId=com.meta.RNTester'
</details>

### WebSocket endpoints

<small>`DevMiddlewareAPI.websocketEndpoints`</small>

#### `/inspector/device`

WebSocket handler for registering device connections.

#### `/inspector/debug`

WebSocket handler that proxies CDP messages to/from the corresponding device.
34 changes: 26 additions & 8 deletions packages/dev-middleware/src/createDevMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @flow strict-local
* @format
* @oncall react_native
*/
Expand All @@ -14,18 +14,36 @@ import type {Logger} from './types/Logger';

import connect from 'connect';
import openDebuggerMiddleware from './middleware/openDebuggerMiddleware';
import InspectorProxy from './inspector-proxy/InspectorProxy';

type Options = $ReadOnly<{
host: string,
port: number,
projectRoot: string,
logger?: Logger,
}>;

export default function createDevMiddleware({logger}: Options = {}): {
type DevMiddlewareAPI = $ReadOnly<{
middleware: NextHandleFunction,
} {
const middleware = connect().use(
'/open-debugger',
openDebuggerMiddleware({logger}),
);
websocketEndpoints: {[path: string]: ws$WebSocketServer},
}>;

export default function createDevMiddleware({
host,
port,
projectRoot,
logger,
}: Options): DevMiddlewareAPI {
const inspectorProxy = new InspectorProxy(projectRoot);

const middleware = connect()
.use('/open-debugger', openDebuggerMiddleware({logger}))
.use((...args) => inspectorProxy.processRequest(...args));

return {middleware};
return {
middleware,
websocketEndpoints: inspectorProxy.createWebSocketListeners(
`${host}:${port}`,
),
};
}
2 changes: 1 addition & 1 deletion packages/dev-middleware/src/index.flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @flow strict-local
* @format
* @oncall react_native
*/
Expand Down
Loading

0 comments on commit 32abeaa

Please sign in to comment.