معالجة تحديثات مشغّلي الخدمات على الفور

وفقًا للإعدادات التلقائية، تتطلّب دورة حياة مشغّل الخدمات في حال العثور على مشغّل خدمات محدَّث وتثبيته، يجب إغلاق جميع علامات التبويب المفتوحة التي يتحكّم فيها عامل الخدمة الحالي أو أن تخضع عملية التنقّل إلى عملية تنقّل قبل أن يتم تفعيل مشغّل الخدمات المحدَّث وتحكُّمه فيه.

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

الرمز المطلوب وضعه في صفحتك

يتم تشغيل الرمز التالي في عنصر <script> مضمّن باستخدام وحدات JavaScript تم استيرادها من إصدار مستضاف على شبكة توصيل المحتوى (CDN) من workbox-window. ويسجِّل عامل الخدمة مشغّل الخدمات باستخدام workbox-window، وسيتفاعل في حال توقّف عامل الخدمة في مرحلة الانتظار. وعند العثور على عامل خدمة انتظار، يخبر هذا الرمز المستخدم بتوفّر إصدار محدَّث من الموقع الإلكتروني، ويُطلب منه إعادة التحميل.

<!-- This script tag uses JavaScript modules, so the proper `type` attribute value is required -->
<script type="module">
  // This code sample uses features introduced in Workbox v6.
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');
    let registration;

    const showSkipWaitingPrompt = async (event) => {
      // Assuming the user accepted the update, set up a listener
      // that will reload the page as soon as the previously waiting
      // service worker has taken control.
      wb.addEventListener('controlling', () => {
        // At this point, reloading will ensure that the current
        // tab is loaded under the control of the new service worker.
        // Depending on your web app, you may want to auto-save or
        // persist transient state before triggering the reload.
        window.location.reload();
      });

      // When `event.wasWaitingBeforeRegister` is true, a previously
      // updated service worker is still waiting.
      // You may want to customize the UI prompt accordingly.

      // This code assumes your app has a promptForUpdate() method,
      // which returns true if the user wants to update.
      // Implementing this is app-specific; some examples are:
      // https://open-ui.org/components/alert.research or
      // https://open-ui.org/components/toast.research
      const updateAccepted = await promptForUpdate();

      if (updateAccepted) {
        wb.messageSkipWaiting();
      }
    };

    // Add an event listener to detect when the registered
    // service worker has installed but is waiting to activate.
    wb.addEventListener('waiting', (event) => {
      showSkipWaitingPrompt(event);
    });

    wb.register();
  }
</script>

في حال الموافقة، يطلب messageSkipWaiting() من عامل خدمة الانتظار استدعاء self.skipWaiting()، ما يعني أنه سيبدأ تفعيله. بعد التفعيل، سيتحكّم مشغّل الخدمات الجديد في أي عملاء حاليين، ما يؤدي إلى بدء حدث controlling في workbox-window. وعند حدوث ذلك، تتم إعادة تحميل الصفحة الحالية باستخدام أحدث إصدار من جميع مواد العرض المخزَّنة مؤقتًا وأي أسلوب توجيه جديد تم العثور عليه في مشغّل الخدمات المحدَّث.

الرمز البرمجي المطلوب وضعه في مشغّل الخدمات

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

إذا كنت تكتب مشغّل الخدمات الخاص بك، ربما بالتزامن مع إحدى أدوات إصدار Workbox في وضع injectManifest، ستحتاج إلى إضافة الرمز التالي بنفسك:

addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

سيؤدي هذا الإجراء إلى استماع الرسائل إلى مشغّل الخدمات من workbox-window بقيمة SKIP_WAITING إلى type، وعند حدوث ذلك، يتم الاتصال بـ self.skipWaiting(). إنّ طريقة messageSkipWaiting() في workbox-window المعروضة في الرمز البرمجي السابق مسؤولة عن إرسال هذه الرسالة.

هل يجب عرض إشعار؟

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

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

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