House
/
Blog
/
The Current State of Debugging on React Native - Part One: EXPO
React Native

The Current State of Debugging on React Native - Part One: EXPO

Turbo modules broke remote debugging for React Native on all JavaScript. Until now you might have not been impacted by this if you don't use a native module that leverages Turbo Module's JSI features like react-native-reanimated. Moving forward with the new Fabric architecture everyone will be impacted.

The Current State of Debugging on React Native - Part One: EXPO

Moving forward the React Native community will need to find ways to debug the running JavaScript directly on the device itself instead of connecting to a remotely instantiated JavaScript engine like it used to be done with Chrome. A discussion was started a while back about this subject.

For those unaware of the difference between remote and direct JS debugging. The way Enable JS Debugger used to work is by connecting your app to Chrome's browser JavaScript. In the past for instance, this resulted in different behaviors since Chrome by default uses the V8 JS engine while React Native with iOS used JavaScriptCore and Android could use Hermes or any other JS engine.

Trying With Expo

By default for instance on Expo@v47.0.3 if you generate an app and try to open the dev menu this is the message you see:

And even with Hermes enabled, Expo does a nice job opening Chrome DevTools for you but while you can see logs and inspect the code source you can't profile performance.

Message you get from Performance tab when you try to run a profiler

According to Expo docs you could enable React Native Debugger with a few extra steps and have access to its network tab but that didn't seem to work with Expo@v47.0.3 - I was never able to connect to React Native Debugger. 

Using chrome://inspect

Then I tried chrome://inspect on Android

On Expo on you inspect JS via chrome://inspect if you forward the localhost:19000 

This also didn't work, I can see console logs but I can't inspect Network nor Profile the app.

What About V8?

Next I thought I would try a different JS engine with Expo since I knew react-native-v8 has done some extra work to implement Chrome's debugging protocols. 

Another interesting point was how the open debugger option on the Expo CLI did not work with V8, and I was only able to inspect the running JS by opening the developer menu and choosing the Start Remote Debugging option which opened Chrome for me.

With V8 I was able to get logs and run the performance tab, although this time chrome://inspect didn't find the running JS engine for me to inspect it - I could be doing something wrong with the ports forwarding section.

And Flipper?

Up to this point our debug experience is still incomplete. You can get logs and step through code with Expo and Hermes but you can't profile nor see Network logs. And with react-native-v8 you can get logs, step through, and profile but you don't get Network logs.

In its documentation it did mention that you would be able to inspect Network tabs with React Native Debugger but as you noted above we couldn't find a way to figure that out.

Lastly, we know we could use Flipper’s network extension. But Expo doesn’t come with Flipper installed in its default template. After following Expo's documentation on enabling Flipper. Side note, I had to create an Expo account to use their Expo Application Service and make a developer build for Android to finally build Android with the Flipper native module then install the APK locally which allowed me to run Expo dev.

This took a while, I guess you could pay to increase the concurrency limit.

Flipper + React Native V8

Finally, I was able to see Network logs on Flipper, on this attempt I was using react-native-v8. 

Flipper's Network Tab working with React Native V8
Flipper's Hermes Debugger Tab working with React Native V8

The above was a pleasant surprise - I was not expecting to see Hermes Debugger's tab work with react-native-v8.

Flipper + Hermes

Next I also made sure to test the Flipper plugin with Hermes. Interesting note, when using react-native-v8 your JavaScript logs on Android are under ReactNativeJS tag and on Hermes they are on client_log. This is important to know if you want to filter out only for these logs either using Flipper's tag filter or adb's "-s" flag. 

Using Flipper's Hermes Debugger panel we were also able to profile the app:

Hermes Debugger Profile Tab

Rant: Flipper Network Plugin's Shortcoming

Flipper's Network plugin lacks a network waterfall view similar to Chrome's. This for me has been the second feature I use the most in Chrome's network tab after simple request inspection. Over the years, while fine tuning apps for performance, one thing that has come up over and over is the latency implications caused by a network request waterfall. Without this feature, finding this undesired behavior of network waterfall becomes much harder. 

Concluding Debugging with Expo

In order to fulfill all debugging requirements that include the ability to: log; inspect code source and step-through with breakpoints; take memory snapshots; profile CPU; and inspect Network, you have to use Expo's EAS service to create a development build and enable the ability to use Flipper else you will find yourself with a limited debugging experience.

Note, Expo 47 will be shipped with support for the Hermes inspector allowing you profile, snapshot memory, and use that integrated Chrome inspector that comes with Flipper. This means it will only miss a proper way to inspect the Network.

Next: Trying with Bare React Native

Next post we will explore how using a Bare React Native Template without Expo differ's in the development experience.

House
/
Blog
/
React Native

