نافذة إطار العمل

حزمة workbox-window هي مجموعة من الوحدات التي تهدف إلى تشغيلها في سياق window، أي داخل صفحات الويب الخاصة بك. إنها مكملة لحزم صندوق العمل الأخرى التي يتم تشغيلها في عامل الخدمة.

الميزات أو الأهداف الرئيسية للعبة "workbox-window" هي:

استيراد نافذة إطار العمل واستخدامها

نقطة الدخول الأساسية لحزمة workbox-window هي الفئة Workbox، ويمكنك استيرادها في الرمز الخاص بك إما من شبكة توصيل المحتوى (CDN) أو باستخدام أي من أدوات تجميع JavaScript الشائعة.

استخدام شبكة توصيل المحتوى

أسهل طريقة لاستيراد الفئة Workbox على موقعك هي من شبكة توصيل المحتوى (CDN):

<script type="module">
  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');

    wb.register();
  }
</script>

يُرجى العِلم أنّ هذا المثال يستخدم <script type="module"> والعبارة import لتحميل الفئة Workbox. على الرغم من أنك قد تعتقد أنك بحاجة إلى تحويل هذه التعليمة البرمجية إلى تشغيل في المتصفحات القديمة، إلا أن هذا ليس ضروريًا في الواقع.

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

تحميل Workbox باستخدام حزم JavaScript

ولست بحاجة على الإطلاق إلى استخدام أي أدوات لاستخدام workbox-window، ولكن إذا كانت البنية الأساسية للتطوير تتضمّن أداة حزم مثل webpack أو Rollup تعمل مع الاعتماديات npm، يمكن استخدامها لتحميل workbox-window.

تتمثل الخطوة الأولى في تثبيت workbox-window كإضافة لتطبيقك:

npm install workbox-window

بعد ذلك، ضمن مربّع عمل import في أحد ملفات JavaScript في تطبيقك، يجب الإشارة إلى اسم حزمة workbox-window على النحو التالي:

import {Workbox} from 'workbox-window';

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

  wb.register();
}

إذا كانت الحِزمة تتيح تقسيم الرمز عبر عبارات الاستيراد الديناميكية، يمكنك أيضًا تحميل workbox-window بشكل مشروط، والذي من المفترض أن يساعد في تقليل حجم الحزمة الرئيسية لصفحتك.

مع أنّ نطاق workbox-window صغير جدًا، ما مِن سبب لحاجته إلى تحميله وفقًا لمنطق التطبيقات الأساسي على موقعك الإلكتروني، لأنّ عاملي الخدمة، بطبيعة الحال، يمثلون تحسينًا تدريجيًّا.

if ('serviceWorker' in navigator) {
  const {Workbox} = await import('workbox-window');

  const wb = new Workbox('/sw.js');
  wb.register();
}

مفاهيم التجميع المتقدمة

على عكس حِزم Workbox التي يتم تشغيلها في مشغّل الخدمات، يتم نقل ملفات الإصدار التي تمت الإشارة إليها من خلال الحقلين workbox-windowmain وmodule في package.json إلى ES5. وهذا يجعلها متوافقة مع أدوات الإنشاء الحالية، التي لا يسمح بعضها للمطوّرين بنقل أي شيء من ملحقات node_module.

إذا كان نظام التصميم يسمح لك بنقل تبعياتك (أو إذا لم تكن بحاجة إلى ترجمة أي من الرموز البرمجية)، فمن الأفضل استيراد ملف مصدر محدد بدلاً من الحزمة نفسها.

في ما يلي الطرق المختلفة التي يمكنك من خلالها استيراد Workbox، مع شرح لما سيعرضه كل منها:

// Imports a UMD version with ES5 syntax
// (pkg.main: "build/workbox-window.prod.umd.js")
const {Workbox} = require('workbox-window');

// Imports the module version with ES5 syntax
// (pkg.module: "build/workbox-window.prod.es5.mjs")
import {Workbox} from 'workbox-window';

