قاعة بمقاعد ذهبية أمام مسرح مضاء
تطوير React Native

iOS وAndroid معًا.

تطبيقات جوّال مبنية بـ React Native — شيفرة مشتركة بين المنصات، ومكوّنات أصلية حيث يهم الأمر، ومنظومة JavaScript خلفها.

بالتفصيل

ما يجب معرفته قبل البدء.

01الاختيار

React Native أم Flutter، بلا خطاب بيع.

كلاهما جيد، وكلاهما سيبني التطبيق. والاختيار تحسمه عادةً أمور لا علاقة لها بقياسات أداء العرض.

  • فريقك. إن كان لديك مطوّرو React، أو تطبيق ويب React يمكن مشاركة أنواعه وقواعد تحققه ومنطق أعماله، فإن React Native يراكم الفائدة. أما Flutter فتُدخل لغة ثانية إلى الشركة.
  • التصميم. React Native يرتبط بمكوّنات المنصة الحقيقية، وهذا يناسب تطبيقًا يجب أن يشعر المستخدم بأنه من المنصة التي يعمل عليها. وFlutter ترسم مكوّناتها بنفسها، وهذا يناسب التصميم المخصّص الثقيل.
  • الاعتماديات. المنظومة التي فيها وحدة مصانة لأجل الـ SDK الذي لا خيار لك في دمجه تكسب النقاش كله.
  • الويب. React Native for Web يستطيع مشاركة الشيفرة مع تطبيق ويب فعلي. وهذه ميزة حقيقية حين يوجد المنتج نفسه في المتصفح.
  • التوظيف، في سوقك وفي سوقنا. كلاهما شائع. تحقّق من أيهما تستطيع فعليًا التوظيف له، لأنك ستصون هذا سنوات.

نبني الاثنين، فليس لدينا سبب لبيع أحدهما على حساب الآخر. وما لن نفعله هو التظاهر بأن القرار بديهي. وحين يكون متقاربًا فعلًا نقول ذلك، ونختار بحسب شكل فريقك لا شكل فريقنا.

02Expo أم المجرّد

Expo أم React Native المجرّد.

هذا أول قرار حقيقي في مشروع React Native، وقد تغيّر الافتراضي فيه. فـ Expo صارت الطريقة الموصى بها للبدء: توفّر خدمة البناء، وخدمة التحديثات، ومجموعة كبيرة من الوحدات الأصلية المصانة، ونظام إعداد يولّد مشروعَي iOS وAndroid بدل تركهما مجلدين يعدّلهما أحد يدويًا.

Expo مع نسخ التطوير

تطبيق Expo Go، وهو صندوق الرمل، لا يشغّل إلا الشيفرة الأصلية التي تشحنها Expo نفسها. والمنتجات الحقيقية تتجاوزه سريعًا، لذلك نبني نسخة تطوير مبكرًا: ملفك التنفيذي الخاص، باعتمادياتك الأصلية، مع الحفاظ على حلقة التكرار السريعة. ويُعبَّر عن الإعداد الأصلي عبر config plugins، ما يعني أن الترقية تعيد توليد المشروعين الأصليين بدل أن تفرض دمجًا يدويًا. وهذه الخاصية وحدها تزيل معظم الألم المرتبط تاريخيًا بترقية React Native.

المجرّد (bare)

مشروعان أصليان مودَعان في المستودع ويُداران يدويًا. وهو الجواب الصحيح حين تضيف React Native إلى تطبيق قائم، أو حين تحتاج اعتمادية إلى تغييرات أصلية لا يعبّر عنها أي plugin، أو حين يصرّ فريق منصات على ملكية عملية البناء. والكلفة أن كل ترقية صارت دمجًا عليك أنت.

وفي الحالتين يُحسَم هذا في تحديد النطاق وقائمة الاعتماديات أمامنا — لا يُكتشَف في الشهر الثالث.

03تطبيق قائم

إضافة React Native إلى تطبيق تملكه بالفعل.

