חוויות ניווט מיידי

הוספת רכיבי שירות (service worker) לשיטות מסורתיות של שליפה מראש (prefetch).

Demián Renzulli
Demián Renzulli
Gilberto Cocchi
Gilberto Cocchi

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

במונחים טכניים, מעבר בין דפים שונים פירושו שליחת בקשת ניווט. באופן כללי, לא כדאי להשתמש בכותרות Cache-Control לטווח ארוך כדי לשמור במטמון את תגובת ה-HTML לבקשת ניווט. לרוב, הם אמורים להיות מרוצים דרך הרשת, עם Cache-Control: no-cache, כדי להבטיח שה-HTML, יחד עם שרשרת בקשות הרשת הבאות, עדכניות (באופן סביר). לצערנו, אם המשתמש עובר לדף חדש בכל פעם שהוא עובר לדף חדש, הוא עלול לפעול באיטיות, לכל הפחות, המשמעות היא שהוא לא יהיה מהיר מהימן.

כדי לזרז את הטיפול בבקשות האלה, אם אפשר לצפות לפעולה של המשתמש, אפשר לבקש את הדפים והנכסים האלה מראש ולשמור אותם במטמון לפרק זמן קצר עד שהמשתמש ילחץ על הקישורים האלה. השיטה הזו נקראת שליפה מראש, ובדרך כלל מיישמים אותה באמצעות הוספת תגי <link rel="prefetch"> לדפים, כדי לציין את המשאב לשליפה מראש.

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

תרחישים בסביבת ייצור

MercadoLibre הוא אתר המסחר האלקטרוני הגדול ביותר באמריקה הלטינית. כדי לזרז את הניווט, הן מחדירות תגי <link rel="prefetch"> באופן דינמי בחלקים מסוימים של התהליך. לדוגמה, בדפי רשימה, הם מאחזרים את דף התוצאות הבא ברגע שהמשתמש גולל לתחתית הרישום:

צילום מסך של דף הרישום הראשון והשני ב-MercadoLibre, ותג של אחזור מראש של קישור שמקשר בין שניהם.

קבצים שנשלפו מראש מבקשים בעדיפות 'הנמוכה ביותר' ומאוחסנים במטמון HTTP או במטמון הזיכרון (בהתאם לסוג המשאב: אפשר לשמור אותו במטמון או לא), למשך פרק זמן שמשתנה בין דפדפנים. לדוגמה, החל מגרסה 85 של Chrome, הערך הזה הוא 5 דקות. המשאבים נשמרים בערך למשך חמש דקות, ולאחר מכן חלים כללי Cache-Control הרגילים של המשאב.

השימוש בשמירת קבצים במטמון של Service Worker יכול לעזור לכם להאריך את משך החיים של משאבים לשליפה מראש (prefetch) מעבר לחלון של חמש הדקות.

לדוגמה, פורטל הספורט האיטלקי Virgilio Sport משתמש ב-service worker כדי לאחזר מראש את הפוסטים הפופולריים ביותר בדף הבית שלו. הם גם משתמשים ב-Network Information API כדי למנוע שליפה מראש (prefetch) של משתמשים בחיבור 2G.

הלוגו של Virgilio Sport.

כתוצאה מכך, במשך יותר מ-3 שבועות של תצפית ב-Virgilio Sport, זמני הטעינה של הניווט לכתבות עלו ב-78%, ומספר החשיפות של כתבות עלה ב-45%.

צילום מסך של דפי הבית והמאמרים של Virgilio Sport, עם מדדי השפעה לאחר השליפה מראש.

הטמעת שמירה מראש במטמון באמצעות Workbox

בקטע הבא נשתמש ב-Workbox כדי להראות איך להטמיע שיטות שונות של שמירה במטמון ב-Service Worker, שניתן להשתמש בהן כהשלמה ל-<link rel="prefetch"> או אפילו תחליף לו, על ידי הענקת גישה מלאה למשימה הזו ל-Service Worker.

‫1. שמירה מראש של דפים סטטיים ומשאבי משנה של דפים

שמירה במטמון היא היכולת של Service Worker לשמור קבצים במטמון במהלך ההתקנה.

במקרים הבאים נעשה שימוש בשמירה מראש במטמון להשגת יעד דומה לשליפה מראש: האצת הניווטים.

הגדרה מראש של דפים סטטיים

