Skip to content

Conversation

@mweststrate
Copy link
Contributor

Summary:

This PR introduce a new endpoint, /events to be used by developer tooling, that services two goals:

  1. Stream the applications JavaScript logs and metro events
  2. Support receiving commands and forward them to Metro. The setup is generic, but the two use cases for now are "reload" and "open dev menu"

This change reflects changes we made to the CLI at FB as well. This enables Flipper to have better first class support for React Native. Although some Flipper plugins could already be used on RN through the generic ADB support, this change makes it possible to see the Metro server as a real device and interact with it.

Preview:

Screen Shot 2020-02-10 at 17 51 05

https://youtu.be/HIau7zjJ3gg

Note that currently errors are not send by RN to the Metro logging, so in the current RN version those won't be visible, but that will change in a next minor or patch release in RN.

Test Plan:

  1. Build the repo
  2. Take a test project and update the CLI according to the contributing guidelines.
  3. Start Flipper (the supporter Flipper version didn't have an OSS release yet so need to clone from source and yarn && yarn start)
  4. Start the RN app with yarn android (or ios)
  5. React Native should show up as device, logging, open devtools and reload should work

@mweststrate
Copy link
Contributor Author

N.B.: during testing I encountered errors like ReferenceError: SHA-1 for file /Users/mweststrate/Desktop/cli/node_modules/metro/src/lib/polyfills/require.js (/Users/mweststrate/Desktop/cli/node_modules/metro/src/lib/polyfills/require.js) is not computed.

However those seem to be unrelated, and the setup works despite that. But to be able to see the fully working version; using relative-deps to link the cli, rather than yarn link seems to solve the issue.

@mweststrate
Copy link
Contributor Author

Tests failures seem to be unrelated to this PR, let me know if they are related, or this branch needs rebasing

@thymikee
Copy link
Member

Lovely!

Whenever you run Metro (e.g. through start) for local CLI development, you need to pass it extra root (it sucks, but we're working on removing this indirection): https://github.com/react-native-community/cli/blob/master/CONTRIBUTING.md#running-start-command. That should get rid of ReferenceError: SHA-1

Some e2e tests are flaky, we need to fix or at least disable them, so unrelated.

@mweststrate
Copy link
Contributor Author

Tried and that failed, but fiddled a bit more, and added changes to this PR describing what I needed instead :)

@grabbou
Copy link
Member

grabbou commented Feb 11, 2020

I am going to look at this later today or tomorrow, thanks for this contribution!

@lucasbento
Copy link
Member

I just tested this on iPhone simulator (iOS 13.3), reload works fine but opening the dev menu does not.

Also, I was only able to get the packager to work by running:

REACT_NATIVE_APP_ROOT=path/to/cli node path/to/cli/packages/cli/build/bin.js start

@mweststrate
Copy link
Contributor Author

@lucasbento against which RN version was that? I tested against a project in 0.62.rc-0

@lucasbento
Copy link
Member

I tested on 0.61.5 😅 forgot that the CLI has been bumped for 0.62, nevermind then!

'/events',
ms,
);
logger.log('Created events socket');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this console log here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way Flipper works, is that it scans the system for all open terminals, and parses their output stream. To find out which one belongs to Metro, it need to be able to recognize it, so this logging statement is secretly used as a marker so that we know that we are looking at the metro output stream.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kidding, will remove.

.watchmanconfig Outdated
@@ -0,0 +1 @@
{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can gitignore this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

@grabbou grabbou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Left some tiny comments, but nothing major! Great work!

@@ -0,0 +1,161 @@
/**
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this header appropriate here? We're not adding them to any new files and this project is MIT based. Not a lawyer, but "confidential" is a bit concerning :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I copied that just from some of the other CLI files, will double check😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just dropped the header, like in most files. Some files do have still this header though (e.g. messageSocket)


const PROTOCOL_VERSION = 2;

function parseMessage(data: any): any {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to have parseMessage<T>(data: Object): T | undefined?

clientWs.onmessage = event => {
const message: Command = parseMessage(event.data);
if (message == null) {
logger.error('Received message not matching protocol');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note that we already log this information inside parseMessage I'd suggest to leave it just once.

const clients = new Map();
let nextClientId = 0;

function broadCastEvent(message: any) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took me a while to realize that this is used to actually send logs from JavaScript to all connected clients that support it (such as Flipper). Again, a little description here or at the top of the module would be great!

@mweststrate
Copy link
Contributor Author

Processed all review comments! Documented the general setup better, hopefully clarifies the bi-directional communication setup between the websockets and reporter better :)

@thymikee thymikee changed the title introduce /events endpoint for devtools like Flipper feat: introduce /events endpoint for devtools like Flipper Feb 17, 2020
@thymikee thymikee merged commit 73aad4f into react-native-community:master Feb 17, 2020
thymikee added a commit that referenced this pull request Feb 17, 2020
* introduce /events endpoint for devtools like Flipper

* Small fix for the CONTRIBUTING instructions on running a local CLI

* Processed review comments

* Update packages/cli/src/commands/server/eventsSocket.ts

* Update packages/cli/src/commands/server/eventsSocket.ts

Co-authored-by: Michał Pierzchała <thymikee@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants