في أغلب الأحيان عند اختيار هذه اللغة ، من المتوقع أن يستغرق تطوير تطبيق واحد لمنصتين أساسيين نصف الوقت الذي يستغرقه تطوير تطبيقين. لكن في النهاية اتضح أن التطوير يأخذ الكثير ، إن لم يكن أكثر ، بسبب الصعوبات المخبأة في ظل التألق الخارجي والتسويق. سنتحدث عن بعض الصعوبات المماثلة التي واجهناها في الأشهر القليلة الماضية من العمل مع React Native.
React Native تتكيف مع جافا سكريبت لتطوير الهاتف المحمول. يتحقق ذلك من خلال حقيقة أنه يستخدم عدة جامعين لإنشاء مشاريع - Metro Bundler ، الذي يفسر رمز JS ويمثل الموارد وجامع النظام المستهدف. في حالتنا ، كان بمثابة منصة للأندرويد. من الناحية النظرية ، يجب أن يبدأ تطبيق React Native بكل بساطة. يمكّن الأمر run-android التفاعلي المترو Bundler ويبني التطبيق لجميع أجهزة Android ومحاكياتها المتصلة.
في الواقع ، اتضح أنه حتى في هذه المرحلة ، هناك صعوبات. ظهر خطأ باستمرار "غير قادر على تنزيل حزمة JS" في مشروعنا ، مما يعني أن المجمّع لا يمكنه ترجمة الشفرة إلى الشفرة الأصلية. كما اتضح في وقت لاحق ، ويرجع ذلك إلى حقيقة أنه لم يبدأ. أكد StackOverflow عملية التخمين واقترح أنه يجب عليك تشغيل المجمّع في مؤشر ترابط منفصل باستخدام أمر بدء رد الفعل الأصلي. هذا يسمح لك بإعادة تشغيل bundler فقط إذا تغير package.json ، لأن الإجراء لا يؤدي إلى إبطاء عملية التطوير كثيرًا.
Package.json هو ملف يحتوي على مجموعة من الوحدات الخارجية للتطبيق. يوجد في npmjs.com عدد كبير من المكتبات المختلفة لـ React Native ، مما يعمل على توسيع الوظائف وتبسيط التطوير. تستخدم العديد من المكتبات (على سبيل المثال ، Firebase) وظائف أصلية ، وبالتالي يجب ربطها مباشرة بالكود الأصلي. للقيام بذلك ، استخدم أمر الارتباط الأصلي <library-name> ، والذي يجب أن يقوم بتكوين هذه العلاقات مع الكود الأصلي.
بسبب حقيقة أن جميع المكتبات مكتوبة في أوقات مختلفة ، فإنها تستخدم إصدارات مختلفة من SDK وتتطلب مقاربة مختلفة. يحدث أحيانًا أن المكتبات لا تتوافق مع بعضها البعض ، أو أن الإصدار الأخير من المكتبة تجريبي ، وينصح المطورون أنفسهم بالرجوع إلى ما قبل الأخير. في كثير من الأحيان ، لا يقوم الرابط بتكوين كل التبعيات المطلوبة. لذلك ، بالنسبة لقاعدة الحماية المذكورة أعلاه ، تحتاج إلى إضافة العديد من المكتبات الإضافية في الكود الأصلي ، وتوصيل مستودعات خارجية مختلفة ، وتعديل mainApplication.java (وهذا فقط لنظام Android!). بالنسبة إلى Firebase ، هناك تعليمات مفهومة إلى حد ما لتنفيذ هذه الإجراءات ، لكن بالنسبة للمكتبات الأخرى ، فهي غير موجودة دائمًا.
بعد تكوين الاتصالات بالرمز الأصلي ، يمكنك إنشاء المشروع على أمل أن تعمل المكتبة المتصلة. عند التجميع ، تجدر الإشارة إلى أنه في حالة حدوث خطأ ، يجب عليك التأكد من أنه قد حدث بالضبط بسبب تصرفاتك ، وليس بسبب خطأ في المجمع. للثقة الكاملة ، يجب عليك تنفيذ تسلسل الإجراءات التالي:
rmdir node_modules /s /q && npm cache clean - force && npm i
سيحذف هذا الأمر مجلد node_modules ثم يعيد تحميله. هذه هي واحدة من أطول المهام ، لذلك يجدر استخدامها نادراً للغاية. في بعض المشروعات ، يمكن أن تشغل node_modules عددًا يصل إلى عدة غيغابايت على القرص الصلب ، وبالتالي فإن إعادة التثبيت ستستغرق بعض الوقت.
rmdir android/app/build /s /q
أثناء التطوير ، لوحظ أن الإنشاء غير الناجح غالبًا ما يكون نتيجة لحقيقة أن المجمع لا يمكنه إنشاء (أو حذف) مجلد من دليل تصحيح الأخطاء. يعمل هذا الإجراء على حل المشكلة التي لا يمكن رد فعل حذف المجلد بمفرده. ولكن في الوقت نفسه ، سيستغرق إنشاء ملفات لهذا المجلد من البداية مرةً إضافية.
react-native start-reset-cache
إطلاق المترو المتجول. يجب أن تظل علامة التبويب هذه مفتوحة طوال عملية تصحيح الأخطاء. في حالة حدوث خطأ ، قد يظهر سجل الخطأ هنا. على الأرجح ، في حالة حدوث خطأ ، ستنتهي هذه العملية وستحتاج إلى إعادة التشغيل مرة أخرى.
react-native run-android
قم بتثبيت التطبيق على جهاز متصل أو محاكي. تحدث معظم أخطاء البناء هنا ، وبعضها مفهوم ، ولكن بعضها غير منطقي تمامًا ويتم "علاجه" من خلال إعادة تشغيل العملية بأكملها.
تخيل عملية الإنشاء بتسلسل من الأوامر لمشروع واحد (يحتوي بالفعل على مجال واسترجاع وتفاعل تفاعلي ، وحوالي عشر مكتبات أخرى) بعد توصيل Firebase.
react-native start react-native run-android >> debug react-native run-android >> , metro bundler react-native start react-native run-android >> debug react-native run-android >> ! metro bundler , JS- react-native start >> restart -
وغني عن القول ، يستغرق وقتا طويلا حقا؟ وهذه ليست عملية لمرة واحدة: بحلول اللحظة الموصوفة ، كان هذا الإجراء مطلوبًا بعد كل تغيير تقريبًا في رمز البرنامج. مع كل مكتبة جديدة ، يصبح المشروع أقل استقرارًا ، ويمكن أن تتغير هذه العملية ، في أغلب الأحيان إلى الأسوأ. تصحيح أخطاء أحد التطبيقات هو أحد أهم الوظائف للمطور ، وفي هذه الحالة تقل سرعته كثيرًا.
الحديث عن تصحيح الأخطاء. مصحح React Native لديه مشاكل ليس فقط مع الإطلاق. تصحيح الأخطاء التي وجدت نتيجة للاختبار هو أيضا عملية مؤلمة إلى حد ما. في رد الفعل الأصلي ، تُترجم شفرة JS إلى الشفرة الأصلية ، ولكن يتم التعتيم أثناء الترجمة. لذلك إذا كنت لا تريد أن ترى أخطاء مثل "استثناء المؤشر الخالي في zzz.yyy ()" ، فأنت بحاجة إلى استخدام مصحح الأخطاء المدمج ، لا يمكنك قراءة الاستثناءات فقط في logcat. على خطأ ، يعرض مصحح الأخطاء "شاشة الموت" حمراء مع وصفها ، يدفع أكثر أو أقل نحو مسار التصحيح. ولكن هناك مشاكل مع هذا الجزء.
حسنًا ، عندما يبدو الخطأ كالتالي:

