יצירת חוויות חיפוש עמידות באמצעות תיבת עבודה

בשיעור הזה תלמדו איך להטמיע חוויית חיפוש עמידה באמצעות Workbox. אפליקציית ההדגמה (דמו) שבה היא משתמשת מכילה תיבת חיפוש שקוראת לנקודת קצה (endpoint) של שרת ומפנה את המשתמשים לדף HTML בסיסי.

מדידה

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

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

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

  1. מקישים על 'Control+Shift+J' (או על 'Command+Option+J' ב-Mac) כדי לפתוח את כלי הפיתוח.
  2. לוחצים על הכרטיסייה רשתות.
  3. פותחים את כלי הפיתוח ל-Chrome ובוחרים בחלונית 'רשת'.
  4. ברשימה הנפתחת של ויסות נתונים, בוחרים באפשרות אופליין.
  5. באפליקציית ההדגמה מזינים שאילתת חיפוש ולוחצים על הלחצן חיפוש.

דף השגיאה הרגיל של הדפדפן מוצג:

צילום מסך של חוויית ברירת המחדל של חוויית המשתמש במצב אופליין בדפדפן.

הוספת תשובה חלופית

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

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

כדי לשמור על פשטות, כבר עשינו זאת בשבילך. הקוד הבא בכתובת public/sw.js עושה את זה:

const FALLBACK_HTML_URL = '/index_offline.html';

workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);

לאחר מכן, מוסיפים קוד לשימוש בדף אופליין כתגובה חלופית:

  1. כדי להציג את המקור, מקישים על הצגת מקור.
  2. צריך להוסיף את הקוד הבא בחלק התחתון של public/sw.js:
workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly());

workbox.routing.setCatchHandler(({event}) => {
  switch (event.request.destination) {
    case 'document':
      return caches.match(FALLBACK_HTML_URL);
      break;
    default:
      return Response.error();
  }
});

הקוד מבצע את הפעולות הבאות:

  • מגדירה אסטרטגיית ברירת מחדל לרשת בלבד, שתחול על כל הבקשות.
  • מצהירה על מטפל שגיאות גלובלי, על ידי קריאה ל-workbox.routing.setCatchHandler() לניהול בקשות שנכשלו. כאשר בקשות מתייחסות למסמכים, יוחזר דף HTML חלופי במצב אופליין.

כדי לבדוק את הפונקציונליות הזו:

  1. חוזרים לכרטיסייה האחרת שבה האפליקציה פועלת.
  2. ברשימה הנפתחת Throttling, מחזירים את האפשרות Online (אונליין).
  3. מקישים על הלחצן הקודם ב-Chrome כדי לנווט חזרה לדף החיפוש.
  4. מוודאים שתיבת הסימון השבתת המטמון מושבתת בכלי הפיתוח.
  5. לוחצים לחיצה ארוכה על הלחצן טעינה מחדש ב-Chrome ובוחרים ריקון המטמון וטעינה מחדש כדי לוודא שה-Service Worker מעודכן.
  6. מחזירים את הרשימה הנפתחת throttling למצב אופליין.
  7. מזינים שאילתת חיפוש ולוחצים שוב על הלחצן חיפוש.

דף ה-HTML החלופי מוצג:

צילום מסך של חוויית המשתמש בהתאמה אישית במצב אופליין בדפדפן.

בקשת הרשאה לשליחת התראות

כדי לפשט את הפשטות, הדף אופליין בכתובת views/index_offline.html כבר מכיל את הקוד לבקשת הרשאות לשליחת התראות בבלוק של סקריפטים בחלק התחתון:

function requestNotificationPermission(event) {
  event.preventDefault();

  Notification.requestPermission().then(function (result) {
    showOfflineText(result);
  });
}

הקוד מבצע את הפעולות הבאות:

  • כשהמשתמש לוחץ על הרשמה לקבלת התראות, הפונקציה requestNotificationPermission() מופעלת, ונקראת Notification.requestPermission(), כדי להציג את בקשת ההרשאה של הדפדפן שמוגדרת כברירת מחדל. ההבטחה משפיעה על ההרשאה שהמשתמש בחר, שיכולה להיות granted, denied או default.
  • מעביר אל showOfflineText() את ההרשאה שטופלה כדי להציג את הטקסט המתאים למשתמש.

מעקב אחר שאילתות אופליין ולנסות שוב כשיהיה חיבור לאינטרנט

בשלב הבא, מטמיעים את Workbox Background Sync (סנכרון ברקע של תיבת עבודה) כדי לשמור שאילתות אופליין, כך שיהיה אפשר לנסות אותן שוב כשהדפדפן יזהה שהקישוריות הוחזרה.

  1. צריך לפתוח את public/sw.js לעריכה.
  2. מוסיפים את הקוד הבא בסוף הקובץ:
const bgSyncPlugin = new workbox.backgroundSync.Plugin('offlineQueryQueue', {
  maxRetentionTime: 60,
  onSync: async ({queue}) => {
    let entry;
    while ((entry = await queue.shiftRequest())) {
      try {
        const response = await fetch(entry.request);
        const cache = await caches.open('offline-search-responses');
        const offlineUrl = `${entry.request.url}&notification=true`;
        cache.put(offlineUrl, response);
        showNotification(offlineUrl);
      } catch (error) {
        await this.unshiftRequest(entry);
        throw error;
      }
    }
  },
});

