في بعض السيناريوهات، قد يحتاج عامل الخدمة إلى التواصل بشكل استباقي مع أي من علامات التبويب النشطة التي يتحكّم فيها لإعلامها بحدث معيّن. تشمل الأمثلة ما يلي:
- إبلاغ الصفحة بتثبيت إصدار جديد من مشغّل الخدمات، حتى تتمكّن الصفحة من عرض الزر "تحديث لإعادة التحميل" للمستخدم للوصول إلى الوظيفة الجديدة على الفور.
- إبلاغ المستخدم بتغيير في البيانات المخزّنة مؤقتًا حدث على جانب الخدمة العاملة، وذلك من خلال عرض إشارة، مثل: "التطبيق جاهز الآن للعمل بلا إنترنت" أو "توفّر إصدار جديد من المحتوى"
سنُطلق على هذه الأنواع من حالات الاستخدام اسم "حالات الاستخدام التي لا يحتاج فيها عامل الخدمة إلى تلقّي رسالة من الصفحات لبدء عملية "بث التعديلات"". في هذا الدليل، سنراجع طُرقًا مختلفة لتنفيذ هذا النوع من الاتصال بين الصفحات ومشغّلي الخدمات، باستخدام واجهات برمجة التطبيقات العادية للمتصفح ومكتبة Workbox.
حالات الإنتاج
Tinder
يستخدم تطبيق Tinder PWA workbox-window
للاستماع إلى أهم لحظات مراحل نشاط عاملي الخدمات من الصفحة ("تم تثبيته" و"تم التحكّم فيه" و"تم التفعيل"). بهذه الطريقة، عندما يتم تشغيل مشغّل خدمات جديد، يعرض بانر "التحديث متاح"
ليتمكّن المستخدم من إعادة تحميل تطبيق الويب التقدّمي (PWA) والوصول إلى أحدث الميزات:
قرع
في تطبيق 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 مع الخدمة العاملة، اطّلِع على:
- دليل التخزين المؤقت الإلزامي: استدعاء مشغّل خدمة من الصفحة لتخزين الموارد مؤقتًا مسبقًا (على سبيل المثال، في سيناريوهات التحميل المُسبَق).
- التواصل المتبادل: تفويض مهمة إلى عامل خدمة (على سبيل المثال، عملية تنزيل مكثفة)، وإبقاء الصفحة على اطلاع بمستوى التقدم.