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

tl;dr

החל מגרסה 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, או כש-Service Worker "מתעורר" דרך אירוע push או sync, הדפדפן יבקש במקביל את משאב ה-JavaScript שהועבר במקור לקריאה ל-navigator.serviceWorker.register() כדי לחפש עדכונים לסקריפט של Service Worker.

לצורך המאמר הזה, נניח שכתובת ה-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, המערכת תתעלם ממטמון ה-HTTP כשמבקשים עדכונים לסקריפט של Service Worker, ולכן יכול להיות שתופיע עלייה בתדירות הבקשות לסקריפט של Service Worker באפליקציות אינטרנט קיימות. הבקשות עבור importScripts עדיין יועברו דרך מטמון ה-HTTP. אבל זו רק ברירת המחדל – יש אפשרות רישום חדשה בשם updateViaCache, שמציעה שליטה על ההתנהגות הזו.

updateViaCache

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

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

  • כשההגדרה מוגדרת לערך 'imports', אף פעם לא בודקים אם יש עדכונים לסקריפט /service-worker.js אבל אף פעם לא בודקים את מטמון ה-HTTP, אבל מקבלים ייעוץ באחזור סקריפטים שיובאו (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 ההיפותטי.

לדוגמה, הקוד הבא רושם קובץ שירות (service worker) ומוודאים שאף פעם לא בודקים את המטמון של ה-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, כל סקריפט של Service Worker שנטען דרך importScripts() היה מאוחזר פעם אחת בלבד (קודם צריך לבדוק מול המטמון של HTTP או דרך הרשת, בהתאם להגדרות של updateViaCache). לאחר השליפה הראשונית, הדפדפן יאוחסן באופן פנימי על ידי הדפדפן ואף פעם לא יאוחזר אותו מחדש.

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

החל מגרסה 78 של Chrome, בכל פעם שבדיקת עדכון של קובץ Service Worker ברמה העליונה מתבצעת בו-זמנית, הבדיקות יבוצעו בו-זמנית כדי לקבוע אם התוכן של סקריפטים מיובאים השתנה. בהתאם לכותרות 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 בסקריפטים של Service Worker, למרות שדפדפנים חדשים יותר עשויים להתעלם מהם.

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

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

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

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

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

קריאה נוספת

"The Service Worker Lifecycle" ו-"CSS יראו שיטות מומלצות לשמירה במטמון ו-max-age Getchas", שניהם מאת ג'ייק ארצ'יבלד, מומלצים לכל המפתחים שפורסים כל אפליקציה באינטרנט.