如何在React Native for Production中添加源映射



应用程序崩溃时,我收到了如下错误日志:

致命异常:com.facebook.react.modules.core.JavascriptException:on选择索引.android.bundle:20:7148 on按下index.android.捆绑包:20:2435

但这对我来说并没有什么帮助。如何启用源映射,以便跟踪问题所在?

更新2018https://docs.expo.io/versions/latest/guides/using-sentry.html看起来很有希望!

对于源映射,以下是我的方法:

在我的生产构建的bundle命令中,我告诉它生成一个源映射:

iOS:

react-native bundle --platform ios --entry-file index.ios.js --dev false --bundle-output ./ios/main.jsbundle --assets-dest ./ios --sourcemap-output ./sourcemap.js

Android-我不得不修改Android/app/react.gradle文件,以便在发布编译时生成源地图。可能有一种更简单的方法,但基本上你可以在bundleReleaseJsAndAssets方法中找到它构建bundle命令的位置,并向其中添加源映射位:

if (Os.isFamily(Os.FAMILY_WINDOWS)) {
    commandLine "cmd","/c", "react-native", "bundle", "--platform", "android", "--dev", "false", "--entry-file",
        entryFile, "--bundle-output", jsBundleFileRelease, "--assets-dest", resourcesDirRelease, "--sourcemap-output", file("$buildDir/../../../sourcemap.js")
} else {
    commandLine "react-native", "bundle", "--platform", "android", "--dev", "false", "--entry-file",
        entryFile, "--bundle-output", jsBundleFileRelease, "--assets-dest", resourcesDirRelease, "--sourcemap-output", file("$buildDir/../../../sourcemap.js")
}

输出路径看起来有点奇怪,但这会将它放在根级别(与iOS相同的位置。我希望它是这样的。很明显,你可以把它放在任何地方)。

然后,一旦行号出现错误,就可以通过"源映射"NPM包运行它。你可能会对你的方法做得很详细,但我只是选择了:

var sourceMap = require('source-map');
var fs = require('fs');
fs.readFile('./sourcemap.js', 'utf8', function (err, data) {
    var smc = new sourceMap.SourceMapConsumer(data);
    console.log(smc.originalPositionFor({
        line: 16,
        column: 29356
    }));
});

其中,行和列应替换为上面示例输出中的行和列编号。

如果您将源映射存储在某个位置,并且随着代码的变化,行号和列号在不同的构建中发生变化,那么这显然效果最佳。不过,如果你可以使用你选择的源代码管理设置返回到用于构建有问题的应用程序的提交,并使用生成源代码映射的命令的附加位重新生成捆绑包,那么它应该会非常接近。

Android灵感来自@chetstone的答案

从android的0.32版本开始,你可以修改你的android/app/build.gradle来实现这一点。寻找线路

apply from: "../../node_modules/react-native/react.gradle"

就在上面,你会看到这样的东西:

project.ext.react = [
    entryFile: "index.js",
]

修改它以匹配以下

project.ext.react = [
    entryFile: "index.js",
    extraPackagerArgs: ["--sourcemap-output", file("$buildDir/../../../sourcemap.android.js")]
]

在iOS上

进入Xcode中的构建阶段,进入"Bundle React Native code and images"阶段,并添加:

export EXTRA_PACKAGER_ARGS="--sourcemap-output sourcemap.ios.js"

如前所述,在iOS上没有明显的方法为React Native生成sourcemap文件。bundle命令是从react-native-xcode.sh调用的,并且没有向bundle命令行添加参数的规定。但我找到了一个干净的方法。

react-native-xcode.sh使用环境变量BUNDLE_CONFIG来指定配置文件。如果您创建了一个空的配置文件,它将无效,然后您可以添加其他CLI参数。

创建一个空的配置文件。

touch null_config

使用配置文件设置BUNDLE_CONFIG,并附带--sourcemap-output参数。

export BUNDLE_CONFIG="null_config --sourcemap-output ./sourcemap.js.map"

构建时,将创建文件sourcemap.js.map

这仅适用于iOS。

步骤1:使用以下命令生成sourcemap.js文件。

在package.json文件中添加此行

 "bundle:ios": "mkdir -p ios/{Bundle,source-map}; react-native bundle --platform ios --entry-file index.js --dev false --bundle-output ios/Bundle/main.jsbundle --assets-dest ios/Bundle --sourcemap-output ios/source-map/sourcemap.js" 

运行此命令,它将在$PROJECT_DIR/ios/source-map/文件夹下创建sourcemap.js文件

$ yarn bundle:ios

步骤2:在$PROJECT_DIR/ios/source-map/ 下创建一个文件sourcemap-decoder.js

$ cd ios/source-map/
$ touch sourcemap-decoder.js

sourcemap-decoder.js的内容是

const sourceMap = require('source-map'); //(install- npm i source-map)
const fs = require('fs');
const path = require('path');
fs.readFile(path.resolve(__dirname, 'sourcemap.js'), 'utf8', async (err, data) => {
  if (err) {
    console.log('err', err,);
  }
  const consumer = await new sourceMap.SourceMapConsumer(JSON.parse(data));
  console.log(consumer.originalPositionFor({
    line: 1408,
    column: 7762
  }));
});

步骤3:执行解码的脚本

$ node ios/source-map/sourcemap-decoder.js

最新更新