لست مضطرًا إلى إعادة كتابة تطبيق لتستخدم React Native فيه. فيمكن تضمين واجهة React Native داخل تطبيق Swift أو Kotlin قائم واستعمالها لجزء من المنتج: منطقة ميزات جديدة، أو مسار تهيئة، أو القسم الذي يتغيّر أسبوعيًا بينما يتغيّر الباقي مرتين في السنة.

وما كلفة ذلك فعلًا

  • نظاما بناء وإصدار واحد. فخط الإنتاج الأصلي عليه أن ينتج حزمة JavaScript ويشحنها أيضًا.
  • التنقّل عبر الحدود: تمرير الحالة إلى الداخل، واستعادة نتيجة، وجعل زر الرجوع يتصرّف باتساق على الجانبين.
  • نظام تصميم مشترك، وإلا رأى المستخدمون الحدّ الفاصل.
  • بدء التشغيل: تهيئة بيئة التشغيل أول مرة تُفتح فيها شاشة React Native، دون أن ينتظر المستخدم أمام واجهة فارغة.
  • حدود الفرق. لا بد أن يملك أحدهم الجسر، وإلا لن يملكه أحد.

ويستحق ذلك حين يتحرك جزء من التطبيق أسرع كثيرًا من بقيته، أو حين يصير بإمكان فريق ويب أن يساهم في الجوّال. ولا يستحق لأجل شاشة واحدة، ونقول ذلك حين يكون هو الحال.

04تحديثات عبر الهواء

التحديثات عبر الهواء، وأين تتوقف.

يستطيع تطبيق React Native تنزيل حزمة JavaScript جديدة وقت التشغيل، فيصل الإصلاح إلى المستخدمين دون مراجعة من المتجر. وهذا مفيد فعلًا: نص خاطئ، أو تخطيط معطوب، أو عنوان خدمة خاطئ، يمكن تصحيحه في اليوم نفسه.

الحدود، بصراحة

  • لا يُحدَّث إلا JavaScript والأصول. أما إضافة اعتمادية أصلية أو ترقيتها فتظل تحتاج نسخة جديدة في المتجر.
  • يجب أن يطابق التحديث إصدار بيئة التشغيل في الملف التنفيذي الذي يهبط عليه، لذلك تُتابَع الإصدارات لكل بيئة تشغيل على حدة لا كتيار واحد.
  • يصل التحديث إلى المستخدمين عند تشغيلهم التالي، لا فورًا، وتبقى النسخ القديمة في الميدان أطول مما يتوقع أي أحد.
  • يسمح المتجران بهذا للإصلاحات والتحسينات، لا لتغيير ماهية التطبيق. فشحن منتج مختلف عبر الهواء مشكلة سياسات لا حيلة ذكية.

وحين يُستعمل كما ينبغي يكون شبكة أمان: طرح على مراحل، وتحديث يمكن التراجع عنه، وإصدار حقيقي في المتجر لأي شيء بنيوي. وحين يُستعمل باستهتار يصير قناة نشر ثانية غير متتبَّعة لا يعرف فيها أحد أي شيفرة يشغّلها مستخدم بعينه. ونحن نبقي هذا الربط صريحًا، في ملاحظات الإصدار وفي أداة تتبّع الأعطال.

05البنية الجديدة

البنية الجديدة، وما الذي تغيّره.

استبدلت React Native جسرها غير المتزامن الأصلي. فـ Fabric يعرض عبر واجهة JavaScript مباشرة، وTurboModules تحمّل الوحدات الأصلية عند الطلب بدل تحميلها كلها عند بدء التشغيل، وتوليد الشيفرة يجعل الحدّ بين JavaScript والأصلي موصوف الأنواع، وHermes هو المحرّك الافتراضي. والإصدارات الحديثة تعمل بهذه الطريقة جاهزةً.

