تفعيل وضع عدم الاتصال لمواقع Gatsby: دليل شامل لتحسين تجربة المستخدم
مقدمة: الارتقاء بأداء مواقع JAMstack إلى آفاق جديدة
لطالما كانت مواقع JAMstack محط إشادة لأدائها الفائق وسهولة خدمتها للملفات الثابتة. هذا الأداء المتميز يأتي كجزء أصيل من تصميمها، مما يجعلها خيارًا مثاليًا للمطورين. ولكن ماذا لو تمكنا من الارتقاء بتجربة الزائر خطوة أخرى، وجعل الموقع متاحًا حتى في غياب الاتصال بالإنترنت؟ هذا هو جوهر وضع عدم الاتصال (Offline Mode) الذي سنتناوله في هذا المقال، مع التركيز على كيفية تطبيقه في مواقع Gatsby.
لفهم كيفية عمل وضع عدم الاتصال، من الضروري أولاً استيعاب آلية Gatsby في تقديم الصفحات. خلافًا للطرق التقليدية، لا يطلب الزائر كل ملف HTML على حدة من الخادم. بدلاً من ذلك، يطلب عميل JavaScript الخاص بـ Gatsby ملف page-data.json للصفحة المطلوبة. هذا النهج يتيح انتقالاً سلسًا بين الصفحات دون الحاجة إلى إعادة تحميل كلاسيكية للصفحة بأكملها. ومع ذلك، حتى هذه العملية تتطلب اتصالاً بالشبكة.

لماذا تحتاج مواقع الويب إلى وضع عدم الاتصال؟
في عصرنا الحالي، يبدو الاتصال بالإنترنت وكأنه أمر مفروغ منه، خاصة مع الهواتف الذكية التي أصبحت جزءًا لا يتجزأ من حياتنا. نستخدم تطبيقات مثل WhatsApp و Messenger باستمرار. ولكن ماذا يحدث عندما نكون داخل مصعد، أو نسير في مرآب سيارات تحت الأرض، أو نقود عبر نفق، أو حتى نستعد للإقلاع على متن طائرة؟ في كل هذه السيناريوهات، ينقطع الاتصال بالشبكة. في هذه اللحظات، يصبح المحتوى المتاح دون اتصال هو المنقذ الوحيد، مثل مشاهدة أفلام Netflix التي تم تنزيلها مسبقًا. هنا يأتي دور وضع عدم الاتصال لموقعك الإلكتروني، ليضمن استمرارية الوصول إلى المحتوى حتى في أسوأ ظروف الشبكة.
كيف يعمل وضع عدم الاتصال؟
ببساطة، يعتمد وضع عدم الاتصال على حفظ رحلة الذهاب والإياب إلى الخادم عن طريق تنزيل جميع البيانات الضرورية مسبقًا. ويتم ذلك بشكل أساسي من خلال تثبيت ServiceWorker، وهو عبارة عن نص برمجي يقوم متصفح الزائر بتشغيله في الخلفية. يعمل هذا ServiceWorker كخادم محلي بدلاً من الخادم البعيد الحقيقي، مما يتيح ميزات مثل الإشعارات الفورية (Push Notifications) والوصول إلى المحتوى دون اتصال. لمزيد من المعلومات التفصيلية حول ServiceWorker، يمكنك الرجوع إلى وثائق Google.

تفعيل وضع عدم الاتصال في Gatsby: خطوة بخطوة
مع Gatsby، وكما اعتدنا، فإن تفعيل هذه الميزة لا يتطلب سوى تثبيت إضافة (plugin) بسيطة:
npm i gatsby-plugin-offline --save
وبعد التثبيت، يجب إضافتها إلى ملف gatsby-config.js الخاص بمشروعك:
plugins: [
// ...
`gatsby-plugin-offline`,
// ...
]
ومع ذلك، نظرًا لأن كل موقع ويب يستخدم أنواعًا مختلفة من الأصول (assets)، فغالبًا ما نحتاج إلى خطوة إضافية لتكوين ServiceWorker بشكل دقيق ليتعامل مع هذه الأصول بفعالية.
استراتيجيات خدمة الأصول (Assets Serving Strategies)
يحتوي كل موقع ويب على العديد من الأصول، بدءًا من ملفات CSS وصولاً إلى الصور والأيقونات وخطوط الويب (web fonts) وبيانات الصفحات الفعلية. لا يمكن لـ ServiceWorker تنزيل جميع هذه الأصول أثناء التحميل الأولي للصفحة، لأن ذلك سيتعارض بشكل مباشر مع فائدة الأداء. لن يكون الزوار سعداء إذا بدأت متصفحاتهم في تنزيل 100 ميجابايت من الصور بمجرد زيارتهم لمعرض الصور الخاص بك. لحل هذه المشكلة، يمكننا استخدام التعبيرات النمطية (Regular Expressions) لاستهداف ملفات معينة وتكوين ServiceWorker للتعامل معها بشكل مناسب. دعنا نلقي نظرة على الاستراتيجيات المتاحة:
CacheFirst (التخزين المؤقت أولاً)
- الاستخدام النموذجي: خطوط الويب (web fonts)، أوراق الأنماط (stylesheets).
- آلية العمل: يتحقق
ServiceWorkerمن ذاكرة التخزين المؤقت (cache) بحثًا عن الملف المطلوب. إذا كان الملف غير موجود، فإنه يتصل بالإنترنت لجلبه، مع تخزينه في ذاكرة التخزين المؤقت للاستخدام المستقبلي.

CacheOnly (التخزين المؤقت فقط)
- الاستخدام المحتمل: منطق التخزين المؤقت المسبق الخاص بك.
- آلية العمل: يتحقق
ServiceWorkerمن ذاكرة التخزين المؤقت بحثًا عن الملف المطلوب. إذا كان الملف غير موجود، فإنه يعيد خطأ.

NetworkFirst (الشبكة أولاً)
- الاستخدام النموذجي: طلبات
APIغير الحرجة. - آلية العمل: يتصل
ServiceWorkerبالإنترنت لجلب الملف المطلوب. إذا كانت الشبكة معطلة أو الخادم لا يستجيب، فإنه يعود إلى ذاكرة التخزين المؤقت.

NetworkOnly (الشبكة فقط)
- الاستخدام النموذجي: طلبات
APIالحرجة. - آلية العمل: يتصل
ServiceWorkerبالإنترنت لجلب الملف المطلوب. إذا كانت الشبكة معطلة أو الخادم لا يستجيب، فإنه يعيد خطأ.

StaleWhileRevalidate (قديم أثناء إعادة التحقق)
- الاستخدام النموذجي: أصول الواجهة الأمامية (front-end assets)، الصور.
- آلية العمل: يتحقق
ServiceWorkerمن ذاكرة التخزين المؤقت بحثًا عن الملف المطلوب ويوفرها على الفور. بعد ذلك، يقوم بتقديم طلب شبكة لتحديث ذاكرة التخزين المؤقت بصمت في الخلفية.