// Imports the module source file with ES2015+ syntax
import {Workbox} from 'workbox-window/Workbox.mjs';

أمثلة

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

تسجيل مشغّل الخدمات وإبلاغ المستخدم في أول مرة يكون فيها مشغّل الخدمات نشطًا

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

const wb = new Workbox('/sw.js');

wb.addEventListener('activated', event => {
  // `event.isUpdate` will be true if another version of the service
  // worker was controlling the page when this version was registered.
  if (!event.isUpdate) {
    console.log('Service worker activated for the first time!');

    // If your service worker is configured to precache assets, those
    // assets should all be available now.
  }
});

// Register the service worker after event listeners have been added.
wb.register();

إبلاغ المستخدم إذا كان أحد مشغّلي الخدمات قد ثبّتَّ ولكنّه لا يزال في انتظار التفعيل

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

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

للمساعدة في الحدّ من الالتباس وتوضيح حدوث هذا الموقف، تقدّم الصف Workbox حدث waiting يمكنك الاستماع إليه:

const wb = new Workbox('/sw.js');

wb.addEventListener('waiting', event => {
  console.log(
    `A new service worker has installed, but it can't activate` +
      `until all tabs running the current version have fully unloaded.`
  );
});

// Register the service worker after event listeners have been added.
wb.register();

إبلاغ المستخدم بتحديثات ذاكرة التخزين المؤقت من حزمة workbox-broadcast-update

تُعدّ حزمة workbox-broadcast-update طريقة رائعة تتيح لك عرض المحتوى من ذاكرة التخزين المؤقت (لتقديمه بسرعة) مع إمكانية إبلاغ المستخدم بالتعديلات التي أجريتها على هذا المحتوى (باستخدام استراتيجية التحقّق من الصحة القديمة أثناء إعادة التحقق).

لتلقّي هذه التعديلات من النافذة، يمكنك الاستماع إلى أحداث message من النوع CACHE_UPDATED:

const wb = new Workbox('/sw.js');

wb.addEventListener('message', event => {
  if (event.data.type === 'CACHE_UPDATED') {
    const {updatedURL} = event.data.payload;

    console.log(`A newer version of ${updatedURL} is available!`);
  }
});

// Register the service worker after event listeners have been added.
wb.register();

إرسال قائمة بعناوين URL إلى ذاكرة التخزين المؤقت لمشغّل الخدمة

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

بالنسبة إلى التطبيقات في الفئة الأخيرة، قد يكون من المنطقي التخزين المؤقت فقط للأصول التي يحتاجها المستخدم للصفحة المحددة التي زارها. عند استخدام حزمة workbox-routing، يمكنك إرسال قائمة بعناوين URL إلى جهاز التوجيه لتخزينها مؤقتًا، وسيخزّنها مؤقتًا وفقًا للقواعد المحدّدة على جهاز التوجيه نفسه.

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

const wb = new Workbox('/sw.js');

wb.addEventListener('activated', event => {
  // Get the current page URL + all resources the page loaded.
  const urlsToCache = [
    location.href,
    ...performance.getEntriesByType('resource').map(r => r.name),
  ];
  // Send that list of URLs to your router in the service worker.
  wb.messageSW({
    type: 'CACHE_URLS',
    payload: {urlsToCache},
  });
});

// Register the service worker after event listeners have been added.
wb.register();

لحظات مهمة في مراحل نشاط عاملي الخدمات

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

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

تستخدم الفئة Workbox طريقة العرض الأبسط هذه لدورة حياة عاملي الخدمات من خلال تقسيم جميع تسجيلات عاملي الخدمات إلى فئتَين: عامل تشغيل خاص بالمثيل ومشغّل خدمات مسجَّل وعامل خدمة خارجي:

  • مشغّل خدمات مسجَّل: عامل خدمات بدأ تثبيته نتيجة للمثيل Workbox الذي يستدعي register() أو عامل الخدمة المفعَّل حاليًا إذا لم يؤدِّ استدعاء register() إلى تشغيل حدث updatefound عند التسجيل.
  • مشغّل خدمات خارجي: مشغّل خدمات بدأ في تثبيت مثيل Workbox الذي يستدعي register() بشكل مستقل. ويحدث ذلك عادةً عندما يكون لدى المستخدم إصدار جديد من موقعك الإلكتروني مفتوحًا في علامة تبويب أخرى. عندما ينشأ حدث من مشغّل خدمات خارجي، سيتم ضبط سمة isExternal للحدث على true.

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

في المرة الأولى التي يتم فيها تثبيت عامل خدمات

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

وفي workbox-window، يمكنك التمييز بين عملية التثبيت الأولى للإصدار والتحديثات المستقبلية من خلال التحقّق من السمة isUpdate في أي من الأحداث التالية. أول عملية تثبيت لأول مرة هي "isUpdate". سيكون "false" في هذه الحالة.

const wb = new Workbox('/sw.js');

wb.addEventListener('installed', event => {
  if (!event.isUpdate) {
    // First-installed code goes here...
  }
});

wb.register();
اللحظة البارزة حدث الإجراء المقترَح
ثبَّت عامل خدمات جديد (لأول مرة). installed

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

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

بدأ مشغّل الخدمات بالتحكّم في الصفحة. controlling

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

يُرجى العِلم أنّه في المرة الأولى التي تثبِّت فيها مشغّل خدمات، لن يبدأ في التحكّم في الصفحة الحالية ما لم يتم استدعاء clients.claim() في حدث التفعيل. ويكون السلوك التلقائي هو الانتظار إلى أن يتم تحميل الصفحة التالية لبدء التحكّم.

من منظور workbox-window، يعني ذلك أنّ فعالية controlling يتم إرسالها فقط في الحالات التي يستدعي فيها مشغّل الخدمة clients.claim(). لا يتم إرسال هذا الحدث إذا سبق أن تم التحكّم في الصفحة قبل التسجيل.

انتهى مشغّل الخدمات من تفعيل. activated

كما ذُكر أعلاه، في المرة الأولى التي ينتهي فيها عامل الخدمة من تنشيطها قد يبدأ (أو لا) في التحكم في الصفحة.

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

عند العثور على إصدار مُحدَّث من مشغّل الخدمات

عندما يبدأ مشغّل خدمات جديد في التثبيت بينما يتحكم إصدار حالي في الصفحة، ستصبح السمة isUpdate لجميع الأحداث التالية true.

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

اللحظة البارزة حدث الإجراء المقترَح
ثبَّت عامل خدمات جديد (مع تحديث عامل خدمات سابق). installed

إذا لم يكن هذا أول ما ثبّته مشغّل الخدمات (event.isUpdate === true)، هذا يعني أنّه تم العثور على إصدار أحدث من عامل الخدمة وتثبيته (أي إصدار مختلف عن الإصدار الذي يتم التحكّم في الصفحة حاليًا).

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

ملاحظة: يستخدم بعض المطوّرين حدث installed لإعلام المستخدمين بتوفّر إصدار جديد من موقعهم الإلكتروني. ومع ذلك، استنادًا إلى ما إذا كنت تستدعي skipWaiting() في مشغّل خدمات التثبيت، قد يصبح مشغّل الخدمة المثبَّت نشطًا على الفور أو قد لا يصبح نشطًا. في حال إجراء اتصال مع "skipWaiting()"، من الأفضل إبلاغ المستخدمين بالتحديث بعد تفعيل مشغّل الخدمات الجديد، وإذا لم تتصل برقم skipWaiting، من الأفضل إبلاغهم بالتحديث الذي سيكون معلَّقًا في حدث الانتظار (اطّلِع على مزيد من التفاصيل أدناه).

ثبَّت عامل خدمات ولكنها متوقفة في مرحلة الانتظار. waiting

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

