أهم النقاط
- العمل دون اتصال أولاً يعني أن التطبيق يقرأ ويكتب في قاعدة بيانات محلية أولاً ثم يزامن مع الخادم في الخلفية.
- اختر التخزين حسب نمط الاستخدام: قواعد SQLite للبيانات المنظمة، والتخزين المشفّر للأسرار، ونظام الملفات للوسائط.
- سجّل كل تغيير كعملية بمعرّف فريد حتى لا تُنشئ إعادة المحاولة نسخاً مكررة أبداً.
- حدّد قواعد التعارض لكل نوع بيانات: آخر كتابة تفوز، أو دمج على مستوى الحقول، أو قرار الخادم للمال والمخزون.
- اعرض حالة المزامنة بصدق ليعرف المستخدم دائماً ما حُفظ على الجهاز وما وصل إلى الخادم.
ما هو تطبيق الجوال الذي يعمل دون اتصال أولاً؟
يتعامل تطبيق العمل دون اتصال أولاً مع الشبكة كإضافة لا كشرط. فكل شاشة تقرأ من بيانات مخزنة على الجهاز، وكل إجراء يُكتب محلياً أولاً، ومحرك مزامنة يتبادل التغييرات مع الخادم كلما توفر الاتصال.
انقطاع الاتصال ليس حالة خطأ، بل واقع يومي للفنيين في الطوابق السفلية ومندوبي المبيعات على الطرق والمسافرين والمستخدمين في المناطق ضعيفة التغطية. والتصميم له منذ البداية أرخص بكثير من إضافته بعد الإطلاق، ولهذا تحدد مشاريع تطوير تطبيقات الجوال لدينا متطلبات العمل دون اتصال منذ مرحلة الاستكشاف.
متى يحتاج التطبيق إلى العمل دون اتصال؟
لا تحتاج كل التطبيقات إلى دعم كامل للعمل دون اتصال. نوصي به عندما:
- يعمل المستخدمون في الميدان أو المستودعات أو مواقع البناء أو أثناء السفر.
- تكون خسارة نموذج أو طلب بسبب انقطاع الإشارة مكلفة فعلاً.
- يُستخدم التطبيق في مناطق تكون فيها بيانات الجوال بطيئة أو باهظة.
- تكون السرعة مهمة: القراءة من قاعدة محلية تجعل الشاشات فورية حتى مع الاتصال.
أما تطبيقات المحتوى فغالباً ما يكفيها تخزين مؤقت بسيط للبيانات الحديثة.
كيف تختار التخزين المحلي؟
يعتمد اختيار التخزين المحلي على أنماط الوصول لا على الموضة:
- البيانات المنظمة والعلائقية مثل الطلبات والمهام والعملاء: قاعدة بيانات مدمجة مبنية على SQLite، تُستخدم مباشرة أو عبر مكتبات مثل WatermelonDB أو op-sqlite في React Native وDrift في Flutter.
- الأسرار والرموز: سلسلة المفاتيح أو مخزن المفاتيح في النظام، وليس تخزين المفتاح والقيمة العادي أبداً.
- الصور والمستندات: نظام الملفات، مع البيانات الوصفية في قاعدة البيانات وقواعد إخلاء واضحة حتى لا تمتلئ مساحة الجهاز بصمت.
نشفّر البيانات المحلية الحساسة ونخطط لترحيل مخطط البيانات منذ الإصدار الأول، لأن تغيير المخطط على آلاف الأجهزة لا يمكن التراجع عنه.
كيف يجب أن تعمل مزامنة البيانات؟
لمحرك المزامنة الموثوق اتجاهان: الدفع يرسل التغييرات المحلية إلى الخادم، والسحب يجلب التغييرات التي حدثت في مكان آخر منذ آخر مزامنة ناجحة، عادةً عبر مؤشر أو طابع زمني.
- سجّل كل إجراء للمستخدم كعملية في صندوق صادر محلي بمعرّف فريد يولّده التطبيق.
- طبّق التغيير على قاعدة البيانات المحلية فوراً لتتحدث الواجهة.
- ادفع العمليات على دفعات عند الاتصال، ويستخدم الخادم المعرّفات لتجاهل التكرار فتصبح إعادة المحاولة آمنة.
- اسحب التغييرات البعيدة وادمجها، ثم حرّك مؤشر المزامنة إلى الأمام.
يوفّر التجميع والضغط البطارية والبيانات. ويجب تصميم الخادم أيضاً لهذا النمط بواجهات متكررة الأمان وخلاصات للتغييرات، وهو ما يبنيه فريق السحابة وDevOps لدينا.
كيف تحل تعارضات المزامنة؟
يحدث التعارض عندما يعدّل جهازان السجل نفسه قبل المزامنة. لا توجد إجابة واحدة للجميع، لذا نوثّق قاعدة لكل نوع من البيانات:
- آخر كتابة تفوز للبيانات منخفضة الأهمية مثل تفضيلات المستخدم.
- الدمج على مستوى الحقول عندما يعدّل أشخاص مختلفون عادةً حقولاً مختلفة من السجل نفسه.
- CRDT أو التحويلات التشغيلية للنصوص والقوائم التعاونية.
- قرار الخادم للمال والمخزون والحجوزات، حيث يتحقق الخادم من قواعد العمل وقد يرفض التغيير.
كيف يجب أن تعمل إعادة المحاولة والمزامنة في الخلفية؟
تفشل الشبكات بطرق فوضوية. نعيد المحاولة بتأخير متزايد أسياً مع عنصر عشوائي، حتى لا تُغرق آلاف الأجهزة العائدة بعد انقطاع الخادم في اللحظة نفسها. وتحترم المزامنة في الخلفية قيود iOS وAndroid، ونعرض إعادة محاولة يدوية حين يكون تأكيد المستخدم أكثر أماناً من التكرار الصامت.
كيف تبدو تجربة المستخدم الصادقة دون اتصال؟
يجب ألا تدّعي الواجهة أبداً أن شيئاً وصل إلى الخادم وهو لم يصل. لذلك نصمم نموذجاً واحداً لحالة المزامنة تستخدمه كل الشاشات:
- مؤشر هادئ لوضع عدم الاتصال، لا رسالة خطأ تمنع الاستخدام.
- حالات لكل عنصر: محفوظ على الجهاز، أو قيد المزامنة، أو تمت مزامنته، أو يحتاج إلى انتباه.
- رسائل واضحة عندما يتطلب الإجراء اتصالاً فعلاً، مثل الدفع بالبطاقة.
يصمم فريق تصميم UI/UX لدينا هذه الحالات جنباً إلى جنب مع المسار الطبيعي، لا كفكرة لاحقة.
كيف تختبر تطبيقاً يعمل دون اتصال أولاً؟
نختبر بمحاكاة ظروف الشبكة على أجهزة حقيقية، ونفعّل وضع الطيران أثناء تنفيذ الإجراء، ونغلق التطبيق أثناء المزامنة، ونجعل جهازين يعدلان السجل نفسه. وتغطي الاختبارات الآلية محرك المزامنة وقواعد التعارض، وتُراقب مؤشرات الأعطال وفشل المزامنة بعد الإصدار ضمن الصيانة والدعم.
المبدأ نفسه الذي يجعل المواقع سريعة ينطبق هنا: السرعة المُدرَكة تأتي من عدم انتظار الشبكة، وهو موضوع نتناوله أيضاً في دليل أداء Next.js. وإذا كانت خارطة طريقك تشمل فرقاً ميدانية أو متاجر أو أسواقاً ناشئة، تحدث إلينا مبكراً.
الأسئلة الشائعة
هل يمكن لتطبيقات React Native العمل دون اتصال؟
نعم. يمكن لتطبيقات React Native تخزين البيانات في قاعدة مدمجة مبنية على SQLite، ووضع التغييرات في طابور محلي، والمزامنة في الخلفية، لتوفير تجربة كاملة دون اتصال على iOS وAndroid.
أيهما أفضل للعمل دون اتصال: Flutter أم React Native؟
كلاهما قادر على ذلك. البنية أهم من إطار العمل: قاعدة بيانات محلية، وصندوق صادر للعمليات، وواجهات API متكررة الأمان، وقواعد تعارض واضحة. اختر الإطار الذي يناسب فريقك.
ما أفضل قاعدة بيانات لتطبيق جوال يعمل دون اتصال؟
للبيانات المنظمة، تبقى قاعدة البيانات المدمجة المبنية على SQLite الخيار الأكثر رسوخاً على المنصتين. خزّن الأسرار في سلسلة المفاتيح أو مخزن المفاتيح والملفات الكبيرة في نظام الملفات.
كيف تتعامل مع التعارض عندما يعدّل مستخدمان البيانات نفسها دون اتصال؟
حدّد قاعدة لكل نوع بيانات: آخر كتابة تفوز للتفضيلات، والدمج على مستوى الحقول للسجلات المشتركة، وCRDT للنصوص التعاونية، والتحقق من جهة الخادم للمال أو المخزون.
فريق الهندسة في OSTORDEV
مهندسون خبراء في OSTORDEV، وكالة تطوير الويب والجوال والذكاء الاصطناعي في الدار البيضاء بالمغرب. نكتب عن المشكلات التي نحلها في مشاريع عملائنا.