חלופה מודרנית ל-importScripts().
רקע
מודולים של ES הם פופולריים בקרב מפתחים כבר זמן מה. בנוסף למספר יתרונות אחרים, הן מציעות פורמט מודול אוניברסלי שבו אפשר לפרסם קוד משותף פעם אחת ולהריץ אותו בדפדפנים ובסביבות זמן ריצה חלופיות כמו Node.js. כל הדפדפנים המודרניים מציעים תמיכה מסוימת במודולים של ES, אבל לא כולם מציעים תמיכה בכל מקום שבו אפשר להריץ קוד. באופן ספציפי, התמיכה בייבוא מודולים של ES בתוך service worker של הדפדפן רק מתחילה להיות זמינה באופן נרחב יותר.
במאמר הזה מפורט המצב הנוכחי של תמיכה במודולים של ES ב-service workers בדפדפנים נפוצים, יחד עם כמה דברים שחשוב להימנע מהם ושיטות מומלצות לשליחת קוד של service worker שתואם לאחור.
תרחישים לדוגמה
התרחיש האידיאלי לשימוש במודולים של ES בתוך שירותי העבודה הוא לטעינה של ספרייה מודרנית או קוד תצורה ששותף עם סביבות זמן ריצה אחרות שתומכות במודולים של ES.
לפני מודולי ES, כדי לשתף קוד באופן הזה היה צריך להשתמש בפורמטים ישנים יותר של מודולים 'אוניברסליים' כמו UMD, שכוללים קוד סטנדרטי מיותר, ולכתוב קוד שמבצע שינויים במשתנים שגלויים לכולם.
סקריפטים שיובאו באמצעות מודולים של ES יכולים להפעיל את תהליך העדכון של ה-service worker אם התוכן שלהם משתנה, בהתאם להתנהגות של importScripts()
.
המגבלות הנוכחיות
ייבוא סטטי בלבד
אפשר לייבא מודולים של ES באחת משתי דרכים: סטטית, באמצעות התחביר import ... from '...'
, או דינמית, באמצעות השיטה import()
. בתוך שירות עובד, רק התחביר הסטטי נתמך כרגע.
ההגבלה הזו דומה להגבלה דומה שחלה על השימוש ב-importScripts()
. קריאות דינמיות ל-importScripts()
לא פועלות בתוך שירות עובד, וכל הקריאות ל-importScripts()
, שהן אסינכרוניות מטבען, חייבות להסתיים לפני ששירות העובד משלים את השלב install
. ההגבלה הזו מבטיחה שהדפדפן יודע על כל קוד ה-JavaScript שנחוץ להטמעת ה-service worker במהלך ההתקנה, ויכול לשמור אותו במטמון באופן משתמע.
יכול להיות שבסופו של דבר נבטל את ההגבלה הזו, ונאפשר ייבוא של מודולים דינמיים של ES. בינתיים, חשוב לוודא שאתם משתמשים בתחביר הסטטי רק בתוך שירות עובד.
מה לגבי עובדים אחרים?
התמיכה במודולים של ES ב'עובדים ייעודיים' – אלה שנוצרו באמצעות new Worker('...', {type: 'module'})
– רחבה יותר, והיא קיימת ב-Chrome וב-Edge מ-גרסה 80, וגם בגרסאות האחרונות של Safari.
אפשר לייבא מודולים סטטיים ודינמיים של ES בעובדים ייעודיים.
ב-Chrome וב-Edge יש תמיכה במודולים של ES בעובדים משותפים מגרסה 83, אבל בשלב זה אין תמיכה בדפדפנים אחרים.
אין תמיכה בייבוא מפות
מפות ייבוא מאפשרות לסביבות זמן ריצה לשכתב את מפרטי המודולים, למשל, להוסיף לתחילת כתובת ה-URL של CDN מועדף שממנו אפשר לטעון את המודולים של ES.
דפדפני Chrome ו-Edge מגרסה 89 ואילך תומכים בייבוא מפות, אבל אי אפשר להשתמש בהם כרגע עם שירותי עובדים.
תמיכה בדפדפנים
יש תמיכה במודולים של ES ב-service workers ב-Chrome וב-Edge החל מגרסה 91.
התמיכה ב-Safari נוספה בגרסה 122 של Technology Preview, ומפתחים יכולים לצפות שהפונקציונליות הזו תשוחרר בגרסה היציבה של Safari בעתיד.
קוד לדוגמה
זוהי דוגמה בסיסית לשימוש במודול ES משותף בהקשר window
של אפליקציית אינטרנט, תוך רישום של עובד שירות שמשתמש באותו מודול 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 כדי לקבל המלצות.
_צילום: Vlado Paunovic ב-Unsplash_