إنشاء تجارب بحث مرنة باستخدام 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. لعرض المصدر، اضغط على عرض المصدر.
  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. اضبط القائمة المنسدلة التقييد على على الإنترنت مرة أخرى.
  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 Background Sync للاحتفاظ بالطلبات بلا إنترنت، حتى يمكن إعادة محاولة تنفيذها عندما يرصد المتصفّح عودة الاتصال.

  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. اضبط القائمة المنسدلة التقييد على على الإنترنت مرة أخرى.
  3. اضغط على زر رجوع في Chrome للرجوع إلى صفحة البحث.
  4. اضغط مع الاستمرار على زر إعادة التحميل في Chrome واختَر إفراغ ذاكرة التخزين المؤقت وإعادة التحميل الكامل للتأكّد من تعديل عامل الخدمة.
  5. اضبط القائمة المنسدلة التقييد على بلا إنترنت مرة أخرى.
  6. أدخِل طلب بحث، ثم انقر على زر بحث مرة أخرى.
  7. انقر على الاشتراك في الإشعارات.
  8. عندما يسألك Chrome عمّا إذا كنت تريد منح التطبيق إذنًا بإرسال الإشعارات، انقر على السماح.
  9. أدخِل طلب بحث آخر وانقر على زر بحث مرة أخرى.
  10. اضبط القائمة المنسدلة التقييد على على الإنترنت مرة أخرى.

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

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

الخاتمة

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