|
| 1 | +--- |
| 2 | +id: debugging |
| 3 | +title: "Debugging Reanimated" |
| 4 | +sidebar_label: "Debugging Reanimated" |
| 5 | +--- |
| 6 | + |
| 7 | +import { |
| 8 | + SummaryTable, |
| 9 | + ChromeDebuggerTable, |
| 10 | + ChromeDevToolsTable, |
| 11 | + FlipperTable, |
| 12 | + SafariDevToolsTable, |
| 13 | + ReactDeveloperToolsTable, |
| 14 | +} from './debugging_tables/tables'; |
| 15 | + |
| 16 | +Due to Reanimated's unique architecture and usage of a second JS runtime, debugging |
| 17 | +can be problematic, and some common solutions might not work as expected. |
| 18 | +This article summarizes all the available methods and highlights their caveats. |
| 19 | + |
| 20 | +:::info |
| 21 | + |
| 22 | +Reanimated v1 works with all the common React Native debugging tools. This |
| 23 | +article focuses on the use of these tools with Reanimated v2. |
| 24 | + |
| 25 | +::: |
| 26 | + |
| 27 | +### React Native debugging tools |
| 28 | + |
| 29 | +These are the debugging tools we checked for compatibility with React Native |
| 30 | +apps using the Reanimated library: |
| 31 | + |
| 32 | +- [**Chrome debugger**](https://reactnative.dev/docs/debugging#chrome-developer-tools) |
| 33 | +(also known as the _React Native Debugger_) is a simple tool that creates a web |
| 34 | +worker inside your preferred browser which executes your app's JavaScript code. It works |
| 35 | +with all the runtimes available in React Native. |
| 36 | + |
| 37 | +- [**Chrome DevTools**](https://reactnative.dev/docs/hermes#debugging-js-on-hermes-using-google-chromes-devtools) |
| 38 | +(unavailable for JSC) is Chrome's built-in feature that allows for connecting to a |
| 39 | +remote JavaScript runtime. This means that the code you are debugging actually |
| 40 | +runs on the device itself and behaves the same way as it would with DevTools detached. |
| 41 | + |
| 42 | +- [**Flipper**](https://fbflipper.com/) (Hermes debugger) is an app created by |
| 43 | +Facebook that makes it easy to use the _Chrome DevTools_ while providing additional tools for |
| 44 | +UI inspection and debugging. |
| 45 | + |
| 46 | +- [**Safari DevTools**](https://reactnative.dev/docs/debugging#safari-developer-tools) |
| 47 | +is Safari's built-in feature that is only available for iOS devices running JSC. It works |
| 48 | +very similarly to Chrome DevTools - it allows you to connect to a remote runtime |
| 49 | +and keep code execution on device. |
| 50 | + |
| 51 | +- [**React Developer Tools**](https://reactnative.dev/docs/debugging#react-developer-tools) |
| 52 | +are a standalone app that allows debugging UI through the inspector, as well as monitoring |
| 53 | +performance and profiling your app. |
| 54 | + |
| 55 | +### The JS context vs. the UI context |
| 56 | + |
| 57 | +It is important to understand the differences between the JS and UI contexts. |
| 58 | +One thing to note is that adding Reanimated changes nothing when it comes |
| 59 | +to debugging the regular JS context that is available in all React Native apps. |
| 60 | +It is only debugging the UI context, which is specific to the Reanimated |
| 61 | +library that might be difficult to debug in some scenarios, which are all |
| 62 | +explained in this article. |
| 63 | + |
| 64 | +You can read more about Reanimated's architecture [here](../fundamentals/architecture). |
| 65 | + |
| 66 | +### Debugging web apps |
| 67 | + |
| 68 | +For debugging web apps, you may use the tools you prefer or any that are provided |
| 69 | +by the browser of your choice. We did not discover any issues with debugging |
| 70 | +apps using Reanimated on web. |
| 71 | + |
| 72 | +### Summary |
| 73 | + |
| 74 | +<SummaryTable /> |
| 75 | + |
| 76 | +:::caution |
| 77 | + |
| 78 | +Remember that console logs will always appear in the primary JS runtime as the |
| 79 | +`console.log` function on the UI runtime is just a wrapper around the one from |
| 80 | +the JS runtime. |
| 81 | + |
| 82 | +::: |
| 83 | + |
| 84 | +### Chrome Debugger |
| 85 | + |
| 86 | +<ChromeDebuggerTable /> |
| 87 | + |
| 88 | +**Summary:** |
| 89 | +Works, but uses web implementations of functions and runs everything on the JS thread. |
| 90 | + |
| 91 | +Since the Chrome Debugger runs its own web worker, all the code is run on |
| 92 | +the JS thread, and it uses the JavaScript engine provided by your web |
| 93 | +browser (V8 in Chrome, JSC in Safari and SpiderMonkey in Firefox). This |
| 94 | +means that this piece of code: |
| 95 | + |
| 96 | +```js |
| 97 | +function runWorklet() { |
| 98 | + 'worklet'; |
| 99 | + console.log('worklet:', _WORKLET); |
| 100 | +} |
| 101 | +runOnUI(runWorklet)(); |
| 102 | +``` |
| 103 | + |
| 104 | +would output: |
| 105 | + |
| 106 | +``` |
| 107 | +LOG: worklet: false |
| 108 | +``` |
| 109 | + |
| 110 | +Another side effect is that Reanimated uses web implementations of all |
| 111 | +functions. This means that the `scrollTo` function will work |
| 112 | +(using the native web implementation), but the `measure` |
| 113 | +function will not be available, and its usage will trigger this error: |
| 114 | + |
| 115 | +``` |
| 116 | +[Reanimated] measure() cannot be used for web or Chrome Debugger |
| 117 | +``` |
| 118 | + |
| 119 | +You may still use the standard web version of `measure` as described |
| 120 | +[here](../api/nativeMethods/measure). |
| 121 | + |
| 122 | +Those functions that are provided by Reanimated and do not have web |
| 123 | +implementations won't work at all. |
| 124 | +An example of this behavior is the `useAnimatedSensor` hook, |
| 125 | +which currently only works on mobile platforms. When debugging in Chrome and using |
| 126 | +this hook, the following message will appear in the logs: |
| 127 | + |
| 128 | +``` |
| 129 | +[Reanimated] useAnimatedSensor is not available on web yet. |
| 130 | +``` |
| 131 | + |
| 132 | +But despite all of this, it is still possible to set breakpoints both in |
| 133 | +normal JS code and in worklets (since they run on the main JS |
| 134 | +thread now). |
| 135 | + |
| 136 | +### Chrome DevTools |
| 137 | + |
| 138 | +<ChromeDevToolsTable /> |
| 139 | + |
| 140 | +**Summary:** |
| 141 | +Works and both contexts can be debugged. |
| 142 | + |
| 143 | +:::warning |
| 144 | + |
| 145 | +This is an early experimental feature. |
| 146 | + |
| 147 | +::: |
| 148 | + |
| 149 | +Worklet debugging is now available in Reanimated apps as an early experimental |
| 150 | +feature. We do not recommend using Chrome DevTools to debug the UI context, but |
| 151 | +instead try using the Flipper tool. It has fewer bugs and provides a much better |
| 152 | +experience. |
| 153 | + |
| 154 | +If you still want to use Chrome DevTools then follow these steps: |
| 155 | + |
| 156 | +1. Add the `patch-package` to your project and set it up to run as a `post-install` task. |
| 157 | +More details can be found [here](https://www.npmjs.com/package/patch-package). |
| 158 | + |
| 159 | +2. Add the necessary patches to the `patches/` folder: |
| 160 | + |
| 161 | +- [this](/content/metro-inspector-proxy+0.72.1.patch) patch for `metro-inspector-proxy`, |
| 162 | +- [this](/content/react-native-gesture-handler+2.5.0.patch) one for `react-native-gesture-handler` |
| 163 | +(not necessary for `react-native-gesture-handler` 2.7.0 or newer). |
| 164 | + |
| 165 | +*Warnings about mismatched patch versions can be safely ignored if the patch was successfully applied.* |
| 166 | + |
| 167 | +3. Open [chrome://inspect](chrome://inspect) in a Google Chrome browser. |
| 168 | + |
| 169 | +4. Select the Reanimated runtime from the list. The list should look something |
| 170 | +like this: |
| 171 | + |
| 172 | + |
| 173 | + |
| 174 | +You may choose either `Reanimated Runtime` or `Reanimated Runtime experimental |
| 175 | +(Improved Chrome Reloads)`, but we recommend the latter. |
| 176 | + |
| 177 | +_Debugging relies on source maps that are generated by the Reanimated Babel plugin, so you |
| 178 | +might have to run `yarn start --reset-cache` for those changes to take effect. |
| 179 | +In case it still doesn't work after that please reinstall the app and reset metro |
| 180 | +cache once again._ |
| 181 | + |
| 182 | +:::caution |
| 183 | + |
| 184 | +Known issues include: |
| 185 | + |
| 186 | +- Reloads don't work - if a debugger is connected to the Reanimated runtime while |
| 187 | +the reload is performed, the app will crash (both on Android and iOS) |
| 188 | + |
| 189 | +- On iOS, a breakpoint can't be set in a line where a breakpoint was previously |
| 190 | +set and then removed |
| 191 | + |
| 192 | +- On iOS, breakpoint labels are not visible |
| 193 | + |
| 194 | +- The profiler does not work (it is not possible to stop the recording) - this is an issue with Hermes and is not related |
| 195 | +to Reanimated and has been already fixed in this [PR](https://github.com/facebook/react-native/pull/34129) |
| 196 | + |
| 197 | +- The console is unresponsive if there are no animations running (this will be fixed in the near future) |
| 198 | + |
| 199 | +These issues **do not** affect release builds as well as debug builds where the debugger connection |
| 200 | +is closed while performing a reload or the debugger is not used at all. |
| 201 | + |
| 202 | +::: |
| 203 | + |
| 204 | +*We are actively working on improving the debugging experience with Chrome DevTools on Hermes.* |
| 205 | + |
| 206 | +### Flipper (Hermes debugger) |
| 207 | + |
| 208 | +<FlipperTable /> |
| 209 | + |
| 210 | +**Summary:** |
| 211 | +Works and both contexts can be debugged. |
| 212 | + |
| 213 | +:::warning |
| 214 | + |
| 215 | +This is an early experimental feature. |
| 216 | + |
| 217 | +::: |
| 218 | + |
| 219 | +Worklet debugging is now available in Reanimated apps as an early experimental |
| 220 | +feature. If you want to try it out follow these steps: |
| 221 | + |
| 222 | +1. Add the `patch-package` to your project and set it up to run as a `post-install` task. |
| 223 | +More details can be found [here](https://www.npmjs.com/package/patch-package); |
| 224 | + |
| 225 | +2. Add the necessary patches to the `patches/` folder: |
| 226 | + |
| 227 | +- [this](/content/metro-inspector-proxy+0.72.1.patch) patch for `metro-inspector-proxy`, |
| 228 | +- [this](/content/react-native-gesture-handler+2.5.0.patch) one for `react-native-gesture-handler` |
| 229 | +(not necessary for `react-native-gesture-handler` 2.7.0 or newer). |
| 230 | + |
| 231 | +*Warnings about mismatched patch versions can be safely ignored if the patch was successfully applied.* |
| 232 | + |
| 233 | +3. Install the `reanimated` plugin in Flipper. |
| 234 | + |
| 235 | + |
| 236 | + |
| 237 | + |
| 238 | +4. Select the plugin from the side menu (it might be disabled) and you should |
| 239 | +be good to go! |
| 240 | + |
| 241 | + |
| 242 | + |
| 243 | +_Debugging relies on source maps that are generated by the Reanimated Babel plugin, so you |
| 244 | +might have to run `yarn start --reset-cache` for those changes to take effect. |
| 245 | +In case it still doesn't work after that please reinstall the app and reset metro |
| 246 | +cache once again._ |
| 247 | + |
| 248 | +:::caution |
| 249 | + |
| 250 | +Known issues include: |
| 251 | + |
| 252 | +- Reloads don't work - if a debugger is connected to the Reanimated runtime while |
| 253 | +the reload is performed, the app will crash (both on Android and iOS) |
| 254 | + |
| 255 | +- Breakpoints might not be active after a reload even though they look as if they |
| 256 | +were |
| 257 | + |
| 258 | +- Android app crashes after the Flipper client is closed and will crash on startup |
| 259 | +after that. This is a known Flipper issue ([link](https://github.com/facebook/flipper/issues/3026)) |
| 260 | +and is not related to Reanimated. |
| 261 | + |
| 262 | +- The profiler does not work (it is not possible to stop the recording) - this is an issue with Hermes and is not related |
| 263 | +to Reanimated and has been already fixed in this [PR](https://github.com/facebook/react-native/pull/34129) |
| 264 | + |
| 265 | +- The console is unresponsive if there are no animations running (this will be fixed in the near future) |
| 266 | + |
| 267 | +These issues **do not** affect release builds as well as debug builds where the debugger connection |
| 268 | +is closed while performing a reload or the debugger is not used at all. |
| 269 | + |
| 270 | +::: |
| 271 | + |
| 272 | +*We are actively working on improving the debugging experience with Flipper on Hermes.* |
| 273 | + |
| 274 | +### Safari DevTools |
| 275 | + |
| 276 | +<SafariDevToolsTable /> |
| 277 | + |
| 278 | +**Summary:** |
| 279 | +Safari DevTools is only available on iOS devices running the JSC engine. |
| 280 | +Worklet debugging is available. |
| 281 | + |
| 282 | +After opening Safari and configuring it as specified in the React Native |
| 283 | +docs, under `Develop > Device` you'll see two JSC contexts |
| 284 | +like in the screenshot below: |
| 285 | + |
| 286 | + |
| 287 | + |
| 288 | +The order of the contexts is random, but one of them will be the main JS context. |
| 289 | +All `console.log` outputs will appear in the console of this context. You can also |
| 290 | +set breakpoints here, but unfortunately the only source file visible is the |
| 291 | +transformed `indexjs.bundle` which does make things more difficult to find. |
| 292 | + |
| 293 | +The other option will be the UI context. No console logs will appear in |
| 294 | +the console of this context, but all worklet functions should be visible |
| 295 | +as separate files. It is also possible to set breakpoints in these |
| 296 | +worklets. |
| 297 | + |
| 298 | +### React Developer Tools |
| 299 | + |
| 300 | +<ReactDeveloperToolsTable /> |
| 301 | + |
| 302 | +**Summary:** |
| 303 | +React Developer Tools work as expected, and the profiler and layout inspector can |
| 304 | +be used as usual. |
| 305 | + |
| 306 | +On Android, remember to first run the command: |
| 307 | +``` |
| 308 | +adb reverse tcp:8097 tcp:8097 |
| 309 | +``` |
0 commit comments