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

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

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

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

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

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

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

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

איך מספקים תשובה חלופית

קובץ השירות מכיל את הקוד להוספת הדף אופליין לרשימת המטמון מראש, כך שתמיד אפשר לשמור אותו במטמון באירוע 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. מוודאים שהתיבה Disable cache (השבתת המטמון) ב-DevTools מושבתת.
  5. לוחצים לחיצה ארוכה על הלחצן טעינה מחדש ב-Chrome ובוחרים באפשרות פינוי המטמון וטעינה מחדש כדי לוודא ש-service worker מעודכן.
  6. ברשימה הנפתחת Throttling, מגדירים שוב את האפשרות Offline.
  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 דקות (אחרי 60 דקות הנתונים יימחקו).
  • onSync הוא החלק החשוב ביותר בקוד הזה. הקריאה החוזרת הזו תתבצע כשהחיבור יחזור, כדי לאחזר את הבקשות שבתור ולאחר מכן לאחזר אותן מהרשת.
  • התגובה מהרשת מתווספת למטמון 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 (בקרת קצב העברת נתונים), מגדירים שוב את האפשרות Offline (אופליין).
  6. מזינים שאילתת חיפוש ולוחצים שוב על הלחצן חיפוש.
  7. לוחצים על הרשמה להתראות.
  8. כשמוצגת ב-Chrome בקשה לאשר לאפליקציה לשלוח התראות, לוחצים על אישור.
  9. מזינים שאילתת חיפוש אחרת ולוחצים שוב על הלחצן חיפוש.
  10. ברשימה הנפתחת Throttling (בקרת תעבורה), מגדירים שוב את האפשרות Online (באינטרנט).

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

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

סיכום

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