من الواضح حقًا ما يحدث هنا - بدلاً من كائن الصفيف المتوقع ، this.state.noteArray.map غير معرف ، مما يتسبب في TypeError الشهير. يمكنك إصلاحه عن طريق الانتقال إلى app.js: 14 والتحقق من القيمة في هذا المتغير قبل الاستخدام.
أسوأ عندما يبدو الخطأ كالتالي:

لذلك:

أو هكذا:

تم التقاط الصور من الإنترنت ، لكننا رأيناها حية. وعلى الرغم من حقيقة أنها تظهر في وقت التشغيل ، فإن هذا الخطأ لا يرجع إلى حقيقة أن شيئًا ما قد تم فعله بشكل غير صحيح في التعليمات البرمجية الخاصة بك. قد يكون هذا بسبب حقيقة أنك قمت بتثبيت المكتبة بشكل غير صحيح ، أو إذا كانت وارداتك تحتوي على تبعيات غير متوافقة ، أو حدث خطأ ما في الكود الأصلي ، ويحاول React اكتشاف الخطأ. كل خطأ هو فردي ويتم حلها بشكل مختلف جدا. من الجيد وجود StackOverflow ونوع من تصحيح الأخطاء على الأقل.
والأسوأ من ذلك ، عندما لا يتم إعادة إنتاج خطأ في تصحيح الأخطاء. واجهنا هذا الموقف عند محاولة إنشاء تطبيق مع إصدار جديد من React مع دعم x64-architecture لنظام Android. عند تثبيت تطبيق باستخدام مصحح أخطاء ، كل شيء يعمل بشكل جيد. ولكن بمجرد أن نبني الاختبار على الهاتف ، يتوقف كل شيء عن العمل ويتوقف بمجرد أن يتعلق الأمر بالتفاعل مع قاعدة البيانات. لتصحيح عدم تصحيح الأخطاء على عجل ، نستخدم رسائل وحدة التحكم ، والتي كانت في هذه الحالة مكون رد الفعل toastAndroid. يعرض هذا المكون نصًا قصيرًا عند الوصول إلى سطر معين من التعليمات البرمجية. بشكل منهجي ، يفضل تقسيم الكود إلى النصف ، نوطن الوظيفة التي يحدث بها الخطأ ونكتشف أن طريقة Object.assign ({} ، عنصر) لا تعمل في الإصدار الجديد من React. كان من حسن الحظ أنه يمكنك استبدال هذه الوظيفة بـ {... item} أقصر مع الحفاظ على وظائف التطبيق ، ولكن البحث عن هذا الخطأ كلف حوالي 12 ساعة من العمل.
بعد إجراء دراسة صغيرة بحثًا عن الأسباب. كما اتضح فيما بعد ، يستخدم React Native محركات Javascript مختلفة لتفسير كود JS في إصدارات التصحيح والإنتاج: لتصحيح أخطاء محرك Chrome JS ، وفي JavaScriptCore. نعم ، لا يترجم React Native JavaScript إلى رمز أصلي ، لكنه يفسر أثناء تشغيله. في الوقت نفسه ، يعمل محرك تصحيح الأخطاء أكثر استقرارًا ، وبالتالي تتسلل الأخطاء بشكل متزايد إلى الإنتاج. على سبيل المثال ، توضح هذه المقالة كيفية عمل تنسيق التاريخ في ظل ظروف مختلفة. بالرجوع إلى الخطأ: اتضح أنه بعد تحديث إصدار React Native ، فقد محرك الويب الخاص بإنتاج الإنتاج دعمه لـ Object.assign (). لكن محرك تصحيح الأخطاء ظل كما هو.
ربما يكون الخيار الأسوأ هو حالة توقف التطبيق في أماكن عشوائية ، فقط في إصدار الإنتاج وبدون أي سجلات من React Native. مثال: بعد تثبيت نسخة إصدار التطبيق على الهاتف ، "يعمل لفترة من الوقت" ، ثم "ينطفئ دون خطأ أو تحذير في لحظة عشوائية." علاوة على ذلك ، الخطأ غير مستنسخ على جميع الأجهزة. في النهاية ، من خلال التجربة والخطأ (والكشف عن أن Crashlytics Firebase المذكورة أعلاه لا يرسل الأخطاء المقابلة) ، تمكنا من التقاط سجلات الخريف التي تبدو مثل هذا:

