בחלק מהתרחישים, יכול להיות ש-service worker יצטרך לתקשר באופן יזום עם כל אחד מהכרטיסיות הפעילות שהוא שולט בהן כדי להודיע על אירוע מסוים. דוגמאות:
- להודיע לדף כשגרסה חדשה של ה-service worker הותקנה, כדי שהדף יוכל להציג למשתמש את הלחצן עדכון לרענון כדי לגשת לפונקציונליות החדשה באופן מיידי.
- להודיע למשתמש על שינוי בנתונים שנשמרו במטמון שהתרחש בצד של ה-service worker, על ידי הצגת אינדיקציה, כמו: "האפליקציה מוכנה עכשיו לעבודה אופליין" או "יש גרסה חדשה של התוכן".
נתייחס לתרחישים לדוגמה שבהם שירות ה-worker לא צריך לקבל הודעה מהדף כדי להתחיל תקשורת בתור 'עדכונים לשידור'. במדריך הזה נסקור דרכים שונות להטמעת סוג התקשורת הזה בין דפים לשירותי עבודה, באמצעות ממשקי API רגילים לדפדפנים וספריית Workbox.
בקשות תמיכה בסביבת ייצור
Tinder
אפליקציית Tinder ל-PWA משתמשת ב-workbox-window
כדי להאזין לדפים לרגעים חשובים במחזור החיים של ה-service worker ('מותקן', 'מוגדר' ו'מופעל'). כך, כשעומד להיכנס לפעולה עובד שירות חדש, הוא מציג באנר עם הכיתוב עדכון זמין כדי שהמשתמשים יוכלו לרענן את אפליקציית ה-PWA ולגשת לתכונות העדכניות ביותר:
Squoosh
ב-Squoosh PWA, כשעובד השירות שומר במטמון את כל הנכסים הנחוצים כדי שהאפליקציה תפעל במצב אופליין, הוא שולח הודעה לדף כדי להציג הודעה קופצת עם הכיתוב 'מוכן לעבודה במצב אופליין', כדי להודיע למשתמש על התכונה:
שימוש ב-Workbox
האזנה לאירועים במחזור החיים של שירות ה-worker
workbox-window
מספק ממשק פשוט להאזנה לאירועים חשובים במחזור החיים של קובץ השירות.
בספרייה נעשה שימוש בממשקי API בצד הלקוח, כמו updatefound
ו-statechange, ומספקים מאזינים לאירועים ברמה גבוהה יותר באובייקט workbox-window
, כדי להקל על המשתמש לצרוך את האירועים האלה.
קוד הדף הבא מאפשר לזהות בכל פעם שגרסה חדשה של ה-service worker מותקנת, כדי שתוכלו להודיע על כך למשתמש:
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
לאפשרויות האסטרטגיה בצד של ה-service worker:
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();
}
});
שימוש בממשקי API של דפדפנים
אם הפונקציונליות של Workbox לא מספיקה לצרכים שלכם, תוכלו להשתמש בממשקי ה-API הבאים לדפדפנים כדי להטמיע 'עדכונים לשידור':
Broadcast Channel API
קובץ השירות יוצר אובייקט BroadcastChannel ומתחיל לשלוח אליו הודעות. כל הקשר (למשל דף) שמעוניין לקבל את ההודעות האלה יכול ליצור אובייקט 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 לא תומך ב-API הזה.
Client API
Client API מספק דרך פשוטה לתקשר עם מספר לקוחות מה-service worker, על ידי איטרציה על מערך של אובייקטים מסוג 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
}
};
ממשק ה-API ללקוח הוא פתרון מצוין למקרים כמו שידור מידע לכמה כרטיסיות פעילות. כל הדפדפנים העיקריים תומכים ב-API, אבל לא כל השיטות שלו נתמכות. לפני שמשתמשים ב-Google Fonts, צריך לבדוק את תמיכת הדפדפן.
ערוץ הודעות
כדי להשתמש ב-Message Channel, צריך לבצע שלב הגדרה ראשוני: העברת יציאה מהדף ל-service worker כדי ליצור ביניהם ערוץ תקשורת. הדף יוצר מופע של אובייקט 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
};
קובץ ה-service worker מקבל את היציאה ושומר הפניה אליה:
// 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
תהיה מורכבת יותר בגלל הצורך לאתחל את היציאות, אבל כל הדפדפנים העיקריים תומכים בה.
השלבים הבאים
במדריך הזה התמקדנו באירוע ספציפי של תקשורת בין חלון לבין עובד שירות: 'שידור עדכונים'. הדוגמאות כוללות הקשבה לאירועים חשובים במחזור החיים של עובד השירות, ודיווח לדף על שינויים בתוכן או בנתונים ששמורים במטמון. אפשר לחשוב על תרחישי לדוגמה מעניינים יותר שבהם עובד השירות מתקשר עם הדף באופן יזום, בלי לקבל הודעה מראש.
דפוסים נוספים של תקשורת בין חלון לבין עובד שירות זמינים במאמרים הבאים:
- מדריך לשימוש חובה במטמון: קריאה לקובץ שירות (service worker) מהדף כדי לשמור משאבים במטמון מראש (למשל בתרחישים של אחסון מראש).
- תקשורת דו-כיוונית: הענקת גישה למשימות ל-service worker (למשל, הורדה כבדה) ועדכון הדף לגבי ההתקדמות.