בדפים שנוצרים בזמן build (למשל, about.html, contact.html), או באתרים סטטיים לחלוטין, אפשר פשוט להוסיף את מסמכי האתר לרשימה השמורה מראש, כך שהם כבר יהיו זמינים במטמון בכל פעם שהמשתמש ניגש אליהם:

workbox.precaching.precacheAndRoute([
  {url: '/about.html', revision: 'abcd1234'},
  // ... other entries ...
]);

שמירה מראש למשאבי משנה של דף

שמירה במטמון של נכסים סטטיים שחלקים שונים באתר עשויים להשתמש בהם (למשל, JavaScript, CSS וכו'), היא שיטה מומלצת כללית והיא יכולה לשפר את הביצועים בתרחישים של שליפה מראש.

כדי לזרז את הניווט באתר מסחר אלקטרוני, אפשר להשתמש בתגי <link rel="prefetch"> בדפי רשימה, כדי לאחזר מראש דפים של פרטי מוצרים בשביל המוצרים הראשונים בדף כרטיס המוצר. אם כבר שמרתם מראש את משאבי המשנה של דף המוצר במטמון, יכול להיות שהניווט יהיה מהיר עוד יותר.

כדי ליישם את זה:

  • מוסיפים תג <link rel="prefetch"> לדף:
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • מוסיפים את משאבי המשנה של הדפים לרשימת המטמון מראש ב-Service Worker:
workbox.precaching.precacheAndRoute([
  '/styles/product-page.ac29.css',
  // ... other entries ...
]);

‫2. הארכת משך החיים של משאבי שליפה מראש (prefetch)

כפי שצוין קודם, <link rel="prefetch"> מאחזר ושומר משאבים במטמון ה-HTTP למשך פרק זמן מוגבל. בסיום התקופה הזו יחולו כללי Cache-Control למשאב מסוים. נכון לגרסה 85 של Chrome, הערך הזה הוא 5 דקות.

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

בדוגמה שלמעלה, אפשר להשתמש באסטרטגיית שמירה במטמון בזמן ריצה בשביל להשתמש ב-<link rel="prefetch"> שמשמש לשליפה מראש (prefetch) של דף מוצר.

כדי ליישם את זה:

  • מוסיפים תג <link rel="prefetch"> לדף:
 <link rel="prefetch" href="/phones/smartphone-5x.html" as="document">
  • להטמיע אסטרטגיית שמירה במטמון בזמן הריצה ב-Service Worker לבקשות מהסוגים הבאים:
new workbox.strategies.StaleWhileRevalidate({
  cacheName: 'document-cache',
  plugins: [
    new workbox.expiration.Plugin({
      maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
    }),
  ],
});

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

3. הענקת גישה לשליפה מראש (prefetch) ל-Service Worker

ברוב המקרים, הגישה הטובה ביותר היא להשתמש ב-<link rel="prefetch">. התג הוא רמז למשאבים שנועד לייעל את השליפה מראש ככל האפשר.

עם זאת, במקרים מסוימים ייתכן שיהיה כדאי יותר להאציל את המשימה הזו באופן מלא ל-Service Worker. לדוגמה: כדי לאחזר מראש את המוצרים הראשונים בדף פרטי מוצר מעובד בצד הלקוח, ייתכן שיהיה צורך להחדיר מספר תגי <link rel="prefetch"> באופן דינמי לדף, על סמך תגובת API. הפעולה הזו עלולה לצרוך זמן מה ב-thread הראשי של הדף ולהקשות על ההטמעה.

במקרים כאלה, כדאי להשתמש ב'אסטרטגיית תקשורת מדף ל-Service Worker' כדי להאציל את המשימה של שליפה מראש (prefetch) באופן מלא ל-Service Worker. אפשר להשיג תקשורת מהסוג הזה באמצעות worker.postMessage():

סמל של דף שמאפשר תקשורת דו-כיוונית עם Service Worker.

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

אפשר להטמיע שליפה מראש (prefetch) באמצעות חלון של תיבת עבודה באופן הבא:

  • בדף: קוראים ל-Service Worker ומעבירים את סוג ההודעה, ואת רשימת כתובות ה-URL לשליפה מראש:
const wb = new Workbox('/sw.js');
wb.register();

const prefetchResponse = await wb.messageSW({type: 'PREFETCH_URLS', urls: […]});
  • ב-Service Worker: מטמיעים handler של הודעות כדי לשלוח בקשת fetch() לכל כתובת URL לשליפה מראש:
addEventListener('message', (event) => {
  if (event.data.type === 'PREFETCH_URLS') {
    // Fetch URLs and store them in the cache
  }
});