ReactNative 线上JS层错误统计解析

一、前言

开发APP,通常都会接入一些第三方的错误统计工具,例如友盟、bugly等,而这些第三方提供的SDK目前来看,只支持Native层的统计。对于ReactNative项目来说,反馈的错误日志无法直接看出具体错误信息,如下是友盟统计的错误日志

com.facebook.react.common.JavascriptException: TypeError: null is not an object (evaluating 't(i).name')

This error is located at:
    in P
    in RCTView
    in f
    in n
    in RCTView
    in RCTView
    in S
    in RCTView
    in h, stack:
getRegionTextArr@1091:751
value@1095:18200
pi@89:51757
Ml@89:70036
Ul@89:67144
Ul@-1
Pl@89:65839
Pl@-1
<unknown>@89:25495
unstable_runWithPriority@168:3915
sn@89:25442
cn@89:25377
_e@89:88686
Ne@89:13582
Ue@89:13755
receiveTouches@89:14547
value@24:3685
<unknown>@24:841
value@24:2939
value@24:813
value@-1

	at com.facebook.react.modules.core.ExceptionsManagerModule.reportException(ExceptionsManagerModule.java:71)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:371)
	at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:150)
	at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
	at android.os.Handler.handleCallback(Handler.java:873)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:26)
	at android.os.Looper.loop(Looper.java:224)
	at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:225)
	at java.lang.Thread.run(Thread.java:764)

这样的错误日志,可读性非常的差,虽然可以通过解压apk,查看assets/index.android.bundle的1091行751列找到报错位置,但是bundle中的代码已经被混淆了,很难找到代码中具体位置。

二、生成Mapping文件

ReactNative App 的打包,完全借助了react.gradle这个文件,你可以在 Android 工程的build.gradle文件中找到它。

继续最终 node/modules 下的 react.gradle 文件。

可以看到它实际上是通过 react-native bundle 命令,通过增加参数的形式,输出index.android.bundle 文件的。还可以添加一个可配置的参数 —sourcemap-output,指定生成一个对应关系的 map 文件。

在项目根目录下,执行命令:

react-native bundle  --platform android  --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/ --sourcemap-output android-release.bundle.map

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XkFqwDMu-1583829759059)(/Users/hxl/Library/Application Support/typora-user-images/image-20200310161159356.png)]

项目根目录下生成android-release.bundle.map文件

三、用source-map解析定位

在和map文件相同的目录下,新建一个js文件map.js,具体代码如下:

var sourceMap = require('source-map')
var fs = require('fs')

fs.readFile('./android-release.bundle.map', 'utf8', function (err, data) {
  var smc = new sourceMap.SourceMapConsumer(data)
  console.log(smc.originalPositionFor({
    line: 1091,
    column: 751
  }))
})

注意行号和列号与日志反馈的一致,使用终端命令行进入当前文件夹目录,执行node map.js,如下:

我们就拿到了错误日志中位置所对应的项目代码的具体位置,查看此处代码
在这里插入图片描述

结合友盟上的日志信息null is not an object (evaluating 't(i).name'),可以得知getProvince(provinceId)返回为null,由此便可以确定问题原因

发布了84 篇原创文章 · 获赞 159 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/hxl517116279/article/details/104777666