React Native 在生产中崩溃

Posted

技术标签:

【中文标题】React Native 在生产中崩溃【英文标题】:React Native crashing in production 【发布时间】:2016-11-21 19:30:50 【问题描述】:

我们使用 React Native 构建了一个应用程序,以改进我们之前的 Cordova 应用程序的用户体验和功能。

一切都很顺利。经过几个月的开发、QA、App 审查,然后我们发布到 App Store。它适用于我们尝试过的所有设备,从 iPhone 4s 到 iPhone 6s+,我们在 ios 8.3(您可以通过 xCode 下载的最早的模拟器)到 10.0 上进行了测试。

发布后,许多用户开始报告应用在启动画面消失之前就崩溃了。我们从未在应用审核、测试或其他任何地方看到过的行为。

我们调查了 xCode 中的“崩溃”,但它们显然没有出现,因为数百名用户经历了崩溃,而我们只能看到少数——这似乎与启动无关。

我们发布了一个集成了 Crashlytics 的更新版本,但这也无济于事。我们也没有收到针对此特定问题的 Crashlytics 错误,这意味着该问题可能发生在之前

我接下来应该去哪里看看有什么想法吗?我们真的不想恢复到旧版本并失去几个月的工作。

加载所有内容时,该应用程序使用大约 100MB 的内存,所以我认为这应该不是问题。它发生在所有设备的所有 iOS 版本上。我们不能只将错误隔离到特定用户。

【问题讨论】:

Crashlytics 是否为您提供了崩溃堆栈跟踪,还是您的崩溃没有得到任何回报?如果您根本看不到任何东西,那么它甚至可能在 Crashlytics 初始化发生之前就崩溃了。 这里缺少一些信息,我们需要这些信息来帮助您:首先,crashlytics 为您提供什么?其次,您能否隔离正在执行此操作的设备(这将是最重要的)。好消息是,一旦您获得执行此操作的设备,您通常可以在本地发布到设备并进行复制。一旦你有了上述,我觉得这个问题会很快得到解决。医生不能不看病人就治病。 必须在 Crashlytics 初始化之前发生崩溃。我无法隔离正在发生的设备。我会相应地更新问题。 如果您的 iOS 设备发生崩溃,请从该设备获取崩溃日志。否则,应用程序的链接可能会有所帮助,因此这里的某人可以测试并提供故障转储。一旦你有了它,使用你的应用程序调试符号来获得崩溃功能。 【参考方案1】:

当似乎没有任何其他分析途径时,我会求助于日志记录这一卑微的后备方式。

我以前在生产 iOS 应用程序中使用过以下技术。这是一项设置工作,但一旦完成,它将对未来的许多其他问题非常有用。不仅仅是崩溃,还有用户报告的任何其他您无法在测试环境中复制的奇怪行为。

    应用程序应该做的第一件事是检查上一次启动是否成功,方法是读取一些应该在上一次启动的开始和结束时写入默认值的值(详细信息在下一步中)。如果以前的启动不成功,请让用户选择以某种“安全模式”运行(这意味着什么取决于您的应用程序在启动时尝试执行的操作,但对我而言,这意味着不加载任何数据或执行除了显示没有任何数据相关项的 UI 之外的任何其他内容;对于某些应用程序,它甚至可以加载完全不同的 UI,其中仅包括诊断工具或数据删除/重置工具)。 在确定上一次启动正常(或者这是有史以来的第一次启动)后,应用程序应该做的下一件事是尽快将某种“startupBegan”状态写入默认值,然后再写入一些只有当它完全启动时才会出现“startupCompleted”状态(“完全启动”的意思是依赖于应用程序,但你真的想确定此时 UI 是完全响应的,并且正在显示它需要的所有内容; 这有时可能有点难以确定,因为有些事情直到启动画面消失后才会运行,等等;如果你找不到任何其他方式,我想你可以用计时器触发它,但那是相当丑陋 - 最好找到某种方法来确定启动何时真正完全完成)。这些值可用于确定启动是否已开始但未完成,并且是第 1 步(上文)用于确定上一次启动是否成功的值。 在应用程序中包含大量日志记录,并将日志写入文件。我认为您可以使用 3rd 方工具来执行此操作,但我编写了自己的方法(如下),如果在生产中运行且未连接到 XCode,则该方法只是将 stderr 重定向到文件。请注意,NSLog() 写入标准错误,而不是标准输出。 让应用能够通过电子邮件将日志文件发送到您的支持电子邮件地址 - 这必须在应用的“安全模式”(以及正常模式)下可用。在正常模式下,我将其设置得相当模糊,以便在一切正常时不会被用户注意到(例如,在“设置”或“关于”视图底部的按钮)。当用户提交我确实需要日志的支持请求时,我会告诉他们如何找到该按钮。 在每次启动时轮换日志,以防止它们占用过多空间,但一定要保持几次轮换,否则只会从“安全模式”启动中获取日志,这是无用的。