تحذير، من الشائع أن يطلب المطوّرون من المستخدمين إعادة تحميل الصفحة للحصول على التحديث، ولكن في كثير من الحالات، لن يؤدي إعادة تحميل الصفحة إلى تفعيل العامل المثبَّت. إذا أعاد المستخدم تحميل الصفحة وكان عامل الخدمة لا يزال منتظرًا، سيتم تنشيط حدث waiting مجددًا وستصبح السمة event.wasWaitingBeforeRegister صحيحة. يُرجى العِلم أنّنا نخطّط لتحسين هذه التجربة في إصدار مستقبلي. يُرجى متابعة المشكلة رقم 1848 لمعرفة آخر المعلومات.

يتوفر خيار آخر، وهو طلب التحديث من المستخدم وسؤاله عما إذا كان يريد الحصول على التحديث أو مواصلة الانتظار. إذا اخترت الحصول على التحديث، يمكنك استخدام postMessage() لتطلب من مشغّل الخدمات تشغيل skipWaiting(). اطّلِع على وصفة الطعام المتقدّمة عرض إمكانية إعادة تحميل الصفحة للمستخدمين للاطّلاع على مثال لذلك.

بدأ مشغّل الخدمات بالتحكّم في الصفحة. controlling

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

ملاحظة: لن يتم تنشيط الحدث controlling إذا لم يتم الاتصال بـ skipWaiting() في مشغّل الخدمات.

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

عند العثور على إصدار غير متوقع من مشغّل الخدمات

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

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

هذه لا مشكلة بشكل عام في علامة التبويب B على الرغم من ذلك، نظرًا لأنه عندما كتبت كود الإصدار 2، كنت على دراية بكيفية عمل التعليمة البرمجية v1. مع ذلك، قد يشكّل ذلك مشكلة بالنسبة إلى علامة التبويب A، لأنّه من المحتمل ألّا يتنبأ رمز الإصدار 1 بالتغييرات التي قد تطرأ على رمز الإصدار 2.

للمساعدة في التعامل مع هذه الحالات، يرسل workbox-window أيضًا أحداث مراحل النشاط عندما يرصد تحديثًا من مشغّل خدمات "خارجي"، حيث يُقصد بالخارجي فقط أي إصدار ليس الإصدار الذي سجّله المثيل Workbox الحالي.

بدءًا من الإصدار 6 من Workbox والإصدارات الأحدث، تكون هذه الأحداث مكافئة للأحداث الموثَّقة أعلاه، مع إضافة سمة isExternal: true تم ضبطها على كل كائن حدث. إذا كان تطبيق الويب يحتاج إلى تنفيذ منطق معيّن للتعامل مع مشغّل خدمات "خارجي"، يمكنك البحث عن هذه الخاصية في معالِجات الأحداث.

تجنُّب الأخطاء الشائعة

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

نعلم أنّ التطوير مع مشغّلي الخدمات قد يكون أمرًا مربكًا، وعندما تحدث أمور تختلف عن ما تتوقعه، قد يكون من الصعب معرفة السبب.

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

ولكن عند تسجيل مشغّل خدمات من خلال الفئة Workbox، سيتم إعلامك بجميع التغييرات في حالة دورة الحياة في وحدة تحكّم المطوّرين، ما سيساعد في تصحيح الأخطاء بسبب عدم توقّع الأمور.

تحذير عامل انتظار التفعيل في وحدة تحكّم Workspace-window

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

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

تحذير بشأن نافذة إطار العمل في وحدة تحكُّم للعاملين غير المتحكّمين في المؤسسة

نافذة للتواصل مع عاملي الخدمات

يتضمّن استخدام مشغّل الخدمات الأكثر تقدّمًا الكثير من المراسلات بين عامل الخدمة والنافذة. وتساعد الفئة Workbox في ذلك أيضًا من خلال توفير طريقة messageSW()، ما سيؤدي إلى postMessage() عامل الخدمة المسجّل في المثيل وتنتظر الاستجابة.

بينما يمكنك إرسال البيانات إلى مشغّل الخدمات بأي تنسيق، فإن التنسيق الذي تشاركه جميع حزم Workbox هو كائن له ثلاث خصائص (الثانيتان اختياريتان):

الموقع مطلوب؟ النوع الوصف
type نعم string

سلسلة فريدة تحدِّد هذه الرسالة

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

meta لا string في Workbox، يكون هذا هو دائمًا اسم حزمة Workbox التي ترسل الرسالة. عند إرسال الرسالة بنفسك، يمكنك حذف هذه السمة أو ضبطها على ما تريده.
payload لا * البيانات التي يتم إرسالها. وعادةً ما يكون هذا كائنًا، ولكن لا ينبغي أن يكون كذلك.

إنّ الرسائل المرسَلة عبر طريقة messageSW() تستخدم MessageChannel ليتمكّن المتلقّي من الرد عليها. للرد على رسالة، يمكنك الاتصال بالرقم event.ports[0].postMessage(response) من خلال أداة معالجة الحدث الخاصة بالرسائل. تعرض طريقة messageSW() وعدًا يلبّي أي نوع response تردّ عليه.

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

الرمز في sw.js:

const SW_VERSION = '1.0.0';

addEventListener('message', event => {
  if (event.data.type === 'GET_VERSION') {
    event.ports[0].postMessage(SW_VERSION);
  }
});

الرمز في min.js (يتم تشغيله في النافذة):

const wb = new Workbox('/sw.js');
wb.register();

const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);

إدارة حالات عدم توافق الإصدار

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

الشبكة أولاً

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

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

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

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

ذاكرة التخزين المؤقت أولاً

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

ومع ذلك، إذا تم العثور على إصدار مُحدَّث من مشغّل الخدمات وتم تفعيله عند طلب صفحتك على register() (أي أنّك تتخطّى مرحلة الانتظار عن قصد)، قد لا يكون من الآمن إرسال رسائل إليها.

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

تخطّي خطوة الانتظار

أحد اصطلاحات الاستخدام الشائع لمراسلة مشغّلي الخدمات في الوقت الفعلي هو إرسال رسالة {type: 'SKIP_WAITING'} لتوجيه عامل الخدمة المثبَّت إلى تخطّي مرحلة الانتظار وتفعيله.

بدءًا من الإصدار 6 من Workbox، يمكن استخدام طريقة messageSkipWaiting() لإرسال رسالة {type: 'SKIP_WAITING'} إلى مشغّل خدمات الانتظار المرتبط بتسجيل عامل الخدمة الحالي. ولن تفعل شيئًا بصمت إذا لم يكن هناك عامل خدمة منتظر.

الأنواع

Workbox

فئة للمساعدة في التعامل مع عمليات تسجيل العاملين في الخدمات والتحديثات والاستجابة لأحداث مراحل نشاط موظفي الخدمات.

