Moment: بناءات الإصدار الأصلي التفاعلي ، تحطم عميق عند تغيير المواقع

تم إنشاؤها على ١٠ أكتوبر ٢٠١٩  ·  4تعليقات  ·  مصدر: moment/moment

عند استخدام 0.59.10 المتفاعل الأصلي ، وتعيين الإعدادات المحلية لـ momentJS ، فقد وقعنا في انهيار وحشي للغاية لإصداراتنا فقط. لم يكن هذا العطل قابلاً للتكرار بالنسبة لنا مع إرفاق المصحح. حدث هذا الانهيار بالنسبة لنا على كل من iOS و Android. عبارات try-catch التي تغلف كل لحظة الاستخدام لم يكتشف الانهيار!

لإعادة إنتاج

  1. نقوم بتجميع اللغات / اللغات التي نريد تجربتها عبر منطق خاص بالتطبيق. على سبيل المثال ، ["fr-CA", "en-US", "fr", "en"]
  2. نقوم بإجراء حلقة من خلال هذه ، واحدًا تلو الآخر بدلاً من استخدام أداة ضبط المصفوفة ، حتى نتمكن من استدعاء بعض الأجهزة الأخرى ، ومن المحتمل أن نلتقط أي استثناءات JS يتم طرحها وتجربة المرشح التالي.
  3. على الرغم من استدعاء moment.locale(localeCandidate) داخل كتلة try-catch ، لا يزال التطبيق يتعطل على هذا الخط⁇

كان هذا تعطلًا عند الإطلاق ولكن فقط لإصدارات الإصدار !! هذا جعل من الصعب للغاية استخراج رسائل خطأ مفيدة / تسجيل.

لقد رأينا رسائل الخطأ التالية عبر Bugsnag Integration & System Console Logging

  • iOS: Exception in HostFunction: Error loading module0from RAM Bundle: unspecified iostream_category error
  • Android: Exception in HostFunction: Module not found: 0
  • بعد يوم واحد ، على iOS و Android ، رأينا أيضًا Requiring unknown module "./locale/en-us". - ولكن الغريب أن هذا الخطأ لم تتم معالجته في الوقت المناسب. ربما يكون رد فعل أصلي / مشكلة bugsnag.
  1. وجد التتبع النهائي نقطة واحدة تسببت في الانهيار:
    https://github.com/moment/moment/blob/96d0d6791ab495859d09a868803d31a55c917de1/moment.js#L1852 -L1853
    الذي أعتقد أنه يأتي من هنا: https://github.com/moment/moment/blob/6a06e7a0db2c83fb92aa72bbf6bde955d4c75a16/src/lib/locale/locales.js#L55 -L56

الحل البديل: التعليق على هذين السطرين أوقف التحطم!

السلوكيات المتوقعة

  • لا ينبغي أن تتصرف Moment بشكل مفاجئ ، ولكن بشكل خاص ليس في إصدارات الإصدار فقط!
  • يجب أن تكون استثناءات Moment قابلة للإزالة (كانت عبارات catch الخاصة بنا ستمنع الانهيار). - (يمكن أن تكون مشكلة أصلية عند العبث بـ require() في الإصدار)

الهاتف الذكي (يرجى استكمال المعلومات التالية):

  • الجهاز: iPhone X ، و iPhone 11 Pro ، و Samsung (؟ - لم يلتقط بالضبط ماذا) ، Google Pixel 3 ، (تفاعل أصلي 0.59.10)
  • نظام التشغيل: iOS و Android
  • iOS JavaScript Core (لإصدارات iOS المذكورة أدناه) و jsc-android (+ intl) 245459.0.0
  • الإصدارات: iOS 12.4 و iOS 13.1 و iOS 13.1.2 و iOS 13.2 (تجريبي؟) و Android 28 وغيرها.

بيئة خاصة باللحظة

  • توقيت المحيط الهادئ ، وربما توقيت لندن
  • تم عرض خطأ التعليمات البرمجية باستمرار خلال الأسبوعين الماضيين (2019-10-09) في جميع أوقات اليوم.
  • المكتبات الأخرى قيد الاستخدام: المنطقة الزمنية اللحظية واللحظة مع اللغات ، TypeScript ، التفاعل الأصلي 0.59.10 ، Apollo-Client وغيرها

الرجاء تشغيل الكود التالي في بيئتك وتضمين الإخراج:

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

سياق إضافي

التذاكر ذات الصلة

  • # 5214 - مختلف لأن هناك سياق أقل هنا ، واستخدام واجهة برمجة تطبيقات مختلفة والحصول على رسالة خطأ مختلفة. مشابه لأنه يحدث فقط في إصدارات الإصدارات ، مما يشير إلى تفاعل أصلي أيضًا ، لكنهم قاموا بإعادة نسخه فقط على ios-simulator / ios.
  • # 3872
  • # 2979

التعليق الأكثر فائدة