وبالنسبة لمنتج يُبنى الآن يعني هذا في معظمه بدء تشغيل أسرع، وتفاعلًا أنعم تحت الحمل، وعللًا زمنية أقل عند الحدّ. أما بالنسبة لتطبيق قائم فهو ترحيل فيه عمل حقيقي — والعمل نادرًا ما يكون في شيفرتك أنت. بل في الاعتماديات المكتوبة للبنية القديمة.

  • كل اعتمادية أصلية يجب أن تدعم البنية الجديدة، أو تُستبدَل.
  • بعض المكتبات تعمل عبر طبقة توافق، وهي حل مؤقت لا وجهة.
  • الوحدات الأصلية المخصّصة التي تملكها تُعاد كتابتها مقابل الواجهات الجديدة.
  • تُنجَز الترقية كبند عمل قائم بذاته، بجولة اختبار خاصة به، بدل حشرها داخل إصدار ميزات.

وقبل بدء أي مشروع نفحص قائمة الاعتماديات مقابل ذلك. يستغرق الفحص ساعة، وقد غيّر توصيتنا أكثر من مرة.

06المنظومة

أين تنفع منظومة JavaScript، وأين تلدغ.

أين تنفع

  • لغة واحدة عبر الويب والجوّال والخلفية غالبًا، فيغطي فريق صغير مساحة أكبر دون أن ينقسم إلى اثنين.
  • أنواع وقواعد تحقق مشتركة بين تطبيق الويب وتطبيق الجوّال، فيكسر تغيير الـ API عملية البناء بدل أن يكسر شاشة مستخدم.
  • مكتبات ناضجة لما يحتاجه كل تطبيق: التنقّل، والقوائم الافتراضية، والنماذج، وجلب البيانات وتخزينها، والحركة التي تعمل خارج خيط JavaScript.
  • التوظيف أسهل، لأن مطوّري React كثيرون والجزء الخاص بالجوّال قابل للتعلّم.

وأين تلدغ

  • الاعتمادية الأصلية التي يهجرها مؤلفها تصير مشكلتك عند إصدار النظام التالي.
  • الاعتماديات المتعدّية تجرّ شيفرة أصلية لم تخترها وصرت تشحنها.
  • مصفوفات الإصدارات: React Native وExpo SDK والحزم وXcode وGradle، ولكل منها رأي في الآخر.
  • ترقيع حزمة لتعمل أمر عادي، ويجب أن يُسجَّل في المستودع وإلا اختفى عند التثبيت التالي.

لذلك تُعامَل الاعتماديات كقرارات. تُختار كل واحدة بحسب طريقة صيانتها بقدر ما تُختار بحسب وظيفتها، وتُراجَع القائمة قبل أن تكبر، وتجري الترقيات وفق جدول بدل أن تجري حين ينكسر شيء. والأداء يخضع للانضباط نفسه: قوائم افتراضية، وحركة خارج خيط JavaScript، وتخزين النتائج (memoisation) حيث أثبت القياس الحاجة إليه، لا منثورًا في كل مكان، وتحليل أداء بأدوات مطوّري React Native ومحلّل Hermes على جهاز حقيقي متوسط الفئة.

07الأداء ومعنى منجَز

الأداء، وما معنى «منجَز».

الأداء

  • قوائم افتراضية لأي شيء طويل، فيعرض التطبيق ما على الشاشة لا كل ما جلبه يومًا.
  • الحركة والإيماءات تُدار خارج خيط JavaScript، فلا يجعل عرض بطيء السحبَ متقطعًا.
  • صور بمقاسات صحيحة ومخزَّنة كما ينبغي — وهي السبب الأشيع لضغط الذاكرة على أجهزة Android الرخيصة.
  • إعادة عرض أقل: الحالة قريبة من موضع استعمالها، وmemoisation حيث أظهر محلّل الأداء الحاجة إليها لا في كل مكان.
  • قياس بدء التشغيل على هاتف Android متوسط الفئة، لأن منه يأتي تقييمك في المتجر.

