Moment: React-Native Rilis Build, Deep Crash saat mengubah lokal

Dibuat pada 10 Okt 2019  ·  4Komentar  ·  Sumber: moment/moment

Saat menggunakan react-native 0.59.10, dan menyetel lokal untuk momentJS, kami mengalami crash yang sangat brutal hanya untuk build-rilis kami. Kerusakan ini tidak dapat direproduksi untuk kami dengan debugger terpasang. Kerusakan ini terjadi pada kami berdua di iOS & Android. pernyataan try-catch yang membungkus semua penggunaan saat tidak menangkap kerusakan!

Untuk Mereproduksi

  1. Kami mengumpulkan lokal/bahasa yang ingin kami coba melalui logika khusus Aplikasi. Misal ["fr-CA", "en-US", "fr", "en"]
  2. Kami mengulangi ini, satu per satu daripada menggunakan penyetel Array, sehingga kami dapat memanggil beberapa instrumentasi lain, dan berpotensi menangkap Pengecualian JS apa pun yang dilemparkan dan mencoba kandidat berikutnya.
  3. Meskipun memanggil moment.locale(localeCandidate) di dalam blok coba-tangkap, Aplikasi masih macet di baris ini⁇

Ini adalah crash-on-launch tetapi hanya untuk rilis build!! Ini membuatnya sangat sulit untuk mengekstrak pesan kesalahan / logging yang berguna.

Kami melihat pesan kesalahan berikut melalui integrasi Bugsnag & Pencatatan Konsol Sistem kami

  • iOS: Exception in HostFunction: Error loading module0from RAM Bundle: unspecified iostream_category error
  • Android: Exception in HostFunction: Module not found: 0
  • Sehari kemudian, di iOS & Android kami juga melihat Requiring unknown module "./locale/en-us". -- tapi anehnya, kesalahan ini tidak diproses tepat waktu. Mungkin masalah reaksi-asli/bugsnag.
  1. Pelacakan akhirnya menemukan satu titik yang menyebabkan crash:
    https://github.com/moment/moment/blob/96d0d6791ab495859d09a868803d31a55c917de1/moment.js#L1852 -L1853
    Yang saya percaya berasal dari sini: https://github.com/moment/moment/blob/6a06e7a0db2c83fb92aa72bbf6bde955d4c75a16/src/lib/locale/locales.js#L55 -L56

Solusi: Mengomentari dua baris itu menghentikan crash!

Perilaku yang diharapkan

  • Momen seharusnya tidak berperilaku crashly, tetapi terutama tidak di rilis-build-only!
  • Pengecualian Momen harus dapat ditangkap (pernyataan tangkapan kami akan mencegah kerusakan). -- (bisa menjadi masalah reaksi asli saat bermain-main dengan require() dalam Rilis)

Smartphone (harap lengkapi informasi berikut):

  • Perangkat: iPhone X, iPhone 11 Pro, Samsung (? -- tidak menangkap apa persisnya), Google Pixel 3, (react-native 0.59.10)
  • OS: iOS dan Android
  • iOS JavaScript Core (untuk versi iOS yang disebutkan di bawah), dan jsc-android(+intl) 245459.0.0
  • Versi: iOS 12.4 & iOS 13.1, iOS 13.1.2, dan iOS 13.2 (beta?), Android 28, lainnya.

Lingkungan khusus momen

  • Waktu Pasifik, dan Mungkin Waktu London
  • Bug kode ditampilkan secara konsisten selama 2 minggu terakhir (2019-10-09) setiap saat sepanjang hari.
  • Pustaka lain yang digunakan: zona waktu-saat dan momen-dengan-lokal, TypeScript, reaksi-asli 0.59.10, Apollo-Client & lainnya

Silakan jalankan kode berikut di lingkungan Anda dan sertakan hasilnya:

        console.log([
            new Date().toString(),
            new Date().toLocaleString(),
            new Date().getTimezoneOffset(),
            navigator && navigator.userAgent, // react-native might not have a navigator
            moment.version,
        ]);

Keluaran:

[
  "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"
]

konteks tambahan

Tiket Terkait

  • #5214 - Berbeda karena ada lebih sedikit konteks di sini, dan menggunakan API yang berbeda dan mendapatkan Pesan Kesalahan yang berbeda. Mirip karena itu hanya terjadi di build rilis, yang menyarankan reaksi asli juga, tetapi mereka hanya mengulanginya di ios-simulator/ios.
  • #3872
  • #2979

