การแคชทรัพยากรระหว่างรันไทม์

เนื้อหาบางอย่างในเว็บแอปพลิเคชันอาจใช้ไม่บ่อยนัก มีขนาดใหญ่มาก หรือแตกต่างกันตามอุปกรณ์ (เช่น รูปภาพที่ปรับเปลี่ยนตามอุปกรณ์) หรือภาษาของผู้ใช้ ซึ่งเป็นกรณีที่การแคชล่วงหน้าอาจเป็นรูปแบบต่อต้าน และคุณควรใช้การแคชรันไทม์แทน

ใน Workbox คุณจะจัดการการแคชรันไทม์สำหรับเนื้อหาได้โดยใช้โมดูล workbox-routing เพื่อจับคู่เส้นทาง และจัดการกลยุทธ์การแคชเนื้อหาด้วยโมดูล workbox-strategies

กลยุทธ์การแคช

คุณสามารถจัดการเส้นทางส่วนใหญ่สำหรับเนื้อหาด้วยหนึ่งในกลยุทธ์การแคชในตัว มีคำอธิบายอย่างละเอียดอยู่ในช่วงต้นของเอกสารนี้ แต่เราขอสรุปข้อมูลสั้นๆ ดังนี้

  • ไม่มีอัปเดตขณะตรวจสอบความถูกต้องอีกครั้งจะใช้การตอบกลับที่แคชไว้สำหรับคำขอ (หากมี) และอัปเดตแคชในเบื้องหลังด้วยการตอบกลับจากเครือข่าย ดังนั้นหากชิ้นงานไม่ได้แคช ชิ้นงานจะรอการตอบสนองของเครือข่ายและใช้ชิ้นงานนั้น กลยุทธ์นี้ค่อนข้างปลอดภัยเนื่องจากอัปเดตแคชที่ใช้แคชเป็นประจำ ข้อเสียก็คือ แอปจะขอเนื้อหาจากเครือข่ายในเบื้องหลังเสมอ
  • Network First จะพยายามรับการตอบสนองจากเครือข่ายก่อน หากได้รับการตอบกลับ ระบบจะส่งการตอบกลับดังกล่าวไปยังเบราว์เซอร์และบันทึกลงในแคช หากคำขอเครือข่ายไม่สำเร็จ ระบบจะใช้การตอบสนองที่แคชไว้ล่าสุด ซึ่งจะเปิดใช้การเข้าถึงเนื้อหาแบบออฟไลน์ได้
  • Cache First ตรวจสอบแคชสำหรับการตอบสนองก่อนและใช้หากมี หากคำขอไม่ได้อยู่ในแคช ระบบจะใช้เครือข่ายนั้น แล้วเพิ่มการตอบสนองที่ถูกต้องลงในแคชก่อนที่จะส่งไปยังเบราว์เซอร์
  • เครือข่ายเท่านั้น บังคับให้การตอบกลับมาจากเครือข่าย
  • แคชเท่านั้น บังคับให้การตอบกลับมาจากแคช

คุณสามารถใช้กลยุทธ์เหล่านี้เพื่อเลือกคำขอโดยใช้วิธีที่ workbox-routing มีให้

การใช้กลยุทธ์การแคชกับการจับคู่เส้นทาง

workbox-routing แสดงเมธอด registerRoute เพื่อจับคู่เส้นทางและจัดการโดยใช้กลยุทธ์การแคช registerRoute ยอมรับออบเจ็กต์ Route ซึ่งก็ยอมรับอาร์กิวเมนต์ 2 รายการดังนี้

  1. สตริง นิพจน์ทั่วไป หรือโค้ดเรียกกลับที่ตรงกันเพื่อระบุเกณฑ์การจับคู่เส้นทาง
  2. เครื่องจัดการสำหรับเส้นทาง โดยทั่วไปจะเป็นกลยุทธ์ที่ workbox-strategies ให้บริการ

