如何在 React Native 中为生产添加源映射?

IT技术 reactjs react-native source-maps
2021-04-12 08:41:42

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

致命异常:com.facebook.react.modules.core.JavascriptException:onSelect index.android.bundle:20:7148 onPress index.android.bundle:20:2435

但是解决问题对我来说并没有真正的帮助。我如何启用源映射以便我可以追踪问题所在?

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

4个回答

对于源映射,我是这样处理的:

在我的生产版本的 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
    }));
});

应使用上面示例输出中的行号和列号替换行和列。

如果您将源映射存储在某处,因为随着代码的变化,行号和列号会随着构建而变化,这显然最有效。但是,如果您可以使用您选择的源代码控制设置返回用于构建相关应用程序的提交,并使用命令的附加位重新生成包以生成源映射,它应该会非常接近。

啊,那会很有趣。我只是使用 Crashlytics 来记录错误,然后在调查错误时使用上述方法手动映射它。有一项自动完成的服务会很好,但我还没有看到。
2021-06-02 08:41:42
在 v0.32 上,添加 args 以生成源映射更简单。只需在该之前添加 project.ext.react = [ extraPackagerArgs: [ "--sourcemap-output", file("$buildDir/../../sourcemaps/sourcemap.js")] ] 即可android/app/build.gradleapply from:
2021-06-04 08:41:42
我输出的源映射返回错误的值。当我产生错误时,它会漏掉大约 10-20 行!有这方面的经验吗?@chetstone
2021-06-11 08:41:42
我也很想看到这个,出于某种原因,我不希望在短期内看到对此的支持添加到 Crashlytics。应该有人建造这个!
2021-06-12 08:41:42
我最终得到了与此类似的东西,并且正在寻找可以自动执行源映射的远程日志服务器。docs.getsentry.com/hosted/clients/javascript/integrations/...看起来很有趣。但没有设法让它工作。
2021-06-15 08:41:42

Android灵感来自@chetstone 的回答

从 v0.32 for android 开始,您可以修改您的 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"
sourcemap 文件不是我创建的。这有什么理由吗。
2021-05-28 08:41:42
react-native为它创建了一个问题,因为我似乎找不到其他人有这个问题:github.com/facebook/react-native/issues/24044
2021-06-05 08:41:42
我在 Android 上收到这些错误: FAILURE: Build failed with an exception. * What went wrong: Failed to capture fingerprint of input files for task ':cntral:bundleReleaseJsAndAssets' property '$1' during up-to-date check. > Failed to create MD5 hash for file '/Users/me/tmp/skylight-87084.sock' as it does not exist.
2021-06-07 08:41:42

如前所述,没有明显的方法可以sourcemap在 iOS 上为 React Native生成文件。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将创建该文件

你能提供更多细节吗?你把 null_config 文件放在哪里?它的内容究竟是什么?你在 Xcode 中设置了 env vars 吗?
2021-05-31 08:41:42

这仅适用于 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

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

$ 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
  }));
});

第三步:执行脚本进行解码

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