רישום של קובץ שירות (service worker)

שיטות מומלצות לתזמון הרישום של Service Worker.

שירותי עובדים יכולים להאיץ באופן משמעותי ביקורים חוזרים באפליקציית האינטרנט שלכם, אבל חשוב לוודא שההתקנה הראשונית של שירות העבודה לא פוגעת בחוויית הביקור הראשון של המשתמש.

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

אם אי פעם קראתם על Service Workers, סביר להניח שנתקלתם בboilerplate שדומה באופן משמעותי לזה:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
}

לפעמים הקוד הזה מלווה בכמה הצהרות console.log() או בקוד שמזהה עדכון לרישום קודם של קובץ שירות, כדי להודיע למשתמשים לרענן את הדף. אבל אלה רק וריאציות קלות על כמה שורות הקוד הסטנדרטיות.

האם יש ניואנסים לגבי navigator.serviceWorker.register? יש שיטות מומלצות שכדאי ליישם? לא מפתיע (בהתחשב בעובדה שהמאמר לא מסתיים כאן), התשובה לשתי השאלות היא 'כן!'

הביקור הראשון של משתמש

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

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

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

סביר להניח ששרשור ברקע שלא פעיל יגרום לשינוי משמעותי. אבל מה קורה אם השרשור הזה לא פעיל, אלא מחליט להתחיל גם להוריד משאבים מהרשת? אם יש לכם חששות לגבי תחרות על המעבד (CPU) או על הזיכרון, עליכם להתמקד בחששות לגבי רוחב הפס המוגבל שזמין למכשירים ניידים רבים. רוחב הפס יקר, לכן לא כדאי לפגוע במשאבים קריטיים על ידי הורדת משאבים משניים בו-זמנית.

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

שיפור הטקסט הסטנדרטי

הפתרון הוא לשלוט בהפעלה של ה-service worker על ידי בחירה של מועד הקריאה ל-navigator.serviceWorker.register(). כלל אצבע פשוט הוא לעכב את הרישום עד אחרי שה-load event יופעל בתאריך window, למשל:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}

אבל הזמן הנכון להתחיל את הרישום של Service Worker תלוי גם במה שאפליקציית האינטרנט שלכם עושה מיד לאחר שהיא נטענת. לדוגמה, אפליקציית האינטרנט של Google I/O 2016 כוללת אנימציה קצרה לפני המעבר למסך הראשי. הצוות שלנו גילה שהפעלת הרישום של ה-service worker במהלך האנימציה עלולה לגרום לתנודות במכשירים ניידים ברמה נמוכה. במקום לתת למשתמשים חוויה גרועה, דחינו את ההרשמה של ה-service worker עד אחרי האנימציה, כשסביר להניח שהדפדפן יהיה במצב חוסר פעילות למשך כמה שניות.

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

ביקורים נוספים

עד עכשיו התמקדנו בחוויית הביקור הראשון, אבל מה ההשפעה של רישום מושהה של שירותי עובדים על ביקורים חוזרים באתר? יכול להיות שזה יפתיע חלק מהאנשים, אבל לא אמורה להיות השפעה בכלל.

כשקובץ שירות (service worker) רשום, הוא עובר את אירועי מחזור החיים install ו-activate. אחרי שמפעילים קובץ שירות, הוא יכול לטפל באירועים מסוג fetch בכל ביקור נוסף באפליקציית האינטרנט. קובץ השירות מתחיל לפעול לפני שליחת הבקשה לדפים שנמצאים בהיקף שלו, וזה הגיוני. אם עובד השירות הקיים לא היה פועל לפני הביקור בדף, לא תהיה לו הזדמנות למלא אירועי fetch לבקשות ניווט.

לכן, אחרי שיוצרים עובד שירות פעיל, לא משנה מתי קוראים ל-navigator.serviceWorker.register(), או בעצם אם קוראים לו בכלל. אלא אם משנים את כתובת ה-URL של סקריפט ה-service worker, הערך של navigator.serviceWorker.register() הוא למעשה no-op (פעולה ללא תוצאה) במהלך ביקורים הבאים. כשהוא מופיע, הוא לא רלוונטי.

סיבות להירשם מוקדם

האם יש תרחישים שבהם כדאי לרשום את ה-service worker מוקדם ככל האפשר? דוגמה אחת שעולה בראש היא כש-service worker משתמש ב-clients.claim() כדי להשתלט על הדף במהלך הביקור הראשון, ו-service worker מבצע אחסון במטמון בסביבת זמן הריצה באופן אגרסיבי בתוך הטיפולן fetch. במצב כזה, יש יתרון כשמפעילים את Service Worker בהקדם האפשרי, כדי לנסות לאכלס את המטמון של סביבת זמן הריצה במשאבים שאולי יהיו שימושיים בהמשך. אם אפליקציית האינטרנט שלכם נכללת בקטגוריה הזו, כדאי לעצור לרגע כדי לוודא שהמתאם install של ה-service worker לא מבקש משאבים שמתחרים על רוחב הפס עם הבקשות של הדף הראשי.

בדיקה של דברים

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

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

תעבורת נתונים ברשת עם רישום מוקדם.

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

תנועה ברשת עם רישום מאוחר.

בצילום המסך שלמעלה, רישום קובץ השירות (service worker) נדחה עד אחרי טעינת הדף. אפשר לראות שהבקשות לאחסון מראש לא מתחילות עד שכל המשאבים אוחזר מהרשת, וכך אין תחרות על רוחב הפס. בנוסף, חלק מהפריטים שאנחנו שומרים במטמון מראש כבר נמצאים במטמון ה-HTTP של הדפדפן – הפריטים עם הערך (from disk cache) בעמודה 'גודל'. לכן, אנחנו יכולים לאכלס את המטמון של ה-service worker בלי צורך לחזור לרשת.

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

סיכום

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

כדי לוודא שהרישום הראשוני של ה-service worker יתבצע רק אחרי טעינת הדף הראשון, אפשר להשתמש בקוד הבא:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
    });
}