منجَز

  • منشور على المتجرين، تحت حسابات المطوّر الخاصة بك، ومفاتيح التوقيع بحوزتك.
  • تقارير الأعطال والأحداث الرئيسية ظاهرة لفريقك، مع ربط التحديثات عبر الهواء بالإصدارات ليقول تقرير العطل من أي حزمة جاء.
  • عملية إصدار قابلة للتكرار ومكتوبة: بناء للمتجر، وطرح على مراحل، وكيفية التراجع.
  • المستودع وإعداد CI وحسابات الأطراف الثالثة باسمك.

وبعد ذلك يُصان التطبيق لا ينتهي: إصدار صيانة بضع مرات في السنة لمتطلبات نظام التشغيل والمتاجر، وترقيات اعتماديات وفق جدول، ومسار دعم لا يعتمد على ذاكرة شخص واحد.

أسئلة

الأسئلة التي تسبق العقد.

React Native أم Flutter؟
السؤال يتعلّق بفريقك أكثر مما يتعلّق بتفضيلنا. إذا كان لديك مطوّرو React وTypeScript، فإن React Native يشارك اللغة والأدوات وسوق التوظيف مع تطبيقك على الويب، ويتيح للأشخاص أنفسهم الانتقال بين الاثنين. وإذا لم يكن لديك استثمار سابق في React وأردت محرّك عرض واحدًا بواجهة متطابقة في كل مكان، فإن Flutter عادةً هو الخيار الأهدأ.
هل تستخدمون Expo أم React Native المجرّد؟
Expo مع TypeScript افتراضيًا، على البنية الجديدة، مع EAS للبناء والنشر، لأن ذلك يزيل معظم صيانة سلسلة الأدوات الأصلية. وعندما تفرض وحدة أصلية أو تطبيق أصلي قائم غير ذلك، ننتقل إلى إعداد مجرّد أو prebuild، ويُكتب القرار مع ما يترتّب عليه.
لدينا تطبيق أصلي بالفعل. هل يمكن إدخال React Native إليه؟
نعم، التكامل مع تطبيق قائم ممكن: شاشات جديدة بـ React Native داخل تطبيقك الحالي على iOS وAndroid. والإعداد أثقل من مشروع جديد لأن التنقّل والحالة وسلسلة البناء يجب أن تعمل على الجانبين، لذلك نحسبه عمل تكامل لا عمل ميزات.
هل يمكن نشر تحديثات دون انتظار مراجعة المتاجر؟
التغييرات التي تمسّ JavaScript وحده يمكن نشرها مباشرة إلى الأجهزة، وهو أمر مفيد للإصلاحات والنصوص. أما ما يمسّ الكود الأصلي فيحتاج نسخة جديدة ومراجعة، ويجب أن تبقى هذه التحديثات ضمن سياسات Apple وGoogle، فهي ليست وسيلة لتغيير وظيفة التطبيق بعد المراجعة.
كيف يجري العمل عمليًا مع فريق في تونس؟
نحن في تونس على التوقيت UTC+1، فيتداخل يوم العمل بالكامل مع غرب أوروبا، وبفارق ساعة واحدة على الأكثر خلال التوقيت الصيفي الأوروبي. نعمل داخل أدواتك: Slack أو Teams، ونظام التذاكر، والمستودع، مع عرض حيّ للبرنامج في نهاية كل دورة. وتتحدّث إلى من يكتب الكود، لا إلى مسؤول حسابات. ولغات العمل لدينا هي الإنجليزية والفرنسية والعربية.
لمن تعود ملكية الكود، وماذا لو أردنا المتابعة وحدنا؟
كل شيء ملك لك، والمستودع لك منذ أول commit. والتسليم يشمل التوثيق وسلسلة البناء والنشر وصلاحيات المتاجر وجلسة انتقال مع مطوّريك. نفضّل أن نترك فريقًا قادرًا على صيانة التطبيق على أن نترك فريقًا عاجزًا عنه.
اتصل بنا

لديك مشروع في ذهنك؟

أخبرنا بما تبنيه. ستحصل على قراءة صادقة للنطاق والجدول الزمني والتكلفة.