تحاول الأسطر المشار إليها "تلقائيًا" طلب الوحدات النمطية في وقت التشغيل ، لكن مستندات لغات التحميل تشير إلى أنه إذا كنت تستخدم مدير الحزم مثل JSPM ، فيمكنك تحميل لغات بواسطة import "moment/locale/fr . نظرًا لأننا نحتاج إلى مدير الحزم التفاعلية "لمعرفة" أنه يجب استيراد الملف ، فقد جربنا هذا النمط من الاستيراد حتى يتمكن الرابط "Packager" من "رؤية" جميع الملفات التي يجب تجميعها.

في النهاية ، بدت خطوط الاستيراد كما يلي:

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

يتم إدخال التنفيذ الدقيق لـ require() في وقت التشغيل الذي تعمل فيه ، وهذا بالتأكيد شيء يتصرف بشكل مختلف بشكل كبير بين إصدارات Debug & Release.

في رد الفعل الأصلي ، هناك أيضًا العديد من النكهات المختلفة لحزمة JavaScript في وضع الإصدار ، بما في ذلك ملف الكل في واحد ، والملفات المنفصلة الكل في واحد ، وحزم ذاكرة الوصول العشوائي. كل من هؤلاء يغيرون أيضًا كيفية طلب الأعمال. التصحيح require() يتصل بـ Metro Bundler الذي يعمل على خادم http محلي. من المحتمل أن يكون هذا مشابهًا جدًا لخوادم webpack / jspm / تصحيح الأخطاء الأخرى ، ولهذا السبب على الأرجح لا يتسبب طلب الاسم المستعار في حدوث مشكلات في تلك البيئة.

ال 4 كومينتر

تحاول الأسطر المشار إليها "تلقائيًا" طلب الوحدات النمطية في وقت التشغيل ، لكن مستندات لغات التحميل تشير إلى أنه إذا كنت تستخدم مدير الحزم مثل JSPM ، فيمكنك تحميل لغات بواسطة import "moment/locale/fr . نظرًا لأننا نحتاج إلى مدير الحزم التفاعلية "لمعرفة" أنه يجب استيراد الملف ، فقد جربنا هذا النمط من الاستيراد حتى يتمكن الرابط "Packager" من "رؤية" جميع الملفات التي يجب تجميعها.

في النهاية ، بدت خطوط الاستيراد كما يلي:

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

يتم إدخال التنفيذ الدقيق لـ require() في وقت التشغيل الذي تعمل فيه ، وهذا بالتأكيد شيء يتصرف بشكل مختلف بشكل كبير بين إصدارات Debug & Release.

في رد الفعل الأصلي ، هناك أيضًا العديد من النكهات المختلفة لحزمة JavaScript في وضع الإصدار ، بما في ذلك ملف الكل في واحد ، والملفات المنفصلة الكل في واحد ، وحزم ذاكرة الوصول العشوائي. كل من هؤلاء يغيرون أيضًا كيفية طلب الأعمال. التصحيح require() يتصل بـ Metro Bundler الذي يعمل على خادم http محلي. من المحتمل أن يكون هذا مشابهًا جدًا لخوادم webpack / jspm / تصحيح الأخطاء الأخرى ، ولهذا السبب على الأرجح لا يتسبب طلب الاسم المستعار في حدوث مشكلات في تلك البيئة.

مقترحات الإصلاح الخاصة بي:

أ. احذف aliasedRequire بالكامل إذا لم تكن هذه هي الطريقة التي من المفترض أن تفعل بها الأشياء بعد الآن + تعليمات تثبيت القرص حولها؟
ب. اكتشاف رد الفعل الأصلي مقابل المستعرض ( navigator غير متوفر في رد الفعل الأصلي ، ولكن هناك تقنيات أخرى هنا) ، والتصرف بشكل مختلف اعتمادًا على الموقف الذي نجد أنفسنا فيه؟ على سبيل المثال إذا كان رد الفعل الأصلي && DEV ، فقم بطباعة خطأ وحدة التحكم إذا كانت اللغة مدعومة من الناحية النظرية ، ولكنها لم تكن required حتى الآن (+ تحديث المستندات).
ج. انقل aliasedRequire من متغير محلي في تلك الدالة إلى "شبه عمومي". moment.aliasedRequire ، بهذه الطريقة يمكننا إدخال وظيفة no-op / do-nothing بحيث لا يمكن أن يتسبب aliasedRequire في تعطل التفاعل الأصلي بشدة بعد الآن.

يسعدني تنفيذ أي من هذه الخيارات إذا كان بإمكان المشرف أن يوجهني إلى الخيار الذي يودون مني تنفيذه ، وبالنسبة للمقترحات B / C ، ساعدني في تحسين التنفيذ الدقيق الذي يميلون إلى قبوله!

marwahaha - لست متأكدا ما هي العملية الخاصة باللحظة. هل لديك رأي في مقترحات الإصلاح الخاصة بي؟ سأكون سعيدًا بتطبيق العلاقات العامة بمجرد أن أحصل على بعض النصائح حول المسار الذي قد يكون مقبولًا للمساهمين / المشرفين؟

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات