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

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

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

  • بديل للعنصر النائب "صورة مفقودة".
  • بديل 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 بشكل منتظم. يروِّج ذلك لنمط إعداد معالج "catch" عام للتعامل مع أي أعطال في دالة معالج واحد، ما يسمح لك بتقديم عناصر احتياطية مختلفة لقيم 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});

الخلاصة

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