أماكن إقامة

  • الدالة الإنشائية

    void

    ينشئ مثيلاً جديدًا لـ Workbox باستخدام عنوان URL للنص البرمجي وخيارات مشغّل الخدمات. عنوان URL للنص البرمجي وخياراته مطابِقان لتلك المستخدمة عند استدعاء navigator.serviceWorker.register(scriptURL, options).

    تبدو الدالة constructor على النحو التالي:

    (scriptURL: string|TrustedScriptURL,registerOptions?: object)=> {...}

    • scriptURL

      سلسلة|TrustScriptURL

      النص البرمجي لمشغِّل الخدمات المرتبط بهذا المثيل. يُسمح باستخدام TrustedScriptURL.

    • registerOptions

      الكائن اختياري

  • نشطة

    Promise<ServiceWorker>

  • التَّحَكُّمْ

    Promise<ServiceWorker>

  • getSW

    void

    يتم حلها باستخدام مرجع إلى مشغّل خدمات يتطابق مع عنوان URL للنص البرمجي لهذه الحالة فور توفّره.

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

    تبدو الدالة getSW على النحو التالي:

    ()=> {...}

    • returns

      Promise<ServiceWorker>

  • messageSW

    void

    لإرسال عنصر البيانات الذي تم تمريره إلى مشغّل الخدمات المسجَّل في هذا المثيل (عبر workbox-window.Workbox#getSW) والتعامل معه بالاستجابة (إن توفّرت)

    يمكن ضبط الاستجابة في معالج الرسائل في مشغّل الخدمات من خلال استدعاء event.ports[0].postMessage(...)، والذي سيحلّ الوعد الذي يعرضه messageSW(). إذا لم يتم تحديد أي رد، فلن يتم حل الوعد أبدًا.

    تبدو الدالة messageSW على النحو التالي:

    (data: object)=> {...}

    • البيانات

      كائن

      عنصر لإرساله إلى مشغّل الخدمات

    • returns

      وعد<any>

  • messageSkipWaiting

    void

    لإرسال رسالة {type: 'SKIP_WAITING'} إلى مشغّل الخدمات الموجود حاليًا في حالة waiting المرتبطة بالتسجيل الحالي.

    وإذا لم يكن هناك تسجيل حالي أو لم يكن هناك مشغّل خدمات هو waiting، لن يكون لذلك أي تأثير لأنّ تسمية هذا الإجراء.

    تبدو الدالة messageSkipWaiting على النحو التالي:

    ()=> {...}

  • register

    void

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

    تبدو الدالة register على النحو التالي:

    (options?: object)=> {...}

    • الخيارات

      الكائن اختياري

      • فوري

        منطقية اختيارية

    • returns

      Promise<ServiceWorkerRegistration>

  • تحديث

    void

    يبحث عن تحديثات مشغّل الخدمات المسجَّل.

    تبدو الدالة update على النحو التالي:

    ()=> {...}

    • returns

      Promise<void>

WorkboxEventMap

أماكن إقامة

WorkboxLifecycleEvent

أماكن إقامة

  • isExternal

    منطقية اختيارية

  • isUpdate

    منطقية اختيارية

  • originalEvent

    الحدث اختياري

  • sw

    ServiceWorkers اختياري

  • الاستهداف

    WorkboxEventTarget اختيارية

  • كتابة

    typeOperator

WorkboxLifecycleEventMap

أماكن إقامة

WorkboxLifecycleWaitingEvent

أماكن إقامة

  • isExternal

    منطقية اختيارية

  • isUpdate

    منطقية اختيارية

  • originalEvent

    الحدث اختياري

  • sw

    ServiceWorkers اختياري

  • الاستهداف

    WorkboxEventTarget اختيارية

  • كتابة

    typeOperator

  • wasWaitingBeforeRegister

    منطقية اختيارية

WorkboxMessageEvent

أماكن إقامة

  • البيانات

    أي فلتر

  • isExternal

    منطقية اختيارية

  • originalEvent

    حدث

  • ports

    typeOperator

  • sw

    ServiceWorkers اختياري

  • الاستهداف

    WorkboxEventTarget اختيارية

  • كتابة

الطُرق

messageSW()

workbox-window.messageSW(
  sw: ServiceWorker,
  data: object,
)

ترسل عنصر بيانات إلى مشغّل الخدمات من خلال postMessage ويتم حلّها بالاستجابة (إن توفّرت).

يمكن ضبط الاستجابة في معالج الرسائل في مشغّل الخدمات من خلال استدعاء event.ports[0].postMessage(...)، والذي سيحلّ الوعد الذي يعرضه messageSW(). إذا لم يتم تحديد أي رد، فلن يتم حل الوعد.

المَعلمات

  • sw

    ServiceWorker

    مشغّل الخدمات لإرسال الرسالة إليه

  • البيانات

    كائن

    كائن لإرساله إلى مشغّل الخدمات.

المرتجعات

  • وعد<any>