עובדי שירות חדשים יותר, כברירת מחדל

אמ;לק

החל מגרסה 68 של Chrome, בקשות HTTP שבודקות אם יש עדכונים לסקריפט של ה-service worker לא ימולאו יותר על ידי המטמון של HTTP כברירת מחדל. כך אפשר לעקוף נקודת כאב נפוצה של מפתחים, שבה הגדרה לא מכוונת של כותרת Cache-Control בסקריפט של ה-service worker עלולה לגרום לעיכוב בעדכונים.

אם כבר ביטלתם את השימוש במטמון HTTP עבור הסקריפט /service-worker.js על ידי הצגתו עם Cache-Control: max-age=0, לא אמורים להיות שינויים בגלל התנהגות ברירת המחדל החדשה.

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

רקע

בכל פעם שמנווטים לדף חדש שנמצא בהיקף של שירות עבודה, קוראים באופן מפורש ל-registration.update() מ-JavaScript, או כששירות עבודה "מתעורר" באמצעות אירוע push או sync, הדפדפן יגיש במקביל בקשה למשאב ה-JavaScript שהוענק במקור לקריאה navigator.serviceWorker.register(), כדי לחפש עדכונים בסקריפט של שירות העבודה.

לצורך המאמר הזה, נניח שכתובת ה-URL שלו היא /service-worker.js והיא מכילה קריאה אחת ל-importScripts(), שמטעינה קוד נוסף שפועל בתוך ה-service worker:

// Inside our /service-worker.js file:
importScripts('path/to/import.js');

// Other top-level code goes here.

מה משתנה?

לפני Chrome 68, בקשת העדכון של /service-worker.js תתבצע דרך המטמון של HTTP (כמו רוב האחזורים). המשמעות היא שאם הסקריפט נשלח במקור עם Cache-Control: max-age=600, עדכונים במהלך 600 השניות הבאות (10 דקות) לא יועברו לרשת, כך שהמשתמש לא יקבל את הגרסה העדכנית ביותר של ה-service worker. עם זאת, אם הערך של max-age יהיה גדול מ-86400 (24 שעות), הוא ייחשב כ-86400 כדי למנוע מהמשתמשים להיתקע בגרסה מסוימת לתמיד.

החל מגרסה 68, מערכת Chrome תתעלם מהמטמון של HTTP כשתבקש עדכונים לסקריפט של ה-service worker, כך שעשויה להיות עלייה בתדירות הבקשות לסקריפט של ה-service worker באפליקציות אינטרנט קיימות. בקשות ל-importScripts עדיין יישלחו דרך מטמון ה-HTTP. אבל זו רק ברירת המחדל. יש אפשרות רישום חדשה, updateViaCache, שמאפשרת לשלוט בהתנהגות הזו.

updateViaCache

מפתחים יכולים עכשיו להעביר אפשרות חדשה כשקוראים ל-navigator.serviceWorker.register(): הפרמטר updateViaCache. הוא יכול לקבל אחד משלושת הערכים הבאים: 'imports',‏ 'all' או 'none'.

הערכים קובעים אם המטמון הסטנדרטי של HTTP בדפדפן ייכנס לפעולה ואיך הוא ייכנס לפעולה כששולחים את בקשת ה-HTTP כדי לבדוק אם יש משאבי service worker מעודכנים.

  • כשהערך מוגדר ל-'imports', המערכת אף פעם לא תתייעץ עם המטמון של HTTP כשבודקת אם יש עדכונים לסקריפט /service-worker.js, אבל היא תתייעץ איתו כשיאחזר סקריפטים מיובאים (path/to/import.js, בדוגמה שלנו). זוהי ברירת המחדל, והיא תואמת להתנהגות שמתחילה ב-Chrome 68.

  • כשהערך מוגדר ל-'all', המערכת תתייעץ עם המטמון של HTTP כששולחים בקשות לסקריפט /service-worker.js ברמה העליונה, וגם לכל סקריפט שיובא בתוך ה-service worker, כמו path/to/import.js. האפשרות הזו תואמת להתנהגות הקודמת ב-Chrome, לפני Chrome 68.

  • כשהערך מוגדר כ-'none', לא יתבצע פנייה למטמון ה-HTTP כששולחים בקשות ל-/service-worker.js ברמה העליונה או לקבצים של סקריפטים מיובאים, כמו path/to/import.js היפותטי.

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

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js', {
    updateViaCache: 'none',
    // Optionally, set 'scope' here, if needed.
  });
}

בדיקה של עדכונים לסקריפטים מיובאים

