עד עכשיו היו רק אזכורים וקטעי קוד זעירים
ממשק Cache
.
כדי להשתמש ב-Service Workers בצורה יעילה, צריך לאמץ אסטרטגיית שמירה אחת או יותר במטמון,
מה שמחייב היכרות מסוימת עם הממשק של Cache
.
אסטרטגיית שמירה במטמון היא אינטראקציה בין אירוע fetch
של קובץ שירות (service worker) לממשק Cache
.
האופן שבו נכתבת אסטרטגיית שמירה במטמון תלוי;
לדוגמה, יכול להיות שעדיף לטפל בבקשות לנכסים סטטיים באופן שונה מטיפול במסמכים,
וזה משפיע על האופן שבו מורכבת אסטרטגיית שמירה במטמון.
לפני שנתחיל באסטרטגיות,
בואו נדבר רגע על מה זה הממשק של Cache
, מה זה,
וסקירה מהירה של כמה מהשיטות שהוא מציע לניהול מטמון של עובדי שירות.
הממשק Cache
לעומת מטמון ה-HTTP
אם לא עבדתם בעבר עם הממשק של Cache
,
מפתה לחשוב על זה באותו אופן,
או לפחות קשורות למטמון של ה-HTTP. זה לא נכון.
- הממשק
Cache
הוא מנגנון שמירה במטמון נפרד לגמרי ממטמון ה-HTTP. - שיהיה
Cache-Control
ההגדרה שבה משתמשים כדי להשפיע על מטמון HTTP לא משפיעה על הנכסים שמאוחסנים בממשקCache
.
חשוב להתייחס למטמון הדפדפן כאל שכבות. מטמון ה-HTTP הוא מטמון ברמה נמוכה שמבוסס על צמדי מפתח-ערך, עם הוראות שמבוטאות בכותרות HTTP.
לעומת זאת, הממשק של Cache
הוא מטמון ברמה גבוהה שמופעל על ידי JavaScript API.
השיטה הזו מספקת יותר גמישות מאשר כשמשתמשים בצמדי מפתח/ערך של HTTP פשוטים יחסית,
והוא רק חצי ממה שהופך אסטרטגיות שמירה במטמון.
הנה כמה שיטות חשובות של API לשמירה במטמון של Service Worker:
CacheStorage.open
כדי ליצור מכונה חדשה שלCache
.Cache.add
ו-Cache.put
כדי לאחסן תגובות רשת במטמון של Service Worker.Cache.match
כדי לאתר תגובה שנשמרה במטמון במכונהCache
.Cache.delete
כדי להסיר תגובה שנשמרה במטמון ממכונה שלCache
.
ועוד תחומים רבים. יש עוד שיטות שימושיות, אבל אלה העקרונות הבסיסיים שבהם תשתתפו בהמשך המדריך.
אירוע fetch
הצנוע
החצי השני של אסטרטגיית שמירה במטמון הוא
אירוע אחד (fetch
).
עד עכשיו במסמך הזה שמעתם קצת על "יירוט בקשות רשת",
והאירוע fetch
בתוך Service Worker מתרחש:
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('install', (event) => {
event.waitUntil(caches.open(cacheName));
});
self.addEventListener('fetch', async (event) => {
// Is this a request for an image?
if (event.request.destination === 'image') {
// Open the cache
event.respondWith(caches.open(cacheName).then((cache) => {
// Respond with the image from the cache or from the network
return cache.match(event.request).then((cachedResponse) => {
return cachedResponse || fetch(event.request.url).then((fetchedResponse) => {
// Add the network response to the cache for future visits.
// Note: we need to make a copy of the response to save it in
// the cache and use the original as the request response.
cache.put(event.request, fetchedResponse.clone());
// Return the network response
return fetchedResponse;
});
});
}));
} else {
return;
}
});
זה צעצוע לדוגמה, שתוכלו לראות בפעולה בעצמכם, אבל היא מאפשרת הצצה למה שעובדי שירות יכולים לעשות. הקוד שלמעלה מבצע את הפעולות הבאות:
- יש לבדוק את המאפיין
destination
של הבקשה כדי לראות אם זו בקשת תמונה. - אם התמונה נמצאת במטמון של Service Worker, יש להציג אותה משם. אם לא, מאחזרים את התמונה מהרשת, אחסון התגובה במטמון והחזרת תגובת הרשת.
- כל שאר הבקשות מועברות דרך Service Worker ללא אינטראקציה עם המטמון.
אובייקט event
של אחזור מכיל
נכס request
אילו קטעי מידע שימושיים שיעזרו לכם לזהות את סוג כל בקשה:
url
זוהי כתובת ה-URL של בקשת הרשת שמטופלת כרגע על ידי האירועfetch
.method
שזו שיטת הבקשה (למשל,GET
אוPOST
).mode
שמתאר את מצב הבקשה. לעיתים קרובות, הערך'navigate'
משמש כדי להבדיל בין בקשות למסמכי HTML לבין בקשות אחרות.destination
שמתאר את סוג התוכן המבוקש באופן שלא משתמש בסיומת הקובץ של הנכס המבוקש.
שוב, אסינכרוני הוא שם המשחק.
תזכיר לך שהאירוע install
כולל
event.waitUntil
בשיטה הזו לוקחת הבטחה, וממתינה לפתרון לפני שממשיכים בהפעלה.
האירוע fetch
כולל
אמצעי תשלום אחד (event.respondWith
)
שאפשר להשתמש בה כדי להחזיר תוצאה של
בקשה אחת (fetch
)
או תשובה שהוחזרה על ידי הממשק Cache
match
.
אסטרטגיות של שמירה במטמון
עכשיו, אחרי שמכירים קצת את המכונות של Cache
ואת הגורם המטפל באירועים של fetch
,
אתם מוכנים להתעמק בכמה אסטרטגיות לשמירה במטמון של עובדי שירות (service worker).
האפשרויות הן כמעט אינסופיות,
המדריך הזה צריך להתמקד באסטרטגיות שמתאימות ל-Workbox,
כדי שאפשר יהיה להבין מה קורה בפנימיות של Workbox.
מטמון בלבד
נתחיל באסטרטגיית שמירה פשוטה במטמון, שנקראת 'מטמון בלבד'. זה רק כך: כשה-Service Worker שולט בדף, בקשות תואמות יועברו תמיד למטמון. פירוש הדבר הוא שצריך לשמור מראש את כל הנכסים שנשמרו במטמון כדי שהתבנית תפעל. ושהנכסים האלה אף פעם לא יעודכנו במטמון עד שה-Service Worker יעודכן.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
// Assets to precache
const precachedAssets = [
'/possum1.jpg',
'/possum2.jpg',
'/possum3.jpg',
'/possum4.jpg'
];
self.addEventListener('install', (event) => {
// Precache assets on install
event.waitUntil(caches.open(cacheName).then((cache) => {
return cache.addAll(precachedAssets);
}));
});
self.addEventListener('fetch', (event) => {
// Is this one of our precached assets?
const url = new URL(event.request.url);
const isPrecachedRequest = precachedAssets.includes(url.pathname);
if (isPrecachedRequest) {
// Grab the precached asset from the cache
event.respondWith(caches.open(cacheName).then((cache) => {
return cache.match(event.request.url);
}));
} else {
// Go to the network
return;
}
});
למעלה, מערך נכסים נשמר מראש בזמן ההתקנה.
כש-Service Worker מטפל בשליפות,
אנחנו בודקים אם כתובת ה-URL של הבקשה שמטופלת על ידי האירוע fetch
נמצאת במערך הנכסים הדיגיטליים שנשמרו מראש.
במקרה כזה, אנחנו נשלפים את המשאב מהמטמון ומדלגים על הרשת.
בקשות אחרות מועברות לרשת,
ורק הרשת.
כדי לראות את האסטרטגיה הזו בפעולה,
תוכלו לצפות בהדגמה הזו כשהמסוף פתוח.
רשת בלבד
האפשרות ההפוך ל'מטמון בלבד' הוא 'רשת בלבד', כאשר בקשה מועברת לרשת דרך Service Worker ללא כל אינטראקציה עם המטמון של ה-Service Worker. זאת אסטרטגיה טובה להבטחת עדכניות התוכן (למשל, 'תגי עיצוב') אבל החיסרון הוא שהוא אף פעם לא יעבוד כשהמשתמש לא מחובר לאינטרנט.
כאשר מוודאים שבקשה עוברת לרשת, לא מתקשרים אל event.respondWith
עבור בקשה תואמת.
אם אתם רוצים להשתמש בתוכן בוטה,
אפשר להוסיף return;
ריק בקריאה חוזרת (callback) של האירוע fetch
לבקשות שרוצים להעביר לרשת.
זה מה שקורה בקטע 'מטמון בלבד' הדגמת האסטרטגיה עבור בקשות שלא נשמרו מראש.
קודם צריך לשמור את המטמון ואז לחזור לרשת
האסטרטגיה הזו היא השלב שבו העסק צריך להיות מעורבים יותר. בבקשות התאמה, התהליך ייראה כך:
- הבקשה מגיעה למטמון. אם הנכס נמצא במטמון, צריך להציג אותו משם.
- אם הבקשה לא במטמון, עוברים לרשת.
- לאחר שבקשת הרשת מסתיימת, מוסיפים אותה למטמון, ולאחר מכן להחזיר את התגובה מהרשת.
הנה דוגמה לשיטה הזו, ואפשר לנסות אותה הדגמה (דמו) בזמן אמת:
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
// Check if this is a request for an image
if (event.request.destination === 'image') {
event.respondWith(caches.open(cacheName).then((cache) => {
// Go to the cache first
return cache.match(event.request.url).then((cachedResponse) => {
// Return a cached response if we have one
if (cachedResponse) {
return cachedResponse;
}
// Otherwise, hit the network
return fetch(event.request).then((fetchedResponse) => {
// Add the network response to the cache for later visits
cache.put(event.request, fetchedResponse.clone());
// Return the network response
return fetchedResponse;
});
});
}));
} else {
return;
}
});
למרות שהדוגמה הזו מתייחסת לתמונות בלבד, זו אסטרטגיה מעולה שכדאי להחיל על כל הנכסים הסטטיים (כמו CSS , JavaScript, תמונות וגופנים). במיוחד גרסאות עם גרסאות hash. הוא מאפשר להגביר את המהירות של נכסים שאינם ניתנים לשינוי על ידי השלמה של בדיקות עדכניות התוכן מול השרת, כאשר מטמון ה-HTTP עשוי להתחיל לפעול. חשוב יותר: כל הנכסים ששמורים במטמון יהיו זמינים במצב אופליין.
קודם רשת, ואז חזרה למטמון
אם מחליפים את המצב 'קודם המטמון, קודם כול הרשת' על הראש, התוצאה היא "קודם רשת, מטמון שנייה" כך זה נשמע:
- קודם עוברים לרשת כדי לקבל בקשה ומציבים את התגובה במטמון.
- אם לא התחברתם לאינטרנט בשלב מאוחר יותר, חוזרים לגרסה האחרונה של התשובה הזו במטמון.
השיטה הזאת מעולה לבקשות HTML או API כאשר, כשאתם מחוברים לאינטרנט, אתם רוצים את הגרסה העדכנית ביותר של משאב, עדיין רוצים להעניק גישה במצב אופליין לגרסה האחרונה שזמינה. כך זה עשוי להיראות כאשר מחילים את הבקשות על HTML:
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
// Check if this is a navigation request
if (event.request.mode === 'navigate') {
// Open the cache
event.respondWith(caches.open(cacheName).then((cache) => {
// Go to the network first
return fetch(event.request.url).then((fetchedResponse) => {
cache.put(event.request, fetchedResponse.clone());
return fetchedResponse;
}).catch(() => {
// If the network is unavailable, get
return cache.match(event.request.url);
});
}));
} else {
return;
}
});
אפשר לנסות את התכונה במסגרת הדגמה. קודם עוברים לדף. ייתכן שיהיה צורך לטעון מחדש לפני שתגובת ה-HTML תמוקם במטמון. לאחר מכן, בכלים למפתחים סימולציה של חיבור אופליין, ולטעון מחדש. הגרסה האחרונה שזמינה תוצג באופן מיידי מהמטמון.
במצבים שבהם היכולת להתחבר לאינטרנט חשובה, אבל צריך לאזן בין היכולת הזו לבין גישה לגרסה העדכנית ביותר של מעט נתוני תגי עיצוב או נתוני API, "קודם רשת, שמירה שניה במטמון" היא אסטרטגיה יציבה להשגת היעד הזה.
לא פעיל בזמן אימות מחדש
מבין האסטרטגיות שעברנו עליהן עד עכשיו, "עיכוב בזמן אימות מחדש" הוא המורכב ביותר. היא דומה לשתי האסטרטגיות האחרונות במובנים מסוימים, אבל התהליך מתעדף את מהירות הגישה למשאב, וגם לעדכן אותו ברקע. האסטרטגיה הזו מתנהלת בערך כך:
- בבקשה הראשונה לנכס, מאחזרים אותו מהרשת, לשמור אותו במטמון ולהחזיר את תגובת הרשת.
- בבקשות הבאות, שולחים קודם את הנכס מהמטמון ואז 'ברקע'. לבקש אותו מחדש מהרשת ולעדכן את רשומת המטמון של הנכס.
- לבקשות לאחר מכן, תוצג הגרסה האחרונה שאוחזרה מהרשת שהוצבה במטמון בשלב הקודם.
זוהי אסטרטגיה מצוינת לדברים שחשובים להתעדכן בהם, אבל לא חיוניות. אפשר לחשוב על דברים כמו דמויות לאתר של רשת חברתית. הם מתעדכנים כשמשתמשים מתחילים לעשות זאת, אבל הגרסה העדכנית ביותר לא הכרחית לכל בקשה.
// Establish a cache name
const cacheName = 'MyFancyCacheName_v1';
self.addEventListener('fetch', (event) => {
if (event.request.destination === 'image') {
event.respondWith(caches.open(cacheName).then((cache) => {
return cache.match(event.request).then((cachedResponse) => {
const fetchedResponse = fetch(event.request).then((networkResponse) => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
return cachedResponse || fetchedResponse;
});
}));
} else {
return;
}
});
אפשר לראות את זה בפעולה
עוד הדגמה פעילה,
במיוחד אם מקדישים תשומת לב לכרטיסיית הרשת בכלים למפתחים בדפדפן,
ומציג CacheStorage
שלו (אם כלים למפתחים בדפדפן שלך כוללים כלי כזה).
קדימה ל-Workbox!
במסמך הזה מסתיימת הבדיקה של ה-API של Service Worker, ואת ממשקי ה-API הקשורים, והמשמעות היא שלמדתם מספיק איך להשתמש ישירות ב-Service Workbox כדי להתחיל להשתמש ב-Workbox.