מודולים של ES ב-Service Workers

חלופה מודרנית ל-importScripts()‎.

רקע

מודולים של ES הם כבר זמן מה המועדפים על המפתחים. בנוסף למספר יתרונות אחרים, הם מציעים הבטחה לפורמט מודול אוניברסלי שבו אפשר להפיץ קוד משותף פעם אחת ולהריץ אותו בדפדפנים ובסביבות זמן ריצה חלופיות כמו Node.js. כל הדפדפנים המודרניים מציעים תמיכה מסוימת במודולים של ES, אבל לא כולם מציעים תמיכה בכל מקום שבו אפשר להריץ קוד. באופן ספציפי, התמיכה בייבוא של מודולים של ES בתוך service worker של דפדפן רק מתחילה להיות זמינה באופן נרחב יותר.

במאמר הזה נסביר על המצב הנוכחי של התמיכה במודולים של ES ב-Service Worker בדפדפנים נפוצים, וגם על כמה דברים שכדאי להימנע מהם ושיטות מומלצות להעברת קוד של Service Worker שתואם לגרסאות קודמות.

תרחישים לדוגמה

תרחיש השימוש האידיאלי למודולים של ES בתוך קובצי שירות (service workers) הוא לטעינת ספרייה מודרנית או קוד הגדרה שמשותף עם סביבות זמן ריצה אחרות שתומכות במודולים של ES.

לפני שהיו מודולים של ES, כדי לשתף קוד בדרך הזו היה צריך להשתמש בפורמטים ישנים יותר של מודולים "אוניברסליים" כמו UMD, שכוללים קטעי קוד סטנדרטיים מיותרים, ולכתוב קוד שביצע שינויים במשתנים שחשופים באופן גלובלי.

סקריפטים שיובאו באמצעות מודולים של ES יכולים להפעיל את תהליך העדכון של ה-service worker אם התוכן שלהם משתנה, בהתאם להתנהגות של importScripts().

מגבלות נוכחיות

ייבוא סטטי בלבד

אפשר לייבא מודולים של ES באחת משתי דרכים: באופן סטטי, באמצעות התחביר import ... from '...', או באופן דינמי, באמצעות השיטה import(). בתוך service worker, כרגע יש תמיכה רק בתחביר הסטטי.

המגבלה הזו דומה למגבלה דומה שחלה על השימוש ב-importScripts(). קריאות דינמיות ל-importScripts() לא פועלות בתוך Service Worker, וכל הקריאות ל-importScripts(), שהן סינכרוניות מטבען, חייבות להסתיים לפני ש-Service Worker מסיים את שלב ה-install שלו. ההגבלה הזו מבטיחה שהדפדפן יכיר את כל קוד ה-JavaScript שנדרש להטמעה של Service Worker במהלך ההתקנה, ויוכל לשמור אותו במטמון באופן משתמע.

יכול להיות שבעתיד ההגבלה הזו תוסר, ויתאפשר לייבא מודולים דינמיים של ES. בינתיים, חשוב להשתמש רק בתחביר הסטטי בתוך service worker.

מה לגבי עובדים אחרים?

התמיכה במודולים של ES ב-workers "ייעודיים" – אלה שנבנו באמצעות new Worker('...', {type: 'module'}) – נפוצה יותר, ונתמכת ב-Chrome וב-Edge מאז גרסה 80, וגם בגרסאות האחרונות של Safari. ייבוא של מודולי ES סטטיים ודינמיים נתמך ב-Dedicated Workers.

ב-Chrome וב-Edge יש תמיכה במודולים של ES ב-shared workers מאז גרסה 83, אבל אין תמיכה בדפדפנים אחרים בשלב הזה.

אין תמיכה במפות ייבוא

מפות ייבוא מאפשרות לסביבות זמן ריצה לשכתב מפרטי מודולים, למשל, להוסיף בתחילת הכתובת את כתובת ה-URL של רשת ה-CDN המועדפת שממנה אפשר לטעון את מודולי ה-ES.

למרות שגרסה 89 ומעלה של Chrome ו-Edge תומכת במפות ייבוא, כרגע אי אפשר להשתמש בהן עם קובצי Service Worker.

תמיכה בדפדפנים

מודולים של ES ב-service workers נתמכים ב-Chrome וב-Edge החל מגרסה 91.

התמיכה ב-Safari נוספה בגרסת Technology Preview 122, והמפתחים יכולים לצפות שהפונקציונליות הזו תשוחרר בגרסה היציבה של Safari בעתיד.

קוד לדוגמה

זו דוגמה בסיסית לשימוש במודול ES משותף בהקשר של אפליקציית אינטרנט window, תוך רישום של Service Worker שמשתמש באותו מודול ES:

// Inside config.js:
export const cacheName = 'my-cache';
// Inside your web app:
<script type="module">
  import {cacheName} from './config.js';
  // Do something with cacheName.

  await navigator.serviceWorker.register('es-module-sw.js', {
    type: 'module',
  });
</script>
// Inside es-module-sw.js:
import {cacheName} from './config.js';

self.addEventListener('install', (event) => {
  event.waitUntil((async () => {
    const cache = await caches.open(cacheName);
    // ...
  })());
});

תאימות לדור קודם

הדוגמה שלמעלה תעבוד מצוין אם כל הדפדפנים יתמכו במודולים של ES ב-service workers, אבל נכון למועד כתיבת המאמר הזה, זה לא המצב.

כדי להתאים לדפדפנים שאין להם תמיכה מובנית, אתם יכולים להריץ את הסקריפט של ה-service worker דרך כלי לאריזה תואם למודול ES כדי ליצור service worker שכולל את כל קוד המודול בתוך השורה, ויפעל בדפדפנים ישנים יותר. לחלופין, אם המודולים שאתם מנסים לייבא כבר זמינים בפורמטים IIFE או UMD, אתם יכולים לייבא אותם באמצעות importScripts().

אחרי שיהיו לכם שתי גרסאות של ה-service worker – אחת שמשתמשת במודולים של ES והשנייה שלא – תצטרכו לזהות במה הדפדפן הנוכחי תומך ולרשום את הסקריפט המתאים של ה-service worker. השיטות המומלצות לזיהוי תמיכה משתנות כל הזמן, אבל אפשר לעקוב אחרי הדיון בבעיה הזו ב-GitHub כדי לקבל המלצות.