שימוש בחלון של תיבת עבודה

מודול תיבת עבודה אחד שעדיין לא קיבל כיסוי נרחב בתיעוד הזה הוא workbox-window, שהוא קבוצת מודולים שמיועדת לפעול ב-window. המטרות של המודול הזה הן:

  • כדי לפשט את תהליך הרישום והעדכונים של Service Worker, הוא עוזר למפתחים לזהות רגעים קריטיים במחזור החיים של Service Worker, וכך קל יותר להגיב לרגעים האלה.
  • כדי למנוע ממפתחים לבצע טעויות נפוצות, כמו רישום של Service Worker בהיקף שגוי.
  • כדי לפשט את העברת ההודעות בין window לבין היקף קובץ השירות.

ייבוא ושימוש ב-workbox-window

הייצוא שבו תשתמש בתדירות הגבוהה ביותר מ-workbox-window הוא המחלקה Workbox. ניתן לייבא אותה בצומת או מה-CDN בדף אינטרנט.

יצירת חבילה מקומית

אם שרשרת הכלים כוללת קובץ Bundle כמו webpack או נכס-על, אפשר לכלול workbox-window בחבילה באופן מקומי.

קודם כול, מתקינים את workbox-window כתלוי ייצור של האפליקציה:

npm install workbox-window --save

לאחר מכן, ב-JavaScript של האפליקציה, אפשר import את המחלקה Workbox מתוך workbox-window:

<script type="module">
import {Workbox} from 'workbox-window';

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

  wb.register();
}
</script>

אמנם השדה workbox-window קטן למדי, אבל אפשר לפצל אותו מהלוגיקה העיקרית של האפליקציה של האתר באמצעות import דינמי, שיכול להקטין את גודל החבילה הראשית של הדף:

<script type="module">
if ('serviceWorker' in navigator) {
  const {Workbox} = await import('workbox-window');

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

שימוש ב-CDN

זו אמנם לא הגישה המומלצת, אבל דרך קלה יותר להשתמש ב-workbox-window היא לייבא מ-CDN:

<script type="module">
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.2.0/workbox-window.prod.mjs';

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

    wb.register();
  }
</script>

תוכלו לראות שהרכיב <script> בדוגמה שלמעלה משתמש במאפיין type="module". צריך לבצע את הפעולה הזו כשרוצים להשתמש בהצהרות import סטטיות בדפדפן ללא שלב build. כל הדפדפנים העיקריים שתומכים ב-Service Workers תומכים גם במודולים של JavaScript, כך שאפשר להציג את הקוד הזה לכל דפדפן. כלומר, דפדפנים ישנים יתעלמו מרכיבי <script> עם ערך המאפיין type של "module".

רישום Service Worker

רישום קובץ שירות (service worker) ב-workbox-window מתבצע ב-method register של המחלקה Workbox, באופן הבא:

import {Workbox} from 'workbox-window';

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

אולי זה דומה לרישום של קובץ שירות (service worker) בעצמכם באמצעות navigator.serviceWorker.register. עם זאת, Workbox.register ימתין עד לאירוע window load לפני הרישום של קובץ השירות (service worker). עדיף לבצע את הפעולה הזאת במצבים שבהם יש מעורבות מראש במטמון, כדי להימנע מחלוקת רוחב פס שעלולה לעכב את ההפעלה של הדף.

תקשורת בין window לבין ההיקף של קובץ השירות (service worker)

ל-Service Workers יש היקף משלהם הנפרד מ-window, ויש להם גישה רק לקבוצת משנה של ממשקי ה-API שזמינים ב-window. עם זאת, ניתן לתקשר בין window לבין קובץ השירות (service worker). workbox-window מאפשר תקשורת קלה יותר בין שני היקפי ההרשאות באמצעות שיטת messageSW של המודול workbox-window.

תיבת העבודה משתמשת בפורמט ספציפי עבור הודעות היא אובייקט עם המאפיינים הבאים:

  • type היא מחרוזת ייחודית שמזהה את ההודעה. הפורמט צריך להיות באותיות רישיות עם קווים תחתונים שמפרידים בין מילים (לדוגמה, CACHE_URLS).
  • meta היא מחרוזת אופציונלית שמייצגת את שם חבילת תיבת העבודה ששולחת את ההודעה, ולרוב היא מושמטת.
  • payload הוא פרמטר אופציונלי שמייצג את הנתונים שרוצים לשלוח. הוא יכול להיות כל סוג של נתונים.

לפניכם דוגמה לאופן שבו messageSW פועל, החל מהקוד שב-Service Worker:

// sw.js
const SW_VERSION = '1.0.0';

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

לאחר מכן הקוד הבא בדף האינטרנט:

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

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

יש מקרים רבים שבהם תקשורת בין Service Worker לבין window יכולה להיות מועילה, כמו הודעה למשתמש כשיש עדכון זמין של Service Worker. המתכון הזה מסתמך על שיטת עזר מיוחדת עבור self.skipWaiting בשם messageSkipWaiting, ששולחת הודעה עם הערך type של SKIP_WAITING.