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

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

רקע

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

במאמר הזה מפורט המצב הנוכחי של התמיכה במודול ES ב-Service Workers בדפדפנים נפוצים, יחד עם כמה דברים שכדאי להימנע מהם, ושיטות מומלצות קוד של קובץ שירות (service worker) שתואם לאחור.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

בזמן ש-Chrome ו-Edge גרסה 89 ומעלה תומכים בייבוא של מפות, כרגע לא ניתן להשתמש עם שירות ב-Google Workspace for Education.

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

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

נוספה תמיכה ב-Safari Technology Preview 122 Release, ומפתחים אמורים לראות שהפונקציונליות הזו תפורסם של 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 Worker באמצעות bundler תואם למודול ES כדי ליצור Service Worker שכולל את כל קוד המודול מוטבע, ויעבוד בדפדפנים ישנים יותר. לחלופין, אם המודולים שניסית לייבא הם כבר זמין בחבילה ב- IIFE או פורמטים של UMD, אפשר לייבא אותם באמצעות importScripts()

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

_צילום: Vlado Paunovic ב-Unbounce_