שמירת משאבים במטמון במהלך זמן ריצה

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

ב-Workbox, אתם יכולים לטפל בשמירת נכסים בזמן ריצה במטמון באמצעות המודול workbox-routing כדי להתאים לנתיבים, ובאסטרטגיות של שמירה במטמון עבורם באמצעות המודול workbox-strategies.

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

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

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

אפשר להחיל את השיטות האלה על בקשות נבחרות באמצעות שיטות שמוצעות על ידי workbox-routing.

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

workbox-routing חושף שיטה registerRoute כדי להתאים מסלולים ולטפל בהם באמצעות אסטרטגיית שמירה במטמון. הפונקציה registerRoute מקבלת אובייקט Route שמקבל שני ארגומנטים:

  1. מחרוזת, ביטוי רגולרי או קריאה חוזרת (callback) של התאמה לציון קריטריונים להתאמת נתיב.
  2. רכיב handler של המסלול – בדרך כלל שיטה שסופקה על ידי workbox-strategies.

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

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

// sw.js
import { registerRoute, Route } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';

// A new route that matches same-origin image requests and handles
// them with the cache-first, falling back to network strategy:
const imageRoute = new Route(({ request, sameOrigin }) => {
  return sameOrigin && request.destination === 'image'
}, new CacheFirst());

// Register the new route
registerRoute(imageRoute);

שימוש במספר קבצים שמורים

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

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

// sw.js
import { registerRoute, Route } from 'workbox-routing';
import { CacheFirst, StaleWhileRevalidate } from 'workbox-strategies';

// Handle images:
const imageRoute = new Route(({ request }) => {
  return request.destination === 'image'
}, new StaleWhileRevalidate({
  cacheName: 'images'
}));

// Handle scripts:
const scriptsRoute = new Route(({ request }) => {
  return request.destination === 'script';
}, new CacheFirst({
  cacheName: 'scripts'
}));

// Handle styles:
const stylesRoute = new Route(({ request }) => {
  return request.destination === 'style';
}, new CacheFirst({
  cacheName: 'styles'
}));

// Register routes
registerRoute(imageRoute);
registerRoute(scriptsRoute);
registerRoute(stylesRoute);
צילום מסך של רשימת מופעים של מטמון בכרטיסייה של האפליקציה בכלי הפיתוח של Chrome. מוצגים שלושה מטמוןים נפרדים: אחד בשם 'scripts', השני בשם 'styles' והמטמון האחרון נקרא 'תמונות'.
מציג האחסון במטמון בחלונית האפליקציות של כלי הפיתוח ל-Chrome. תגובות לסוגים שונים של נכסים נשמרות במטמון נפרד.

הגדרת תפוגה לרשומות במטמון

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

// sw.js
import { registerRoute, Route } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';

// Evict image cache entries older thirty days:
const imageRoute = new Route(({ request }) => {
  return request.destination === 'image';
}, new CacheFirst({
  cacheName: 'images',
  plugins: [
    new ExpirationPlugin({
      maxAgeSeconds: 60 * 60 * 24 * 30,
    })
  ]
}));

// Evict the least-used script cache entries when
// the cache has more than 50 entries:
const scriptsRoute = new Route(({ request }) => {
  return request.destination === 'script';
}, new CacheFirst({
  cacheName: 'scripts',
  plugins: [
    new ExpirationPlugin({
      maxEntries: 50,
    })
  ]
}));

// Register routes
registerRoute(imageRoute);
registerRoute(scriptsRoute);

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

שיקולים ממקורות שונים

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

תשובות אטומות

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

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

אל תשכחו להצטרף למצב CORS

גם אם תטען נכסים ממקורות שונים שכן מגדירות כותרות CORS מתירות יותר שמאפשרות לך לקרוא תשובות, גוף התגובה ממקורות שונים עדיין עשוי להיות אטום. לדוגמה, ה-HTML הבא יפעיל בקשות no-cors שיובילו לתגובות אטומות ללא קשר לכותרות CORS שהוגדרו:

<link rel="stylesheet" href="https://example.com/path/to/style.css">
<img src="https://example.com/path/to/image.png">

כדי להפעיל באופן מפורש בקשת cors שתניב תשובה שאינה שקופה, עליך להביע הסכמה מפורשת למצב CORS על ידי הוספת המאפיין crossorigin ל-HTML:

<link crossorigin="anonymous" rel="stylesheet" href="https://example.com/path/to/style.css">
<img crossorigin="anonymous" src="https://example.com/path/to/image.png">

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

יכול להיות שתיבת העבודה לא תשמור תשובות אטומות במטמון

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

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

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

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

אם אתם בטוחים לחלוטין שאתם רוצים לשמור תגובה אטומה באמצעות אסטרטגיית 'מטמון תחילה' או 'מטמון בלבד', אפשר לאלץ את תיבת העבודה לעשות זאת באמצעות המודול workbox-cacheable-response:

import {Route, registerRoute} from 'workbox-routing';
import {NetworkFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';

const cdnRoute = new Route(({url}) => {
  return url === 'https://cdn.google.com/example-script.min.js';
}, new CacheFirst({
  plugins: [
    new CacheableResponsePlugin({
      statuses: [0, 200]
    })
  ]
}))

registerRoute(cdnRoute);

תגובות אטומות וממשק ה-API של navigator.storage

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

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