Flutter في الإنتاج: ما تعلمناه بعد إطلاق 3 تطبيقات عابرة للأنظمة الأساسية
Flutter هو خيارنا الأول لتطبيقات الأنظمة الأساسية المتعددة. لقد أطلقنا ثلاثة تطبيقات Flutter للإنتاج خلال العام الماضي — تطبيق تكنولوجيا مالية، منصة تعليمية، وأداة خدمة ميدانية. علّمتنا كل واحدة منها شيئاً جديداً حول ما تتفوق فيه Flutter والأماكن التي تحتاج فيها إلى الحذر. إليك الدروس الحقيقية، وليس خطاب التسويق.
إدارة الحالة: استقررنا على Riverpod
بعد تجربة Provider و BLoC و Riverpod عبر مشاريع مختلفة، قمنا بتوحيد معياري على Riverpod لجميع أعمال Flutter الجديدة. السبب بسيط: إنها تتعامل مع حقن التبعيات وإدارة الحالة في نمط واحد، وهي آمنة في وقت التجميع (بدون أخطاء وقت التشغيل من مزودي الخدمات المفقودين)، وتعمل بشكل متطابق في الاختبارات.
BLoC قوية لكنها احتفالية بشكل مفرط لمعظم التطبيقات. يضيف نمط الحدث والحالة رموزاً إضافية تبطئ التطوير بدون فوائد متناسبة للتطبيقات العادية المعتمدة على CRUD و API. نحتفظ بـ BLoC للميزات الحالية المعقدة مثل التحرير التعاوني في الوقت الفعلي حيث يكون تيار الأحداث الصريح مفيداً حقاً.
تتبع معمارية Riverpod الخاصة بنا نمطاً ثلاثي الطبقات: تعتمد عناصر واجهة المستخدم على وحدات التحكم (StateNotifier أو AsyncNotifier)، وتعتمد وحدات التحكم على المستودعات، والمستودعات تعتمد على مصادر البيانات (عملاء API، التخزين المحلي). كل طبقة قابلة للاختبار بشكل مستقل والرسم البياني للتبعيات صريح.
الأداء: قاعدة الـ 90%
تمنحك Flutter معدل 60 إطار في الثانية خارج الصندوق لـ 90% من الشاشات. الـ 10% الأخرى — قوائم التمرير الطويلة، الرسوميات المعقدة المعروضة فوق البيانات الحية، والشاشات التي تحتوي على صور الشبكة المتزامنة — تتطلب تحسيناً مقصوداً. أكثر التحسينات تأثيراً التي وجدناها:
استخدم منشئات const في كل مكان ممكن. تمنع هذه الممارسة الفردية إعادة بناء العناصر غير الضرورية وهي أسهل فوز لتحسين الأداء في Flutter. نفرضها عبر قواعد التحليل. استخدم ListView.builder بدلاً من ListView لأي قائمة أطول من 20 عنصراً — فهي تبني كسولة العناصر المرئية فقط. قم بتخزين صور الشبكة مؤقتاً باستخدام cached_network_image وعيّن حدود الذاكرة المناسبة. للرسوميات المعقدة، استخدم RepaintBoundary لعزل عمليات الرسم المكلفة.
أداة الأداء في Flutter DevTools هي أفضل صديق لك. نقوم بتشغيلها على كل شاشة أثناء التطوير وننبه لأي إطار يستغرق أكثر من 16 ميلي ثانية. معظم التأخيرات تأتي من تخريب التخطيط (الأدوات المتداخلة بعمق التي تُطلق عمليات تخطيط متعددة) أو إعادة البناء غير الضرورية (المزودات التي تُخطر المستمعين على نطاق واسع جداً).
قنوات النظام الأساسي: الجسر إلى الكود الأصلي
كل تطبيق Flutter يحتاج في النهاية إلى كود خاص بالمنصة. بالنسبة لتطبيق التمويل الرقمي الخاص بنا، كانت المصادقة البيومترية وتخزين القبو الآمن. بالنسبة لتطبيق التعليم الإلكتروني الخاص بنا، كانت معالجة إشعارات الدفع مع الحمولات المخصصة. بالنسبة لتطبيق خدمة الميدان الخاص بنا، كان تتبع الموقع في الخلفية.
نستخدم Pigeon لقنوات النظام الأساسي الآمنة من حيث النوع بدلاً من MethodChannels الخام. يولد Pigeon النماذج الأولية لجانب Dart والجانب الأصلي من تعريف واجهة واحد. هذا يلغي مطابقة أسماء الطرق القائمة على السلاسل النصية التي تسبب أخطاء وقت التشغيل ويجعل كود قنوات النظام الأساسي قابلاً للصيانة حقاً.
قاعدتنا الأساسية: إذا كان هناك مكون إضافي بدرجة 90%+ على pub.dev وصيانة نشطة، استخدمه. إذا لم يكن كذلك، اكتب غلافاً رقيقاً من قنوات النظام الأساسي يفوض المهام إلى واجهة برمجة التطبيقات الأصلية. لا تقاوم النظام الأساسي أبداً — احتضنه من خلال جسور نظيفة.
استراتيجية الاختبار التي تعمل فعلاً
أدوات اختبار Flutter ممتازة لكن لا يتم استخدامها. هرم الاختبار الخاص بنا: 60% اختبارات وحدة (المستودعات والمتحكمات والمنطق التجاري)، 30% اختبارات الأدوات (عرض المكونات والتفاعل)، 10% اختبارات التكامل (تدفقات المستخدم الحرجة من البداية إلى النهاية). تعطينا هذه النسبة الثقة في إعادة الهيكلة دون هشاشة الكثير من اختبارات التكامل.
ميزة اختبار الملف الذهبي مقللة من قيمتها. بالنسبة للشاشات ذات التخطيطات المعقدة، نلتقط صورة من الأداة المعروضة ونقارنها بصورة مرجعية. هذا يكتشف الانحدارات البصرية التي تفتقدها اختبارات الوحدة. نقوم بتشغيل الاختبارات الذهبية على CI لكل طلب سحب.
هل كنا سنختار Flutter مرة أخرى؟
نعم، مع بعض التحفظات. Flutter هو أفضل إطار عمل عابر للمنصات المتاح اليوم للتطبيقات التي تحتاج إلى iOS و Android معاً مع قاعدة رمز مشتركة. لغة Dart منتجة ونظام الـ widget مصمم بشكل جيد جداً. Hot reload يجعل التطوير المتكرر سريعاً.
لكنه ليس الخيار الصحيح لكل شيء. التطبيقات التي تحتوي على 50% أو أكثر من رمز خاص بالمنصة (الواقع المعزز الثقيل، خطوط أنابيب الكاميرا المعقدة، التكامل العميق مع نظام التشغيل) يجب أن تكون أصلية. التطبيقات التي تركز بشكل أساسي على عرض المحتوى مع تفاعل بسيط يمكن أن تستخدم React Native أو حتى PWA. Flutter يتفوق في التطبيقات التفاعلية المدفوعة بالبيانات ذات احتياجات التكامل المعتدلة مع المنصة — وهذا يصف معظم منتجات الشركات الناشئة.