Cuando usamos react-native 0.59.10 y configuramos la configuración regional para momentJS, detectamos un bloqueo súper brutal solo para nuestras compilaciones de lanzamiento. Este bloqueo no fue reproducible para nosotros con el depurador adjunto. Este bloqueo ocurrió para nosotros tanto en iOS como en Android. ¡Las declaraciones try-catch que envuelven todo el uso del momento no detectaron el bloqueo!
Reproducir
["fr-CA", "en-US", "fr", "en"]
moment.locale(localeCandidate)
dentro de un bloque try-catch, la aplicación sigue fallando en esta línea⁇¡Este fue un bloqueo en el lanzamiento, pero solo para las versiones de lanzamiento! Esto hizo que fuera muy complicado extraer mensajes de error/registro útiles.
Vimos los siguientes mensajes de error a través de nuestra integración de Bugsnag y registro de la consola del sistema
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".
, pero curiosamente, este error no se procesó de manera oportuna. Posiblemente un problema de react-native/bugsnag.Solución alternativa: ¡ Comentar esas dos líneas detuvo el bloqueo!
Comportamientos esperados
require()
en Release)Teléfono inteligente (por favor complete la siguiente información):
Entorno específico del momento
Ejecute el siguiente código en su entorno e incluya el resultado:
console.log([
new Date().toString(),
new Date().toLocaleString(),
new Date().getTimezoneOffset(),
navigator && navigator.userAgent, // react-native might not have a navigator
moment.version,
]);
Producción:
[
"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"
]
Contexto adicional
Las líneas a las que se hace referencia intentan "automáticamente" requerir módulos en tiempo de ejecución, pero los documentos de carga de locales indican que si está utilizando un Administrador de paquetes como JSPM, puede cargar locales por import "moment/locale/fr
. Dado que necesitamos el administrador de paquetes nativo de reacción para "saber" que el archivo debe importarse, probamos ese estilo de importación para que Packager pueda "ver" todos los archivos que deben incluirse.
En última instancia, nuestras líneas de importación se veían así:
import moment from "moment";
import "moment/min/locales"; // Import all moment-locales -- it's just 400kb
import "moment-timezone";
La implementación exacta de require()
es inyectada por el tiempo de ejecución con el que está trabajando, y eso es definitivamente algo que se comporta de manera significativamente diferente entre las compilaciones de depuración y lanzamiento.
En react-native, también hay varios tipos diferentes de paquetes de JavaScript en modo de lanzamiento, que incluyen todo en un archivo, todo en archivos separados y paquetes de RAM. Cada uno de estos también cambia cómo funciona require. La depuración require()
conecta al Metro Bundler que se ejecuta en un servidor http local. Es probable que esto sea muy similar a webpack/jspm/otros servidores de depuración, por lo que probablemente la necesidad de alias no causa problemas en ese entorno.
A. ¿Eliminar aliasedRequire
completo si ya no es así como se supone que debe hacer las cosas + ajustar las instrucciones de instalación al respecto?
B. Detectar react-native vs browser ( navigator
no está disponible en react-native, pero hay otras técnicas aquí) y comportarse de manera diferente según la situación en la que nos encontremos. p.ej. si es nativo de reacción && DEV, imprima un error de consola si la configuración regional es teóricamente compatible, pero aún no ha sido required
(+ documentos de actualización).
C. Mueva el aliasedRequire
de una variable local en esa función a un "semi-global". moment.aliasedRequire
, de esa manera podríamos inyectar una función de no operación/no hacer nada para que aliasedRequire
ya no pueda causar que react-native se bloquee con fuerza.
Estaría feliz de implementar cualquiera de estas opciones si un mantenedor puede indicarme cuál les gustaría que implementara, y para las Propuestas B/C, ¡ayúdenme a refinar qué implementación exacta estarían inclinados a aceptar!
@marwahaha : no estoy seguro de cuál es el proceso para Moment. ¿Tendrías una opinión sobre mis propuestas de corrección? Estaría feliz de implementar un PR una vez que obtenga algunos consejos sobre qué ruta podría ser aceptable para los contribuyentes/mantenedores.
Comentario más útil
Las líneas a las que se hace referencia intentan "automáticamente" requerir módulos en tiempo de ejecución, pero los documentos de carga de locales indican que si está utilizando un Administrador de paquetes como JSPM, puede cargar locales por
import "moment/locale/fr
. Dado que necesitamos el administrador de paquetes nativo de reacción para "saber" que el archivo debe importarse, probamos ese estilo de importación para que Packager pueda "ver" todos los archivos que deben incluirse.En última instancia, nuestras líneas de importación se veían así:
La implementación exacta de
require()
es inyectada por el tiempo de ejecución con el que está trabajando, y eso es definitivamente algo que se comporta de manera significativamente diferente entre las compilaciones de depuración y lanzamiento.En react-native, también hay varios tipos diferentes de paquetes de JavaScript en modo de lanzamiento, que incluyen todo en un archivo, todo en archivos separados y paquetes de RAM. Cada uno de estos también cambia cómo funciona require. La depuración
require()
conecta al Metro Bundler que se ejecuta en un servidor http local. Es probable que esto sea muy similar a webpack/jspm/otros servidores de depuración, por lo que probablemente la necesidad de alias no causa problemas en ese entorno.