这方面的许多变化是可能的。包括仅在用户为其配置设置时才启用日志记录之类的内容。有时当用户报告特定问题时,您可能必须围绕特定代码区域添加大量日志记录,然后在问题解决后再次将其删除(如果您担心日志记录的性能/存储问题)。

对于我的(Objective-C)应用程序,包含我的代码以将启动状态写入默认值的位置如下(可能有更好的地方更适合您的应用程序):

“startupBegan”早在应用委托的application:didFinishLaunchingWithOptions: “startupCompleted”在视图控制器的 viewDidAppear 末尾(不是 viewWillAppear!这两个发送之间可能会出错)

PS。我的旧日志重定向和轮换方法是这样的(Objective-C):

- (void)logRedirectRotate 
    // If stderr not going to an XCode console (then running in production)
    if ( ! isatty(STDERR_FILENO) ) 
        // Rotate logs

        int rotationsCount = 3;
        NSMutableArray *logRotations = [NSMutableArray array];

        for ( int i = 0; i < rotationsCount; i++ ) 
            [logRotations addObject:[pathToLogsDir stringByAppendingPathComponent:[NSString stringWithFormat:@"appnameorbundleid.%d.log", i]]];
        

        [[NSFileManager defaultManager] removeItemAtPath:[logRotations lastObject] error:nil];

        for ( int i = rotationsCount - 1; i > 0; i-- ) 
            [[NSFileManager defaultManager] moveItemAtPath:[logRotations objectAtIndex:i - 1] toPath:[logRotations objectAtIndex:i] error:nil];
        

        //  Redirect stderr to current log file rotation
        freopen([[logRotations objectAtIndex:0] cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
    

【讨论】:

非常感谢您的建议。我开始实施,但在我完成之前我们就走上了正轨。我会给你赏金,因为我从你的回答中得到了一些对未来可能有帮助的好主意。谢谢! 嘿,谢谢!很高兴听到你解决了它。我很想知道实际发生了什么,所以阅读你自己的答案很有趣。【参考方案2】:

由于我们与用户之间的沟通不畅,问题花了很长时间才解决。应用实际上没有崩溃,只是没有启动(在某些用户看来也是如此)。

在我们发现这一点后,我们意识到其中一个事件没有触发(隐藏扩展启动画面的那个),这就是用户卡住的地方。我们使用的其中一个库没有正确处理错误情况,这使我们的工作变得更加困难。我很幸运在测试时进入了那个状态,我可以从那里继续。

我更新了代码来处理这种情况,现在问题已经解决了。

【讨论】:

我有这个问题。应该触发哪个事件?你是如何解决这个问题的?【参考方案3】:

我遇到了这个问题,我的情况可能非常具体,但无论如何我都会分享我的经验。

这里的重点是应用程序只会在生产环境中崩溃,因此它只会在生产环境中触发,从而导致构建混乱。在我们的例子中,罪魁祸首是进行缩小的React's dependencies 之一。

要带走的东西:

    密切关注依赖项的任何更新 使用崩溃日志

【讨论】:

以上是关于React Native 在生产中崩溃的主要内容,如果未能解决你的问题,请参考以下文章

google 登录崩溃 Apk(React Native)

React Native IOS App 在没有网络连接时崩溃

在我的 react-native 应用程序中的 Swift 中编译器生成的崩溃

facebook登录错误,react-native ios expo

react-native-reanimated iOS 崩溃

尝试连接到 react-native-debugger 或 Chrome 时崩溃