The Current State of Debugging on React Native - Part One: EXPO

/
The Current State of Debugging on React Native - Part One: EXPO
Turbo modules broke remote debugging for React Native on all JavaScript. Until now you might have not been impacted by this if you don't use a native module that leverages Turbo Module's JSI features like react-native-reanimated. Moving forward with the new Fabric architecture everyone will be impacted.

Moving forward the React Native community will need to find ways to debug the running JavaScript directly on the device itself instead of connecting to a remotely instantiated JavaScript engine like it used to be done with Chrome. A discussion was started a while back about this subject.

For those unaware of the difference between remote and direct JS debugging. The way Enable JS Debugger used to work is by connecting your app to Chrome's browser JavaScript. In the past for instance, this resulted in different behaviors since Chrome by default uses the V8 JS engine while React Native with iOS used JavaScriptCore and Android could use Hermes or any other JS engine.

Trying With Expo

By default for instance on Expo@v47.0.3 if you generate an app and try to open the dev menu this is the message you see:

And even with Hermes enabled, Expo does a nice job opening Chrome DevTools for you but while you can see logs and inspect the code source you can't profile performance.

Message you get from Performance tab when you try to run a profiler

According to Expo docs you could enable React Native Debugger with a few extra steps and have access to its network tab but that didn't seem to work with Expo@v47.0.3 - I was never able to connect to React Native Debugger. 

Using chrome://inspect

Then I tried chrome://inspect on Android

On Expo on you inspect JS via chrome://inspect if you forward the localhost:19000 

This also didn't work, I can see console logs but I can't inspect Network nor Profile the app.

What About V8?

Next I thought I would try a different JS engine with Expo since I knew react-native-v8 has done some extra work to implement Chrome's debugging protocols. 

Another interesting point was how the open debugger option on the Expo CLI did not work with V8, and I was only able to inspect the running JS by opening the developer menu and choosing the Start Remote Debugging option which opened Chrome for me.

With V8 I was able to get logs and run the performance tab, although this time chrome://inspect didn't find the running JS engine for me to inspect it - I could be doing something wrong with the ports forwarding section.

And Flipper?

Up to this point our debug experience is still incomplete. You can get logs and step through code with Expo and Hermes but you can't profile nor see Network logs. And with react-native-v8 you can get logs, step through, and profile but you don't get Network logs.

In its documentation it did mention that you would be able to inspect Network tabs with React Native Debugger but as you noted above we couldn't find a way to figure that out.

Lastly, we know we could use Flipper’s network extension. But Expo doesn’t come with Flipper installed in its default template. After following Expo's documentation on enabling Flipper. Side note, I had to create an Expo account to use their Expo Application Service and make a developer build for Android to finally build Android with the Flipper native module then install the APK locally which allowed me to run Expo dev.

This took a while, I guess you could pay to increase the concurrency limit.

Flipper + React Native V8

Finally, I was able to see Network logs on Flipper, on this attempt I was using react-native-v8. 

Flipper's Network Tab working with React Native V8
Flipper's Hermes Debugger Tab working with React Native V8

The above was a pleasant surprise - I was not expecting to see Hermes Debugger's tab work with react-native-v8.

Flipper + Hermes

Next I also made sure to test the Flipper plugin with Hermes. Interesting note, when using react-native-v8 your JavaScript logs on Android are under ReactNativeJS tag and on Hermes they are on client_log. This is important to know if you want to filter out only for these logs either using Flipper's tag filter or adb's "-s" flag. 

Using Flipper's Hermes Debugger panel we were also able to profile the app:

Hermes Debugger Profile Tab

Rant: Flipper Network Plugin's Shortcoming

Flipper's Network plugin lacks a network waterfall view similar to Chrome's. This for me has been the second feature I use the most in Chrome's network tab after simple request inspection. Over the years, while fine tuning apps for performance, one thing that has come up over and over is the latency implications caused by a network request waterfall. Without this feature, finding this undesired behavior of network waterfall becomes much harder. 

Concluding Debugging with Expo

In order to fulfill all debugging requirements that include the ability to: log; inspect code source and step-through with breakpoints; take memory snapshots; profile CPU; and inspect Network, you have to use Expo's EAS service to create a development build and enable the ability to use Flipper else you will find yourself with a limited debugging experience.

Note, Expo 47 will be shipped with support for the Hermes inspector allowing you profile, snapshot memory, and use that integrated Chrome inspector that comes with Flipper. This means it will only miss a proper way to inspect the Network.

Next: Trying with Bare React Native

Next post we will explore how using a Bare React Native Template without Expo differ's in the development experience.

About the Author
React

Hire vetted remote developers today

Technology leaders rely on G2i to hire freelance software developers, find full-time engineers, and build entire teams.

Group

More from G2i