Komentar yang paling membantu

Baris yang direferensikan "secara otomatis" mencoba meminta modul saat runtime, tetapi dokumen lokal pemuatan menunjukkan bahwa jika Anda menggunakan Manajer Paket seperti JSPM, Anda dapat memuat lokal dengan import "moment/locale/fr . Karena kita memerlukan manajer paket asli-reaksi untuk "mengetahui" bahwa file harus diimpor, kami mencoba gaya impor itu sehingga Packager dapat "melihat" semua file yang harus digabungkan.

Pada akhirnya, garis impor kami terlihat seperti ini:

import moment from "moment";
import "moment/min/locales"; // Import all moment-locales -- it's just 400kb
import "moment-timezone";

Implementasi yang tepat dari require() disuntikkan oleh runtime yang Anda kerjakan, dan itu pasti sesuatu yang berperilaku sangat berbeda antara build Debug & Rilis.

Dalam react-native, ada juga beberapa rasa berbeda dari Bundling JavaScript mode-rilis, termasuk all-in-one-file, all-in-separate-files, dan RAM Bundle. Masing-masing juga mengubah cara kerja require. Debug require() terhubung ke Metro Bundler yang berjalan di server http lokal. Ini mungkin sangat mirip dengan webpack/jspm/server debug lainnya, yang mungkin mengapa aliasing memerlukan tidak menyebabkan masalah di lingkungan itu.

Semua 4 komentar

Baris yang direferensikan "secara otomatis" mencoba meminta modul saat runtime, tetapi dokumen lokal pemuatan menunjukkan bahwa jika Anda menggunakan Manajer Paket seperti JSPM, Anda dapat memuat lokal dengan import "moment/locale/fr . Karena kita memerlukan manajer paket asli-reaksi untuk "mengetahui" bahwa file harus diimpor, kami mencoba gaya impor itu sehingga Packager dapat "melihat" semua file yang harus digabungkan.

Pada akhirnya, garis impor kami terlihat seperti ini:

import moment from "moment";
import "moment/min/locales"; // Import all moment-locales -- it's just 400kb
import "moment-timezone";

Implementasi yang tepat dari require() disuntikkan oleh runtime yang Anda kerjakan, dan itu pasti sesuatu yang berperilaku sangat berbeda antara build Debug & Rilis.

Dalam react-native, ada juga beberapa rasa berbeda dari Bundling JavaScript mode-rilis, termasuk all-in-one-file, all-in-separate-files, dan RAM Bundle. Masing-masing juga mengubah cara kerja require. Debug require() terhubung ke Metro Bundler yang berjalan di server http lokal. Ini mungkin sangat mirip dengan webpack/jspm/server debug lainnya, yang mungkin mengapa aliasing memerlukan tidak menyebabkan masalah di lingkungan itu.

Proposal Perbaikan Saya:

A. Hapus aliasedRequire seluruhnya jika bukan itu yang seharusnya Anda lakukan lagi + tweak instruksi instalasi tentangnya?
B. Deteksi react-native vs browser ( navigator tidak tersedia di react-native, tetapi ada teknik lain di sini), dan berperilaku berbeda tergantung pada situasi yang kita hadapi? misalnya. jika reaksi asli && DEV maka cetak console.error jika lokal secara teoritis didukung, tetapi belum required (+ perbarui dokumen).
C. Pindahkan aliasedRequire dari variabel lokal dalam fungsi tersebut ke "semi-global". moment.aliasedRequire , dengan begitu kita bisa menyuntikkan fungsi no-op/do-nothing sehingga aliasedRequire tidak dapat menyebabkan react-native crash lagi.

Saya akan dengan senang hati menerapkan salah satu opsi ini jika pengelola dapat mengarahkan saya ke mana yang mereka ingin saya terapkan, dan untuk Proposal B/C bantu saya memperbaiki implementasi tepat mana yang cenderung mereka terima!

@marwahaha -- tidak yakin apa proses untuk Momen. Apakah Anda memiliki pendapat tentang proposal perbaikan saya? Saya akan dengan senang hati menerapkan PR setelah saya mendapatkan saran tentang rute mana yang dapat diterima oleh kontributor/pengelola?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat