إنشاء تجارب بحث مرنة باستخدام Workbox

يعرض لك هذا الدرس التطبيقي حول الترميز كيفية تنفيذ تجربة بحث مرنة في Workbox. ويحتوي التطبيق التجريبي الذي يستخدمه على مربّع بحث يستدعي نقطة نهاية للخادم ويعيد توجيه المستخدم إلى صفحة HTML أساسية.

القياس

قبل إضافة تحسينات، من الأفضل تحليل الحالة الحالية للتطبيق أولاً.

  • انقر على إنشاء ريمكس لتعديل لجعل المشروع قابلاً للتعديل.
  • لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق. ثم اضغط ملء الشاشة ملء الشاشة

في علامة التبويب الجديدة التي تم فتحها للتو، تحقق من سلوك الموقع الإلكتروني عند انقطاع الاتصال بالإنترنت:

  1. اضغط على "Control+Shift+J" (أو "Command+Option+J" على أجهزة Mac) لفتح "أدوات مطوري البرامج".
  2. انقر على علامة التبويب الشبكة.
  3. افتح أدوات مطوري البرامج في Chrome واختَر لوحة "الشبكة".
  4. في القائمة المنسدلة "تقييد الشبكة"، اختَر بلا إنترنت.
  5. في تطبيق العرض التوضيحي، أدخِل طلب بحث، ثم انقر على الزر بحث.

يتم عرض صفحة خطأ المتصفّح العادية:

لقطة شاشة لتجربة المستخدم التلقائية بلا إنترنت في المتصفِّح

تقديم رد احتياطي

يحتوي مشغّل الخدمات على رمز لإضافة الصفحة بلا اتصال بالإنترنت إلى قائمة ذاكرة التخزين المؤقت مؤقتًا، وذلك كي يمكن تخزينها مؤقتًا في حدث عامل الخدمة install دائمًا.

عادةً ما تحتاج إلى توجيه Workbox لإضافة هذا الملف إلى قائمة التخزين المؤقت في وقت الإصدار، وذلك من خلال دمج المكتبة مع أداة التصميم التي تختارها (مثل webpack أو gulp).

ولتبسيط الأمر، فقد نفّذنا هذا الإجراء من قبل. الرمز التالي في public/sw.js هو ما يلي:

const FALLBACK_HTML_URL = '/index_offline.html';

workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

بعد ذلك، أضف رمزًا لاستخدام الصفحة بلا اتصال بالإنترنت كاستجابة احتياطية:

  1. لعرض المصدر، اضغط على View Source (عرض المصدر).
  2. أضِف الرمز التالي إلى أسفل public/sw.js:
workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly());

workbox.routing.setCatchHandler(({event}) => {
  switch (event.request.destination) {
    case 'document':
      return caches.match(FALLBACK_HTML_URL);
      break;
    default:
      return Response.error();
  }
});

تقوم التعليمة البرمجية بما يلي:

  • تحدِّد هذه السياسة استراتيجية الشبكة فقط التلقائية التي سيتم تطبيقها على جميع الطلبات.
  • لتعريف المعالِج العام للأخطاء، عن طريق طلب workbox.routing.setCatchHandler() لإدارة الطلبات التي تعذّر تنفيذها. عندما تكون الطلبات متعلّقة بالمستندات، سيتم عرض صفحة HTML احتياطية بلا اتصال بالإنترنت.

لاختبار هذه الوظيفة:

  1. ارجع إلى علامة التبويب الأخرى التي تشغّل تطبيقك.
  2. اضبط القائمة المنسدلة Throttling مرة أخرى على Online (على الإنترنت).
  3. اضغط على زر الرجوع في Chrome للرجوع إلى صفحة البحث.
  4. تأكد من أنّ مربّع الاختيار إيقاف ذاكرة التخزين المؤقت في "أدوات مطوري البرامج" مفعَّل.
  5. اضغط مع الاستمرار على زر إعادة التحميل في Chrome واختَر إفراغ ذاكرة التخزين المؤقت وإعادة التحميل الثابت لضمان تحديث مشغّل الخدمات.
  6. أعِد ضبط القائمة المنسدلة تقييد البيانات على بلا إنترنت مرّة أخرى.
  7. أدخل طلب بحث، وانقر على الزر بحث مرة أخرى.

تظهر صفحة HTML الاحتياطية:

لقطة شاشة لتجربة المستخدم المخصّصة بلا إنترنت في المتصفّح

طلب إذن إرسال الإشعارات

للتبسيط، تتضمّن الصفحة المتوفّرة بلا إنترنت في views/index_offline.html الرمز الذي يتيح طلب أذونات إرسال الإشعارات في كتلة نص برمجي في أسفل الصفحة:

function requestNotificationPermission(event) {
  event.preventDefault();

  Notification.requestPermission().then(function (result) {
    showOfflineText(result);
  });
}

تقوم التعليمة البرمجية بما يلي:

  • عندما ينقر المستخدِم على الاشتراك في الإشعارات، يتم استدعاء وظيفة requestNotificationPermission()، التي تستدعي Notification.requestPermission()، لعرض طلب إذن المتصفّح التلقائي. يتم حلّ الوعد من خلال الإذن الذي اختاره المستخدم، والذي يمكن أن يكون إما granted أو denied أو default.
  • تمرير الإذن الذي تم حلّه إلى showOfflineText() لعرض النص المناسب للمستخدم

الاستمرار في تنفيذ طلبات البحث بلا اتصال بالإنترنت وإعادة المحاولة عند الاتصال بالإنترنت مجددًا

بعد ذلك، نفِّذ مزامنة خلفية Workbox للاحتفاظ بطلبات البحث بلا اتصال بالإنترنت، حتى يمكن إعادة المحاولة عندما يكتشف المتصفِّح عودة الاتصال.

  1. افتح public/sw.js للتعديل.
  2. أضف التعليمة البرمجية التالية في نهاية الملف:
const bgSyncPlugin = new workbox.backgroundSync.Plugin('offlineQueryQueue', {
  maxRetentionTime: 60,
  onSync: async ({queue}) => {
    let entry;
    while ((entry = await queue.shiftRequest())) {
      try {
        const response = await fetch(entry.request);
        const cache = await caches.open('offline-search-responses');
        const offlineUrl = `${entry.request.url}&notification=true`;
        cache.put(offlineUrl, response);
        showNotification(offlineUrl);
      } catch (error) {
        await this.unshiftRequest(entry);
        throw error;
      }
    }
  },
});

تقوم التعليمة البرمجية بما يلي:

  • يستخدم "workbox.backgroundSync.Plugin" الإجراءات المنطقية لإضافة الطلبات التي تعذّر تنفيذها إلى قائمة الانتظار كي تتم إعادة محاولة تنفيذها لاحقًا. وسيتم الاحتفاظ بهذه الطلبات في IndexedDB.
  • تشير السمة maxRetentionTime إلى المدة الزمنية التي يمكن أن تتم خلالها إعادة محاولة تقديم طلب. في هذه الحالة، اخترنا 60 دقيقة (وبعدها سيتم تجاهلها).
  • onSync هو أهم جزء في هذا الرمز. سيتم طلب معاودة الاتصال هذه عند استعادة الاتصال بحيث يتم استرداد الطلبات في قائمة الانتظار ثم استرجاعها من الشبكة.
  • تتم إضافة استجابة الشبكة إلى ذاكرة التخزين المؤقت لـ offline-search-responses مع إلحاق معلَمة طلب البحث &notification=true بحيث يمكن اختيار إدخال ذاكرة التخزين المؤقت هذا عندما ينقر المستخدم على الإشعار.

لدمج المزامنة في الخلفية مع خدمتك، حدِّد استراتيجية NetworkOnly للطلبات الواردة إلى عنوان URL للبحث (/search_action) ومرِّر bgSyncPlugin المحددة مسبقًا. أضِف الرمز التالي إلى أسفل public/sw.js:

const matchSearchUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return url.pathname === '/search_action' && !(notificationParam === 'true');
};

workbox.routing.registerRoute(
  matchSearchUrl,
  new workbox.strategies.NetworkOnly({
    plugins: [bgSyncPlugin],
  }),
);

يؤدي ذلك إلى إعلام Workbox بالانتقال دائمًا إلى الشبكة، وعند فشل الطلبات، استخدام منطق المزامنة في الخلفية.

بعد ذلك، أضِف الرمز التالي إلى أسفل public/sw.js لتحديد استراتيجية تخزين مؤقت للطلبات الواردة من الإشعارات. استخدِم استراتيجية CacheFirst، لكي يتم عرضها من ذاكرة التخزين المؤقت.

const matchNotificationUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return (url.pathname === '/search_action' && (notificationParam === 'true'));
};

workbox.routing.registerRoute(matchNotificationUrl,
  new workbox.strategies.CacheFirst({
     cacheName: 'offline-search-responses',
  })
);

أخيرًا، أضف الرمز لعرض الإشعارات:

function showNotification(notificationUrl) {
  if (Notification.permission) {
     self.registration.showNotification('Your search is ready!', {
        body: 'Click to see you search result',
        icon: '/img/workbox.jpg',
        data: {
           url: notificationUrl
        }
     });
  }
}

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
     clients.openWindow(event.notification.data.url)
  );
});

اختبار الميزة

  1. ارجع إلى علامة التبويب الأخرى التي تشغّل تطبيقك.
  2. اضبط القائمة المنسدلة Throttling مرة أخرى على Online (على الإنترنت).
  3. اضغط على زر الرجوع في Chrome للرجوع إلى صفحة البحث.
  4. اضغط مع الاستمرار على زر إعادة التحميل في Chrome واختَر إفراغ ذاكرة التخزين المؤقت وإعادة التحميل الثابت لضمان تحديث مشغّل الخدمات.
  5. أعِد ضبط القائمة المنسدلة تقييد البيانات على بلا إنترنت مرّة أخرى.
  6. أدخل طلب بحث، وانقر على الزر بحث مرة أخرى.
  7. انقر على الاشتراك في الإشعارات.
  8. عندما يسألك Chrome عما إذا كنت تريد منح التطبيق إذنًا لإرسال إشعارات، انقر على سماح.
  9. أدخل طلب بحث آخر وانقر على الزر بحث مرة أخرى.
  10. اضبط القائمة المنسدلة Throttling مرة أخرى على Online (على الإنترنت) مرة أخرى.

بعد استعادة الاتصال، سيظهر إشعار:

لقطة شاشة للتدفق الكامل بلا اتصال بالإنترنت

الخاتمة

يوفّر Workbox العديد من الميزات المدمجة لجعل تطبيقات الويب التقدّمية (PWA) أكثر مرونة وتفاعلاً. في هذا الدرس التطبيقي حول الترميز، تعرّفت على كيفية تنفيذ واجهة برمجة التطبيقات Background Sync API عن طريق تجريد مربع العمل، وذلك لضمان عدم فقدان طلبات بحث المستخدمين بلا اتصال بالإنترنت ومن إمكانية إعادة المحاولة بعد عودة الاتصال. إن العرض التوضيحي هو تطبيق بحث بسيط، ولكن يمكن استخدام تنفيذ مماثل للسيناريوهات وحالات الاستخدام الأكثر تعقيدًا، بما في ذلك تطبيقات المحادثة ونشر الرسائل على شبكة اجتماعية وما إلى ذلك.