הקוד מבצע את הפעולות הבאות:

  • הפונקציה workbox.backgroundSync.Plugin כוללת את הלוגיקה להוספת בקשות שנכשלו לתור כדי שאפשר יהיה לנסות אותן שוב מאוחר יותר. הבקשות האלה יישארו בתוקף ב-IndexedDB.
  • maxRetentionTime מציין את משך הזמן שבו ניתן לנסות שוב בקשה. במקרה הזה בחרנו 60 דקות (ולאחר מכן הן יימחקו).
  • החלק onSync הוא החלק החשוב ביותר בקוד. תתבצע קריאה חוזרת (callback) הזה כשהחיבור יחזור, כדי שהבקשות שנמצאות בתור יאוחזרו ואז יאוחזרו מהרשת.
  • תגובת הרשת מתווספת למטמון של offline-search-responses ומוסיפה את פרמטר השאילתה &notification=true, כדי שאפשר יהיה לקלוט את רשומת המטמון הזו כשמשתמש לוחץ על ההתראה.

כדי לשלב סנכרון ברקע עם השירות שלכם, צריך להגדיר אסטרטגיית NetworkOnly לבקשות שנשלחות לכתובת ה-URL של החיפוש (/search_action) ולהעביר את bgSyncPlugin שהוגדר קודם לכן. צריך להוסיף את הקוד הבא בחלק התחתון של public/sw.js:

const matchSearchUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return url.pathname === '/search_action' && !(notificationParam === 'true');
};

workbox.routing.registerRoute(
  matchSearchUrl,
  new workbox.strategies.NetworkOnly({
    plugins: [bgSyncPlugin],
  }),
);

הפעולה הזו מורה ל-Workbox לעבור תמיד לרשת, וכשבקשות נכשלות, להשתמש בלוגיקת הסנכרון ברקע.

בשלב הבא צריך להוסיף את הקוד הבא לתחתית של public/sw.js כדי להגדיר אסטרטגיית שמירה במטמון לבקשות שמגיעות מהתראות. משתמשים בשיטת CacheFirst, כדי שניתן יהיה להציג אותן מהמטמון.

const matchNotificationUrl = ({url}) => {
  const notificationParam = url.searchParams.get('notification');
  return (url.pathname === '/search_action' && (notificationParam === 'true'));
};

workbox.routing.registerRoute(matchNotificationUrl,
  new workbox.strategies.CacheFirst({
     cacheName: 'offline-search-responses',
  })
);

לסיום, מוסיפים את הקוד כדי להציג התראות:

function showNotification(notificationUrl) {
  if (Notification.permission) {
     self.registration.showNotification('Your search is ready!', {
        body: 'Click to see you search result',
        icon: '/img/workbox.jpg',
        data: {
           url: notificationUrl
        }
     });
  }
}

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
     clients.openWindow(event.notification.data.url)
  );
});

בדיקת התכונה

  1. חוזרים לכרטיסייה האחרת שבה האפליקציה פועלת.
  2. ברשימה הנפתחת Throttling, מחזירים את האפשרות Online (אונליין).
  3. מקישים על הלחצן הקודם ב-Chrome כדי לנווט חזרה לדף החיפוש.
  4. לוחצים לחיצה ארוכה על הלחצן טעינה מחדש ב-Chrome ובוחרים ריקון המטמון וטעינה מחדש כדי לוודא שה-Service Worker מעודכן.
  5. מחזירים את הרשימה הנפתחת throttling למצב אופליין.
  6. מזינים שאילתת חיפוש ולוחצים שוב על הלחצן חיפוש.
  7. לוחצים על הרשמה לקבלת התראות.
  8. כש-Chrome שואל אם אתם רוצים להעניק לאפליקציה הרשאה לשלוח התראות, לוחצים על Allow (מתן הרשאה).
  9. מזינים שאילתת חיפוש נוספת ולוחצים שוב על הלחצן חיפוש.
  10. מחזירים את הרשימה הנפתחת Throttling ל-Online (אונליין).

כשהחיבור יחזור, תוצג ההודעה:

צילום מסך של התהליך המלא במצב אופליין.

סיכום

ב-Workbox יש הרבה תכונות מובנות שנועדו להפוך את אפליקציות ה-PWA לעמידות יותר ומעניינות יותר. בשיעור ה-Codelab הזה למדתם איך להטמיע את Background Sync API באמצעות הפשטה של Workbox, כדי להבטיח ששאילתות של משתמשים במצב אופליין לא יאבדו, ויהיה אפשר לנסות שוב כשהחיבור חוזר. ההדגמה היא אפליקציית חיפוש פשוטה, אבל אפשר להשתמש בהטמעה דומה לתרחישים מורכבים יותר ותרחישי שימוש מורכבים יותר, כולל אפליקציות צ'אט, פרסום הודעות ברשת חברתית וכו'.