לפני Chrome 78, כל סקריפט של שירות טעון דרך importScripts() היה מאוחזר רק פעם אחת (המערכת בודקת קודם במטמון ה-HTTP או דרך הרשת, בהתאם להגדרה של updateViaCache). אחרי האחזור הראשוני, הוא יישמר באופן פנימי בדפדפן ולא יאוחזר שוב.

הדרך היחידה לאלץ שירות פעיל שכבר הותקן לזהות שינויים בסקריפט שיובאו היא לשנות את כתובת ה-URL של הסקריפט. בדרך כלל, עושים זאת על ידי הוספת ערך semver (למשל importScripts('https://example.com/v1.1.0/index.js')) או הוספת גיבוב של התוכן (למשל importScripts('https://example.com/index.abcd1234.js')). תופעת לוואי של שינוי כתובת ה-URL שיובאה היא שינוי התוכן של סקריפט השירות ברמה העליונה, וכתוצאה מכך הפעלה של תהליך העדכון של שירות העבודה.

החל מגרסה 78 של Chrome, בכל פעם שמתבצעת בדיקה של עדכון לקובץ של שירות משתמש ברמה העליונה, מתבצעות בו-זמנית בדיקות כדי לקבוע אם התוכן של סקריפטים מיובאים השתנה. בהתאם לכותרות Cache-Control שבהן נעשה שימוש, יכול להיות שהבדיקות של הסקריפטים המיובאים יבוצעו במטמון ה-HTTP אם הערך של updateViaCache מוגדר כ-'all' או כ-'imports' (ערך ברירת המחדל), או שהבדיקות יבוצעו ישירות ברשת אם הערך של updateViaCache מוגדר כ-'none'.

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

ההתנהגות של Chrome 78 תואמת לזו ש-Firefox הטמיע לפני כמה שנים, ב-Firefox 56. גם ב-Safari כבר יש הטמעה של ההתנהגות הזו.

מה המפתחים צריכים לעשות?

אם ביטלתם את ההסכמה לשמירת פריטים במטמון HTTP עבור הסקריפט /service-worker.js על ידי הצגתו עם Cache-Control: max-age=0 (או ערך דומה), לא אמורים להיות שינויים בגלל התנהגות ברירת המחדל החדשה.

אם אתם מציגים את הסקריפט /service-worker.js כשאחסון ב-HTTP מופעל, בין שבכוונה ובין שזו ברירת המחדל בסביבת האירוח, יכול להיות שתבחינו בעלייה במספר הבקשות הנוספות מסוג HTTP ל-/service-worker.js שנשלחות לשרת שלכם. אלה בקשות שהיו מתקבלות בעבר מאחסון ה-HTTP. אם רוצים להמשיך לאפשר לערך הכותרת Cache-Control להשפיע על רמת הרעננות של /service-worker.js, צריך להתחיל להגדיר את updateViaCache: 'all' באופן מפורש כשרושמים את ה-service worker.

מכיוון שיכול להיות שיש משתמשים רבים עם גרסאות דפדפן ישנות, עדיין מומלץ להמשיך להגדיר את כותרת ה-HTTP Cache-Control: max-age=0 בסקריפטים של שירותי העבודה, גם אם דפדפנים חדשים יותר עשויים להתעלם מהם.

המפתחים יכולים לנצל את ההזדמנות הזו כדי להחליט אם הם רוצים לבטל עכשיו את ההסכמה להטמעת הסקריפטים שלהם במטמון HTTP, ולהוסיף את updateViaCache: 'none' לרישום של ה-service worker אם הדבר רלוונטי.

הצגת סקריפטים מיובאים

החל מ-Chrome 78, יכול להיות שמפתחים יראו יותר בקשות HTTP נכנסות למשאבים שנטענים דרך importScripts(), כי מעכשיו הם ייבדקו אם יש להם עדכונים.

כדי להימנע מתעבורת ה-HTTP הנוספת הזו, צריך להגדיר כותרות Cache-Control לטווח ארוך כשמציגים סקריפטים שכתובות ה-URL שלהם כוללות semver או גיבוב, ולהסתמך על התנהגות ברירת המחדל של updateViaCache ב-'imports'.

לחלופין, אם רוצים שהסקריפטים המיובאים ייבדקו לעיתים קרובות אם יש עדכונים, צריך להציג אותם באמצעות Cache-Control: max-age=0 או להשתמש ב-updateViaCache: 'none'.

קריאה נוספת

מומלץ לקרוא את המאמרים The Service Worker Lifecycle ו-Caching best practices & max-age gotchas, שניהם מאת ג'ייק ארקדיל (Jake Archibald), לכל המפתחים שמפרסמים משהו באינטרנט.