当使用 react-native 0.59.10 并为 momentJS 设置语言环境时,我们仅在发布版本中遇到了超级残酷的崩溃。 附加调试器后,我们无法重现此崩溃。 我们在 iOS 和 Android 上都发生了这种崩溃。 包装所有时刻使用的 try-catch 语句没有捕获崩溃!
重现
["fr-CA", "en-US", "fr", "en"]
moment.locale(localeCandidate)
,应用程序仍然在这一行崩溃⁇这是一个启动时崩溃,但仅适用于发布版本! 这使得提取有用的错误消息/日志变得非常棘手。
我们通过 Bugsnag 集成和系统控制台日志记录看到以下错误消息
Exception in HostFunction: Error loading module0from RAM Bundle: unspecified iostream_category error
Exception in HostFunction: Module not found: 0
Requiring unknown module "./locale/en-us".
——但奇怪的是,这个错误没有得到及时处理。 可能是 react-native / bugsnag 问题。解决方法:注释掉这两行可以阻止崩溃!
预期行为
require()
时可能是一个 react-native 问题)智能手机(请填写以下信息):
特定时刻的环境
请在您的环境中运行以下代码并包含输出:
console.log([
new Date().toString(),
new Date().toLocaleString(),
new Date().getTimezoneOffset(),
navigator && navigator.userAgent, // react-native might not have a navigator
moment.version,
]);
输出:
[
"Wed Oct 09 2019 18:52:16 GMT-0700 (PDT)",
"09/10/2019 à 18:52:16", // This particular device is configured as fr-FR
420,
null,
"2.24.0"
]
附加上下文
引用的行是“自动”尝试在运行时要求模块,但加载语言环境文档表明,如果您使用像 JSPM 这样的包管理器,则可以通过import "moment/locale/fr
加载语言环境。 由于我们需要 react-native 包管理器“知道”必须导入文件,因此我们尝试了这种导入方式,以便 Packager 可以“看到”所有必须捆绑的文件。
最终,我们的导入行看起来像这样:
import moment from "moment";
import "moment/min/locales"; // Import all moment-locales -- it's just 400kb
import "moment-timezone";
require()
的确切实现是由您正在使用的运行时注入的,这绝对是在 Debug 和 Release 构建之间的行为明显不同的东西。
在 react-native 中,还有几种不同风格的发布模式 JavaScript 捆绑包,包括多合一文件、多合一文件和 RAM 捆绑包。 这些中的每一个也改变了 require 的工作方式。 Debug require()
连接到在本地 http 服务器上运行的Metro Bundler 。 这可能与 webpack/jspm/other 调试服务器非常相似,这可能是别名 require 在该环境中不会导致问题的原因。
A. 完全删除aliasedRequire
如果这不是您应该再做的事情 + 调整有关它的安装说明?
B. 检测 react-native 与浏览器( navigator
在 react-native 中不可用,但这里还有其他技术),并根据我们所处的情况采取不同的行为? 例如。 如果 react-native && DEV 然后打印一个 console.error 如果理论上支持语言环境,但还没有required
(+更新文档)。
C. 将aliasedRequire
从该函数中的局部变量移动到“半全局”。 moment.aliasedRequire
,这样我们就可以注入一个 no-op/do-nothing 函数,这样aliasedRequire
就不会导致 react-native 崩溃了。
如果维护者可以向我指出他们希望我实施哪个选项,我将很乐意实施这些选项中的任何一个,并且对于提案 B/C 帮助我完善他们倾向于接受的确切实施!
@marwahaha - 不确定 Moment 的流程是什么。 您对我的修复建议有意见吗? 一旦我得到一些关于贡献者/维护者可以接受的路线的建议,我会很乐意实施 PR?
最有用的评论
引用的行是“自动”尝试在运行时要求模块,但加载语言环境文档表明,如果您使用像 JSPM 这样的包管理器,则可以通过
import "moment/locale/fr
加载语言环境。 由于我们需要 react-native 包管理器“知道”必须导入文件,因此我们尝试了这种导入方式,以便 Packager 可以“看到”所有必须捆绑的文件。最终,我们的导入行看起来像这样:
require()
的确切实现是由您正在使用的运行时注入的,这绝对是在 Debug 和 Release 构建之间的行为明显不同的东西。在 react-native 中,还有几种不同风格的发布模式 JavaScript 捆绑包,包括多合一文件、多合一文件和 RAM 捆绑包。 这些中的每一个也改变了 require 的工作方式。 Debug
require()
连接到在本地 http 服务器上运行的Metro Bundler 。 这可能与 webpack/jspm/other 调试服务器非常相似,这可能是别名 require 在该环境中不会导致问题的原因。