แนะนำให้ใช้โค้ดเรียกกลับเพื่อจับคู่กับเส้นทาง เนื่องจากให้ออบเจ็กต์บริบทที่ประกอบด้วยออบเจ็กต์ Request, สตริง URL คำขอ, เหตุการณ์การดึงข้อมูล และบูลีนที่ระบุว่าคำขอเป็นคำขอที่มีต้นทางเดียวกันหรือไม่

จากนั้นเครื่องจัดการจะจัดการเส้นทางที่ตรงกัน ในตัวอย่างต่อไปนี้ ระบบจะสร้างเส้นทางใหม่ที่ตรงกับคำขอรูปภาพต้นทางเดียวกันที่กำลังจะส่งเข้ามา และใช้แคชก่อน แล้วกลับไปใช้กลยุทธ์เครือข่าย

// 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);

การใช้แคชหลายรายการ

Workbox ช่วยให้คุณเก็บการตอบกลับที่แคชไว้ออกเป็นอินสแตนซ์ 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 ระบบแสดงแคชที่แตกต่างกัน 3 แบบ ได้แก่ แคชที่ตั้งชื่อว่า "scripts" อีกรูปหนึ่งชื่อว่า "styles" และอันสุดท้ายชื่อว่า 'images'
โปรแกรมดูพื้นที่เก็บข้อมูลแคชในแผงแอปพลิเคชันของเครื่องมือสำหรับนักพัฒนาเว็บใน 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 ของ Workbox จะช่วยให้บรรลุเป้าหมายดังกล่าว

การพิจารณาแบบข้ามต้นทาง

การโต้ตอบระหว่าง Service Worker และชิ้นงานข้ามต้นทางแตกต่างจากชิ้นงานที่มีต้นทางเดียวกันเป็นอย่างมาก Cross-Origin Resource Shared (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 คุณควรใช้กลยุทธ์ที่เน้นเครือข่ายเป็นหลักหรือใช้ระบบเก่าขณะตรวจสอบเพื่อจัดการกับการตอบกลับดังกล่าว ใช่ ซึ่งหมายความว่าระบบจะยังขอเนื้อหาจากเครือข่ายทุกครั้ง แต่มั่นใจได้ว่าการตอบกลับที่ล้มเหลวจะหายไป และในที่สุดจะมีการแทนที่ด้วยการตอบกลับที่ใช้งานได้

หากคุณใช้กลยุทธ์การแคชแบบอื่นและมีการส่งคืนการตอบกลับที่ไม่ชัดเจน กล่องงานจะเตือนคุณว่าระบบไม่ได้แคชคำตอบนั้นเมื่ออยู่ในโหมดการพัฒนา

บังคับแคชคำตอบที่ไม่ชัดเจน

หากมั่นใจว่าต้องการแคชการตอบกลับที่คลุมเครือโดยใช้กลยุทธ์แบบเน้นแคชเป็นหลักหรือเฉพาะแคช คุณก็บังคับให้ 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);

การตอบกลับแบบทึบและ navigator.storage API

เพื่อหลีกเลี่ยงการรั่วไหลของข้อมูลข้ามโดเมน มีการเพิ่มระยะห่างจากขอบอย่างมีนัยสำคัญในขนาดของการตอบสนองที่ทึบแสงซึ่งใช้ในการคำนวณขีดจำกัดโควต้าของพื้นที่เก็บข้อมูล การดําเนินการนี้จะส่งผลต่อวิธีที่ navigator.storage API รายงานโควต้าพื้นที่เก็บข้อมูล

ระยะห่างจากขอบนี้จะแตกต่างกันไปในแต่ละเบราว์เซอร์ แต่สำหรับ Chrome ขนาดขั้นต่ำที่การตอบสนองที่ไม่ชัดเจนในแคชหนึ่งๆ ทำให้เกิดพื้นที่เก็บข้อมูลโดยรวมที่ใช้ประมาณ 7 เมกะไบต์ โปรดคำนึงถึงเรื่องนี้เมื่อกำหนดจำนวนคำตอบที่ไม่ชัดเจนที่ต้องการแคช เนื่องจากคุณอาจเกินโควต้าพื้นที่เก็บข้อมูลเร็วกว่าที่คาดไว้มาก