The above image is a crash report of a react native app on New Relic which is not really readable. However, it contains some useful information such as
- call .map() on an undefined object
- the last stack is in line 1856 and column 3113
Nevertheless, the two pieces of information are still too vague to find where is the crash since .map() can be used more than a hundred times in a project and line 1856 and column 3113 is a kind of magic number.
A Primitive Approach
Actually, line 1856 and column 3113 is the crash that happened in the minified and compiled file. We can unzip the apk or ipa file, you can find the minified and compiled file in these places.
- for iOS, it is on
Payload/[App Name].app/main.jsbundleof ipa
- for Android, it is on
Source Map Approach
By default, React Native has different behaviors of generating source map for iOS and Android.
- for iOS, React Native won’t generate the source map(at least I cannot find it).
- for Android, it is on
You can pass
--sourcemap-output to change the output path. If your project uses CI/CD to build and distribute the app, it is recommended to include the source map files to artifacts because the source map of each build will be different, we cannot use a source map of A build for the app of B build.
- for iOS, go to build phases in Xcode on “Bundle React Native code and images” and add the following line shown as the below image. The source map will be output on
export EXTRA_PACKAGER_ARGS="--sourcemap-output main.jsbundle.map"
- for Andorid, add the following line inside project.ext.react in
./android/app/build.gradleshown as the below image. The source map will be output on
extraPackagerArgs: ["--sourcemap-output", file("$buildDir/index.android.bundle.map")]
However, the output path is for the demo purpose, you should change to the right place for your needs, for example the folder for CI/CD upload.
Source Map Lookup
I cannot find a GUI tool that can load the source map of react native successfully. Eventually, I created a very simple source-map-lookup library to wrap mozilla/source-map. Use this command to install source-map-lookup.
npm install -g https://github.com/weironghuang31/source-map-lookup
Then you can run this command to find the crash place of the original file.
In order to make a better interpretation, I created a demo app to show you the process.
- Create a demo app and add CrashButton.js which will cause a crash when you click the button.
.\gradlew installRelease to build an Release app and install it on an android device.
3. Click the button to cause crash and find the crash on logcat. And know the crash is taking place at line 415 and column 189.
4. Try the primivite approach, open the
index.android.bundle, go to line 415, copy the line, paste it on a new file and format it. Although, it is still not easy to figure out which file, but we have a clue that a file includes “Touch me”.
5. Try source-map-lookup with the source map and the line and the column of the crash in a terminal. Then source-map-lookup prints the original file path, line and column.
This my approach of inspecting react native crash. There might be a better method, however, the approach really helps me a lot. I hope it can help you as well.