השרת ממלא את הבקשה

אחת מההיבטים העיקריים של Progressive Web Apps היא שהן מהימנות. הן יכולות לטעון נכסים במהירות, להמשיך לשמר את רמת העניין של המשתמשים ולתת משוב באופן מיידי, גם בתנאי רשת גרועים. איך זה אפשרי? תודה לאירוע fetch של קובץ השירות (service worker).

אירוע האחזור

תמיכה בדפדפן

  • 40
  • 17
  • 44
  • 11.1

מקור

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

ה-handler של fetch מקבל את כל הבקשות מהאפליקציה, כולל כתובות URL וכותרות HTTP, ומאפשר למפתח האפליקציה להחליט איך לעבד אותן.

קובץ השירות (service worker) נמצא בין הלקוח והרשת.

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

self.addEventListener("fetch", event => {
    console.log(`URL requested: ${event.request.url}`);
});

תגובה לבקשה

כשבקשה מגיעה ל-service worker, יש שני דברים שאפשר לעשות: אפשר להתעלם ממנה, לאפשר לה לעבור לרשת, או להגיב לה. כשאתם מגיבים לבקשות מתוך קובץ השירות (service worker), אתם יכולים לבחור מה, ואיך הם יוחזרו ל-PWA, גם כשהמשתמש לא מחובר לאינטרנט.

כדי להגיב לבקשה נכנסת, צריך להתקשר ל-event.respondWith() מתוך handler של אירועים של fetch, באופן הבא:

// fetch event handler in your service worker file
self.addEventListener("fetch", event => {
    const response = .... // a response or a Promise of response
    event.respondWith(response);
});

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

יצירת תשובות

בזכות Fetch API, ניתן ליצור תגובות HTTP בקוד ה-JavaScript, וניתן לשמור את התגובות האלה במטמון באמצעות Cache Storage API ולהחזיר אותן כאילו הן הגיעו משרת אינטרנט.

כדי ליצור תגובה, צריך ליצור אובייקט Response חדש ולהגדיר את הגוף שלו ואפשרויות כמו סטטוס וכותרות:

const simpleResponse = new Response("Body of the HTTP response");

const options = {
   status: 200,
   headers: {
    'Content-type': 'text/html'
   }
};
const htmlResponse = new Response("<b>HTML</b> content", options)

תגובה מהמטמון

עכשיו, כשאתם יודעים איך לשלוח תגובות HTTP מ-Service Worker, זה הזמן להשתמש בממשק של Cloud Storage כדי לאחסן את הנכסים במכשיר.

אפשר להשתמש ב-API של אחסון במטמון כדי לבדוק אם הבקשה שהתקבלה מה-PWA זמינה במטמון, ואם כן, להגיב ל-respondWith() איתה. כדי לעשות זאת, קודם צריך לחפש מתוך המטמון. הפונקציה match(), שזמינה בממשק caches ברמה העליונה, מחפשת בכל החנויות במקור, או באובייקט פתוח אחד של מטמון.

הפונקציה match() מקבלת בקשת HTTP או כתובת URL כארגומנט, ומחזירה הבטחה שמסתיימת עם התגובה שמשויכת למפתח התואם.

// Global search on all caches in the current origin
caches.match(urlOrRequest).then(response => {
   console.log(response ? response : "It's not in the cache");
});

// Cache-specific search
caches.open("pwa-assets").then(cache => {
  cache.match(urlOrRequest).then(response => {
    console.log(response ? response : "It's not in the cache");
  });
});

אסטרטגיות של שמירה במטמון

הצגת קבצים רק מהמטמון של הדפדפן לא מתאימה לכל תרחיש לדוגמה. לדוגמה, המשתמש או הדפדפן יכולים להוציא את המטמון. לכן, כדאי לכם להגדיר אסטרטגיות משלכם להעברת נכסים לאפליקציית ה-PWA. אינך מוגבל לאסטרטגיית שמירה אחת במטמון. תוכל להגדיר תבניות שונות עבור תבניות URL שונות. לדוגמה, אפשר ליצור אסטרטגיה אחת למספר המינימלי של נכסי ממשק המשתמש, שיטה אחרת לקריאות ל-API ואסטרטגיה שלישית לכתובות URL של תמונות ונתונים. כדי לעשות זאת, צריך לקרוא את event.request.url ב-ServiceWorkerGlobalScope.onfetch ולנתח אותה באמצעות ביטויים רגולריים או דפוס כתובת URL. (נכון לרגע הכתיבה, תבנית URL לא נתמכת בכל הפלטפורמות).

האסטרטגיות הנפוצות ביותר הן:

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

קודם מטמון

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

האסטרטגיה של &#39;מטמון תחילה&#39;

self.addEventListener("fetch", event => {
   event.respondWith(
     caches.match(event.request)
     .then(cachedResponse => {
       // It can update the cache to serve updated content on the next request
         return cachedResponse || fetch(event.request);
     }
   )
  )
});

קודם רשת

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

האסטרטגיה של Network First

self.addEventListener("fetch", event => {
   event.respondWith(
     fetch(event.request)
     .catch(error => {
       return caches.match(event.request) ;
     })
   );
});

לא פעיל במהלך אימות מחדש

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

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

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cachedResponse => {
        const networkFetch = fetch(event.request).then(response => {
          // update the cache with a clone of the network response
          const responseClone = response.clone()
          caches.open(url.searchParams.get('name')).then(cache => {
            cache.put(event.request, responseClone)
          })
          return response
        }).catch(function (reason) {
          console.error('ServiceWorker fetch failed: ', reason)
        })
        // prioritize cached response over network
        return cachedResponse || networkFetch
      }
    )
  )
})

רשת בלבד

האסטרטגיה 'רשת בלבד' דומה לאופן הפעולה של דפדפנים ללא Service Worker או API ל-cache Storage. הבקשות יחזירו משאב רק אם ניתן לאחזר אותו מהרשת. בדרך כלל הדבר שימושי למשאבים כמו בקשות API אונליין בלבד.

האסטרטגיה &#39;רשת בלבד&#39;

מטמון בלבד

האסטרטגיה של המטמון בלבד מבטיחה שבקשות אף פעם לא יועברו לרשת. כל הבקשות הנכנסות מגיבות עם פריט מטמון שאוכלסו מראש. הקוד הבא משתמש ב-handler של האירועים fetch עם השיטה match של אחסון המטמון כדי להגיב רק מהמטמון:

self.addEventListener("fetch", event => {
   event.respondWith(caches.match(event.request));
});

אסטרטגיית &#39;מטמון בלבד&#39;.

אסטרטגיות מותאמות אישית

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

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

המערכת מעדכנת את הנכסים

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

משאבים