إدارة الردود الاحتياطية

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

الردّ الاحتياطي هو ردّ عام بمقاس واحد يناسب الجميع، وهو عنصر نائب أفضل من ما سيوفّره المتصفّح تلقائيًا عند تعذُّر تنفيذ أحد الطلبات. تشمل بعض الأمثلة:

  • بديل لـ "الصورة المفقودة" .
  • بديل HTML للمعيار "لا يتوفر اتصال بالشبكة" .

صفحة بلا إنترنت فقط

إذا كان كل ما عليك فعله هو توفير صفحة HTML مخصَّصة بلا إنترنت، ولكن لا يتوفر شيء آخر، إليك وصفة أساسية يمكنك اتّباعها:

import {offlineFallback} from 'workbox-recipes';
import {setDefaultHandler} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

setDefaultHandler(new NetworkOnly());

offlineFallback();

يستخدم الرمز البرمجي أعلاه setDefaultHandler لاستخدام استراتيجية الشبكة فقط كاستراتيجية تلقائية لجميع المسارات. بعد ذلك، يشغِّل وصفة offlineFallback لعرض الإجراء الاحتياطي بلا إنترنت في حال حدوث خطأ. تفترض الوصفة أنّ ملف HTML الاحتياطي بلا إنترنت سيكون باسم offline.html وسيتم عرضه من جذر خادم الويب.

الإجراءات الاحتياطية الشاملة

عند حدوث عطل في الشبكة أو خطأ في ذاكرة التخزين المؤقت، سيتم رفض استراتيجيات التخزين المؤقت التي يقدّمها "workbox-strategies" بشكل متّسق. ويعزز هذا نمط تعيين "التقاط" عمومي معالج لمعالجة أي حالات تعذُّر في دالة معالج واحد، ما يسمح لك بتوفير طرق احتياطية مختلفة لقيم request.destination المختلفة.

يستخدم المثال التالي وصفة warmStrategyCache من workbox-recipes ويضبط معالج صيد لعرض العناصر المخزّنة مؤقتًا مسبقًا في ذاكرة التخزين المؤقت لبيئة التشغيل. ومع ذلك، قد تكون الإجراءات الاحتياطية للتخزين المؤقت أكثر ملاءمةً لتطبيقك:

import {warmStrategyCache} from 'workbox-recipes';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate} from 'workbox-strategies';

// Fallback assets to cache
const FALLBACK_HTML_URL = '/offline.html';
const FALLBACK_IMAGE_URL = '/images/image-not-found.jpg';
const FALLBACK_STRATEGY = new CacheFirst();

// Warm the runtime cache with a list of asset URLs
warmStrategyCache({
  urls: [FALLBACK_HTML_URL, FALLBACK_IMAGE_URL],
  strategy: FALLBACK_STRATEGY,
});

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // The warmStrategyCache recipe is used to add the fallback assets ahead of
  // time to the runtime cache, and are served in the event of an error below.
  // Use `event`, `request`, and `url` to figure out how to respond, or
  // use request.destination to match requests for specific resource types.
  switch (request.destination) {
    case 'document':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_HTML_URL});

    case 'image':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_IMAGE_URL});

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

في الخطوة التالية، يتم تخزين الردود الاحتياطية مؤقتًا باستخدام injectManifest مع أدوات الإنشاء في Workbox، ويتم عرضها كإجراء احتياطي في حال حدوث خطأ في الطريقة matchPrecache.

import {matchPrecache, precacheAndRoute} from 'workbox-precaching';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

// Optional: use the injectManifest mode of one of the Workbox
// build tools to precache a list of URLs, including fallbacks.
precacheAndRoute(self.__WB_MANIFEST);

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // Fallback assets are precached when the service worker is installed, and are
  // served in the event of an error below. Use `event`, `request`, and `url` to
  // figure out how to respond, or use request.destination to match requests for
  // specific resource types.
  switch (request.destination) {
    case 'document':
      // FALLBACK_HTML_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_HTML_URL);

    case 'image':
      // FALLBACK_IMAGE_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_IMAGE_URL);

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

من الأمثلة على حالة الاستخدام الخاصة بالإعداد الاحتياطي الثاني ما إذا تم تخزين الصفحة مؤقتًا بشكل مسبق، ولكن لم يتم تخزين الصور (أو مواد العرض الأخرى) التي طلبتها الصفحة. سيظل من الممكن قراءة الصفحة من ذاكرة التخزين المؤقت عندما يكون المستخدم غير متصل بالإنترنت، ولكن يمكن توفير عناصر نائبة احتياطية أو وظائف بديلة في حال حدوث خطأ في الشبكة.

جارٍ تدفئة ذاكرة التخزين المؤقت لبيئة التشغيل

يحتفظ Workbox بذاكرة تخزين مؤقت منفصلة للتخزين المؤقت وذاكرة التخزين المؤقت لبيئة التشغيل، وقد تكون هناك حالات تريد فيها تخزين عنصر بشكل مؤقت مسبقًا بدون الاعتماد على التخزين المؤقت، نظرًا لأن تحديثات بيان التخزين المؤقت تتطلب منك نشر عامل خدمة محدث.

لإعداد ذاكرة التخزين المؤقت لبيئة التشغيل مسبقًا باستخدام مواد العرض، يمكنك استخدام وصفة warmStrategyCache من workbox-recipes. بشكل غير مرئي، تستدعي هذه الاستراتيجية Cache.addAll في حدث install الخاص بعامل الخدمات.

import {warmStrategyCache} from 'workbox-recipes';
import {CacheFirst} from 'workbox-strategies';

// This can be any strategy, CacheFirst used as an example.
const strategy = new CacheFirst();
const urls = [
  '/offline.html',
];

warmStrategyCache({urls, strategy});

الخاتمة

تستغرق إدارة الردود الاحتياطية للطلبات التي تعذّر تنفيذها بعض الجهد، ولكن بقليل من التخطيط المسبق، يمكنك إعداد تطبيق الويب لتوفير مستوى معيّن من المحتوى والوظائف عندما يكون المستخدم غير متصل بالإنترنت.