في بعض السيناريوهات، قد يحتاج عامل الخدمة إلى التواصل بشكل استباقي مع أي من علامات التبويب النشطة التي يتحكّم فيها لإعلامها بحدث معيّن. تشمل الأمثلة ما يلي:
- إبلاغ الصفحة عند تثبيت إصدار جديد من الخدمة العاملة، حتى تتمكّن الصفحة من عرض زر "تحديث لإعادة تحميل الصفحة" للمستخدم للوصول إلى الوظيفة الجديدة على الفور
- إبلاغ المستخدم بتغيير في البيانات المخزّنة مؤقتًا حدث على جانب الخدمة العاملة، وذلك من خلال عرض إشارة، مثل: "التطبيق جاهز الآن للعمل بلا إنترنت" أو "توفّر إصدار جديد من المحتوى"
سنُطلق على هذه الأنواع من حالات الاستخدام اسم "حالات الاستخدام التي لا يحتاج فيها عامل الخدمة إلى تلقّي رسالة من الصفحات لبدء عملية "بث التعديلات"". في هذا الدليل، سنراجع مختلف طُرق تنفيذ هذا النوع من الاتصالات بين الصفحات وخدمات Worker، وذلك باستخدام واجهة برمجة التطبيقات المعتادة للمتصفّح ومكتبة Workbox.
حالات الإنتاج
Tinder
يستخدم تطبيق Tinder PWA workbox-window
للاستماع إلى
اللحظات المهمة في دورة حياة worker الخدمة من الصفحة ("مثبّت" و"مُدار" و
"مفعّل"). بهذه الطريقة، عندما يتم تشغيل عامل خدمة جديد، يعرض بانر "توفّر تحديث"
، حتى يتمكّن المستخدمون من إعادة تحميل تطبيق الويب التقدّمي والوصول إلى أحدث الميزات:
Squoosh
في تطبيق Squoosh PWA، عندما يُخزِّن عامل الخدمة كل مواد العرض اللازمة لتشغيل التطبيق بلا إنترنت، يُرسِل رسالة إلى الصفحة لعرض إشعار ناتج عن رمز مصغر "جاهز للعمل بلا إنترنت"، ما يُعلِم المستخدم بهذه الميزة:
استخدام Workbox
الاستماع إلى أحداث دورة حياة worker الخدمة
workbox-window
يوفّر واجهة مباشرة للاستماع إلى أحداث مهمة في دورة حياة مشغّل الخدمات.
في الخلفية، تستخدم المكتبة واجهات برمجة تطبيقات من جهة العميل، مثل
updatefound
وstatechange
وتوفّر مستمعي أحداث من مستوى أعلى في عنصر workbox-window
، ما يسهّل على
المستخدِم استخدام هذه الأحداث.
يتيح لك رمز الصفحة التالي رصد كل مرة يتم فيها تثبيت إصدار جديد من الخدمة العاملة، كي تتمكّن من إبلاغ المستخدم بذلك:
const wb = new Workbox('/sw.js');
wb.addEventListener('installed', (event) => {
if (event.isUpdate) {
// Show "Update App" banner
}
});
wb.register();
إبلاغ الصفحة بالتغييرات في بيانات ذاكرة التخزين المؤقت
توفّر حزمة Workbox
workbox-broadcast-update
طريقة قياسية لإشعار عملاء النوافذ بأنّه تم تعديل استجابة محفوظة في ذاكرة التخزين المؤقت. ويُعدّ
هذا الإجراء هو الأكثر استخدامًا مع استراتيجية StaleWhileRevalidate.
لبثّ التحديثات، أضِف broadcastUpdate.BroadcastUpdatePlugin
إلى خيارات استراتيجيتك في
جانب worker service:
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {BroadcastUpdatePlugin} from 'workbox-broadcast-update';
registerRoute(
({url}) => url.pathname.startsWith('/api/'),
new StaleWhileRevalidate({
plugins: [
new BroadcastUpdatePlugin(),
],
})
);
في تطبيق الويب، يمكنك الاستماع إلى هذه الأحداث على النحو التالي:
navigator.serviceWorker.addEventListener('message', async (event) => {
// Optional: ensure the message came from workbox-broadcast-update
if (event.data.meta === 'workbox-broadcast-update') {
const {cacheName, updatedUrl} = event.data.payload;
// Do something with cacheName and updatedUrl.
// For example, get the cached content and update
// the content on the page.
const cache = await caches.open(cacheName);
const updatedResponse = await cache.match(updatedUrl);
const updatedText = await updatedResponse.text();
}
});
استخدام واجهات برمجة تطبيقات المتصفّح
إذا لم تكن الوظيفة التي يوفّرها Workbox كافية لتلبية احتياجاتك، استخدِم واجهات برمجة التطبيقات التالية للمتصفّح لتنفيذ "عمليات نشر التحديثات":
واجهة برمجة التطبيقات Broadcast Channel API
ينشئ مشغّل الخدمة BroadcastChannel
object ويبدأ بإرسال
الرسائل إليه. يمكن لأي سياق (مثل الصفحة) مهتم بتلقّي هذه الرسائل إنشاء مثيل لعنصر
BroadcastChannel
وتنفيذ معالِج رسائل لتلقّي الرسائل.
لإعلام الصفحة عند تثبيت عامل خدمة جديد، استخدِم الرمز التالي:
// Create Broadcast Channel to send messages to the page
const broadcast = new BroadcastChannel('sw-update-channel');
self.addEventListener('install', function (event) {
// Inform the page every time a new service worker is installed
broadcast.postMessage({type: 'CRITICAL_SW_UPDATE'});
});
تستمع الصفحة إلى هذه الأحداث من خلال الاشتراك في sw-update-channel
:
// Create Broadcast Channel and listen to messages sent to it
const broadcast = new BroadcastChannel('sw-update-channel');
broadcast.onmessage = (event) => {
if (event.data && event.data.type === 'CRITICAL_SW_UPDATE') {
// Show "update to refresh" banner to the user.
}
};
هذه تقنية بسيطة، ولكنّها تقتصر على المتصفّحات: في وقت كتابة هذه المقالة، لا يتيح Safari استخدام واجهة برمجة التطبيقات هذه.
Client API
توفّر Client API طريقة مباشرة
للتواصل مع عملاء متعدّدين من خلال الخدمة العاملة من خلال تكرار صفيف من
عناصر Client
.
استخدِم رمز الخدمة التالي لإرسال رسالة إلى علامة التبويب التي تم التركيز عليها مؤخرًا:
// Obtain an array of Window client objects
self.clients.matchAll(options).then(function (clients) {
if (clients && clients.length) {
// Respond to last focused tab
clients[0].postMessage({type: 'MSG_ID'});
}
});
تنفِّذ الصفحة معالِج رسائل لمنع وصول هذه الرسائل:
// Listen to messages
navigator.serviceWorker.onmessage = (event) => {
if (event.data && event.data.type === 'MSG_ID') {
// Process response
}
};
تشكّل Client API خيارًا رائعًا لحالات مثل بث المعلومات إلى علامات تبويب نشطة متعددة. تتوفّر واجهة برمجة التطبيقات في جميع المتصفحات الرئيسية، ولكن لا تتوفّر بعض طرقها. يُرجى التحقّق من توافق المتصفّح قبل استخدامه.
قناة الرسائل
تتطلّب قناة الرسائل
خطوة إعداد أولية، وذلك من خلال تمرير منفذ من الصفحة إلى الخدمة العاملة، لإنشاء
قناة تواصل بينهما. تنشئ الصفحة مثيلًا لعنصر MessageChannel
وتُمرِّر بوابة إلى مشغّل الخدمات من خلال واجهة postMessage()
:
const messageChannel = new MessageChannel();
// Init port
navigator.serviceWorker.controller.postMessage({type: 'PORT_INITIALIZATION'}, [
messageChannel.port2,
]);
تستمع الصفحة إلى الرسائل من خلال تنفيذ معالِج "onmessage" على هذا المنفذ:
// Listen to messages
messageChannel.port1.onmessage = (event) => {
// Process message
};
يتلقّى مشغّل الخدمة المنفذ ويحفظ إشارة إليه:
// Initialize
let communicationPort;
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'PORT_INITIALIZATION') {
communicationPort = event.ports[0];
}
});
ومن هذه النقطة، يمكنه إرسال الرسائل إلى الصفحة من خلال استدعاء postMessage()
في الإشارة إلى
البروتوكول:
// Communicate
communicationPort.postMessage({type: 'MSG_ID' });
قد يكون تنفيذ MessageChannel
أكثر تعقيدًا، بسبب الحاجة إلى بدء تشغيل المنافذ، ولكنه
متوافق مع جميع المتصفحات الرئيسية.
الخطوات التالية
في هذا الدليل، اطّلعنا على حالة معيّنة من تواصل Window مع الخدمة العاملة: "نشر التعديلات". تشمل الأمثلة التي تم استكشافها الاستماع إلى أحداث دورة حياة العامل في الخدمة المهمة، والتواصل مع الصفحة بشأن التغييرات في المحتوى أو البيانات المخزّنة مؤقتًا. يمكنك التفكير في حالات استخدام أكثر إثارة للاهتمام حيث يتواصل عامل الخدمة بشكل استباقي مع الصفحة، بدون تلقّي أي رسالة في السابق.
لمزيد من أنماط تواصل Window مع الخدمة العاملة، اطّلِع على:
- دليل التخزين المؤقت الإلزامي: استدعاء مشغّل خدمة من الصفحة لتخزين الموارد مؤقتًا مسبقًا (على سبيل المثال، في سيناريوهات التحميل المُسبَق).
- التواصل الثنائي الاتجاه: تفويض مهمة إلى عامل خدمة (مثل عملية تنزيل كبيرة) وإبقاء الصفحة على اطّلاع بالتقدّم المحرز