هذا النص لا ينطبق حتى على طلبنا ، لم يتم وضع علامة باللون الأحمر. ولكن بعد أن وصلنا إلى المنتديات ، وجدنا أن الإصدار الجديد من React Native معطل. وكسر السابق. بالنسبة إلى متتبع المشكلات الرسمي ، كان الخطأ "تعطل Android: الإشارة 11 (SIGSEGV)" موجودًا لمدة شهرين ، ولحسن حظنا قبل يومين من ذهابنا إلى هناك (!) تم اقتراح حل تجريبي لإصلاح الخطأ.
من المفارقات أن بعض المطورين الذين اضطروا للتعامل مع Android Studio كانوا في حيرة من أن IDE لديه خيارات مثل build / clean project أو file / cache caches. هذا مطلوب من أجل التخلص من السلوك غير الطبيعي للمهد ، من رسائل الخطأ والتحذيرات ، من أخطاء المزامنة. سأل المطورين: "لماذا يجب علينا القيام بالعمل من أجل IDE الخاص بنا ، في مثل هذه الحالات ، يجب تنفيذ هذه الأوامر تلقائيًا." ويمكن فهمها ، ولكن في نفس الوقت ، تقوم IDE الحديثة بكل الأعمال الصعبة وراء الكواليس. وهؤلاء المطورين ببساطة لم يعملوا مع React Native.
كل ما سبق حالات منعزلة حدثت خلال الأسابيع القليلة الماضية. نحن هنا لا نصف مدى تعقيد تشغيل التطبيقات مع Expo ، من خلال ضبط نمط الكود في babel / eslint ، نحن لا نوبخ Javascript للحصول على مرونة مفرطة ، ونحن لا نعلم كيف أن تصحيح الأخطاء بسبب رابط الإعادة / الإقلاع قد ضاع بالكامل تقريباً في أحد المشاريع. بالنظر إلى الصعوبات الموضحة في الدعم والتطوير وحقيقة أنه في كل نظامين يتكاثر كل منهما على حدة ، يجدر التفكير فيما إذا كانت React Native مربحة حقًا؟ بعد أن أكملنا مشروعنا الثالث بهذه اللغة ، قررنا عدم ذلك. ما رايك