تكوين موقع Gatsby للعمل دون اتصال
تكوين بسيط لموقع Gatsby يجب أن يعمل دون اتصال يبدو كالتالي:
{
resolve: `gatsby-plugin-offline`,
options: {
precachePages: [`/blog/*`],
},
}
بهذه الطريقة، نقوم بتكوين ServiceWorker للتخزين المؤقت المسبق لجميع منشورات المدونة، وهي جميع الصفحات التي يبدأ عنوان URL الخاص بها بـ /blog/. بمجرد وصول الزائر إلى الصفحة الرئيسية التي تحتوي على روابط لمنشورات المدونة، سيتمكن من النقر عليها والتنقل بينها دون الحاجة إلى اتصال إنترنت نشط. هذا بشرط أن تستخدم عنصر Link من Gatsby في التنفيذ. علامات الربط القياسية (anchor tags) تجعل المتصفح يتجاوز ServiceWorker ويجلب البيانات مباشرة من الخادم البعيد.
سيتعامل ServiceWorker مع جميع الأصول وفقًا لتكوينه الافتراضي:
CacheFirst: ملفاتJS، ملفاتCSS، كل ما بداخل مجلد"static/".NetworkFirst: ملفات/page-data/و/page-data.json.StaleWhileRevalidate: الصور، ملفات خطوط الويب (web font files)، إلخ.
لذا، إذا كنت قلقًا من أن ServiceWorker سيجلب جميع أصول جميع منشورات المدونة، فإنه سيفعل ذلك فقط بعد أن يفتح الزائر صفحة المنشور فعليًا. والسبب في ذلك هو أن مساحة التخزين المؤقت وعرض النطاق الترددي لاتصال الإنترنت للزائر محدودة. عند التحميل الأول للصفحة، يقوم الزائر بتنزيل جميع الأصول على مستوى الموقع مثل أوراق الأنماط وخطوط الويب والأيقونات وغيرها، لذلك ستكون هذه الأصول متاحة في ذاكرة التخزين المؤقت في التحميلات اللاحقة. سيتم حل الصور والموارد الأخرى للصفحات المخزنة مؤقتًا مسبقًا بمجرد طلب الصفحة، ولا يمكن تغيير ذلك إلا من خلال منطق مخصص.
متى تحتاج إلى تغيير التكوين الافتراضي؟
في معظم الحالات، يكون التكوين الافتراضي كافيًا، ولكن هناك بعض السيناريوهات التي قد تتطلب تعديلات:
- الأصول المقدمة من عناوين
URLبدون لاحقة اسم ملف مطابقة: على سبيل المثال، تقدمGoogleتعريفاتCSSلخطوط الويب بدون لاحقة.css، وهذا مغطى بالفعل بالتكوين الافتراضي. ومع ذلك، قد تقوم بتقديم صور أو أصول أخرى من عناوينURLلا تحتوي على اللاحقة المناسبة. - التحكم بشكل أكبر في ذاكرة التخزين المؤقت: مع بعض الأصول، قد ترغب في التحكم في المدة التي يمكن أن يبقى فيها عنصر معين في ذاكرة التخزين المؤقت قبل أن يصبح منتهي الصلاحية.
- الأصول غير الشائعة: مثل خطوط الويب بتنسيق
EOT، والصور بتنسيقHEIC، ومقاطع الفيديو القصيرة، والأغاني، وما إلى ذلك. في هذه الحالات، تحتاج إلى تعديل التكوين الافتراضي وتحديده ضمن خيارات الإضافة (plugin options):
{
resolve: `gatsby-plugin-offline`,
options: {
precachePages: [`/blog/*`],
runtimeCaching: [
// التعريفات السابقة من التكوين الافتراضي (...),
{
urlPattern: /^https:\/\/fonts\.gstatic\.com/,
handler: 'cacheFirst',
options: {
cacheableResponse: {
statuses: [0, 200]
},
cacheName: 'google-fonts-webfonts',
expiration: {
maxAgeSeconds: 60 * 60,
maxEntries: 30
}
}
},
]
},
}
سيضمن هذا العنصر الإضافي في التكوين أن 30 خطًا كحد أقصى من خطوط Google التي يتم تقديمها من gstatic.com سيتم تخزينها مؤقتًا لمدة ساعة واحدة كحد أقصى، وسيتم التعامل معها باستخدام استراتيجية CacheFirst.
بناء الموقع قبل الاختبار
بمجرد الانتهاء من التكوين، تأكد من بناء الموقع وتقديمه قبل اختبار إمكانيات وضع عدم الاتصال. هذه الميزات لا تعمل في وضع التطوير (development mode).
gatsby build && gatsby serve
الخلاصة التقنية
لقد أثبتت مواقع JAMstack، وعلى رأسها Gatsby، تفوقها في الأداء بشكل افتراضي. ومع ذلك، فإن دمج وضع عدم الاتصال (Offline Mode) عبر gatsby-plugin-offline يمثل نقلة نوعية في تجربة المستخدم، محولًا الموقع من مجرد سريع إلى متاح دائمًا. إن استخدام Service Workers واستراتيجيات التخزين المؤقت الذكية لا يضمن فقط الوصول إلى المحتوى في غياب الاتصال، بل يعزز أيضًا سرعة التحميل ويقلل من استهلاك البيانات. إن القدرة على تخصيص هذه الاستراتيجيات تمنح المطورين مرونة كبيرة للتعامل مع مختلف أنواع الأصول، مما يجعل مواقع Gatsby خيارًا لا يُضاهى لبناء تطبيقات ويب تقدمية (PWAs) توفر تجربة مستخدم استثنائية في جميع الظروف.