Cache API
เวลาต้องคุมเองว่าจะ cache request ไหน ใช้กลยุทธ์อะไร และเมื่อไรจะลบทิ้ง — service worker เพียงอย่างเดียวไม่พอ ต้องมี API ที่จัดการคู่ Request/Response ได้โดยตรง นี่คือหน้าที่ของ Cache API
method ทั้งหมดของ Cache API
หัวข้อที่มีชื่อว่า “method ทั้งหมดของ Cache API”Cache API เข้าถึงได้ผ่าน global object caches ด้านล่างนี้คือ method ทั้งหมดที่คุณจะใช้
caches.open(name)
หัวข้อที่มีชื่อว่า “caches.open(name)”เปิด cache ที่มีชื่อ หรือสร้างใหม่ถ้ายังไม่มี คืนค่าเป็น Cache object
const cache = await caches.open('demo-cache-v1');cache.put(request, response)
หัวข้อที่มีชื่อว่า “cache.put(request, response)”จัดเก็บคู่ Request/Response อาร์กิวเมนต์แรกอาจเป็น Request object หรือ URL string ส่วนอาร์กิวเมนต์ที่สองต้องเป็น Response หากมี entry สำหรับ request เดิมอยู่แล้ว จะถูกแทนที่
const cache = await caches.open('demo-cache-v1');await cache.put('/api/hello', new Response('{"status":"ok"}', { headers: { 'Content-Type': 'application/json' },}));cache.add(url)
หัวข้อที่มีชื่อว่า “cache.add(url)”ดึงข้อมูลจาก URL ที่ระบุแล้วจัดเก็บ response ที่ได้ไว้ใน cache เทียบเท่ากับการเรียก fetch(url) ตามด้วย cache.put(url, response) request ต้องสำเร็จ (status 2xx) มิฉะนั้น cache จะไม่ถูกอัปเดต
const cache = await caches.open('demo-cache-v1');await cache.add('/images/logo.png'); // fetches then storescache.addAll(urls)
หัวข้อที่มีชื่อว่า “cache.addAll(urls)”รับ array ของ URL string แล้ว fetch ทั้งหมดแบบ atomic ถ้า request ใด แม้แต่ตัวเดียว ล้มเหลว จะ ไม่มี response ใดถูกจัดเก็บเลย ใช้เมื่อต้องการ cache asset กลุ่มหนึ่งพร้อมกันทั้งหมดหรือไม่เลย
const cache = await caches.open('demo-cache-v1');await cache.addAll([ '/index.html', '/styles/main.css', '/scripts/app.js',]);cache.match(request, options?)
หัวข้อที่มีชื่อว่า “cache.match(request, options?)”ค้นหาใน cache สำหรับ entry ที่ตรงกับ request ที่ระบุ (URL string หรือ Request) คืนค่า Response ที่ตรงกัน หรือ undefined ถ้าไม่พบ argument options (ไม่บังคับ) รับ ignoreSearch, ignoreMethod, และ ignoreVary
const cache = await caches.open('demo-cache-v1');const response = await cache.match('/api/hello');if (response) { console.log(await response.json());}caches.match(request, options?)
หัวข้อที่มีชื่อว่า “caches.match(request, options?)”เหมือนกับ cache.match แต่ค้นหาในทุก cache ที่มีชื่อของ origin ปัจจุบัน คืนค่า match แรกที่พบ มีประโยชน์เมื่อไม่ทราบว่า response ที่ต้องการอยู่ใน cache ไหน
const response = await caches.match('/api/hello');cache.delete(request, options?)
หัวข้อที่มีชื่อว่า “cache.delete(request, options?)”ลบ entry เฉพาะออกจาก cache ที่มีชื่อ คืนค่า true ถ้าพบและลบได้ หรือ false ถ้าไม่พบ
const cache = await caches.open('demo-cache-v1');const deleted = await cache.delete('/api/hello');console.log('Deleted:', deleted); // truecaches.keys()
หัวข้อที่มีชื่อว่า “caches.keys()”คืนค่า array ของชื่อ cache ทั้งหมดสำหรับ origin ปัจจุบัน ใช้สำหรับจัดการ version
const names = await caches.keys();console.log('Open caches:', names);
// Delete all cachesfor (const name of names) { await caches.delete(name);}ลองเลย: สร้าง, จับคู่, และล้าง cache
หัวข้อที่มีชื่อว่า “ลองเลย: สร้าง, จับคู่, และล้าง cache”ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
ใช้ cache.put() เก็บ opaque response (cross-origin, no-cors) | ใช้งานได้กับ resource จาก CDN หรือ third-party ที่ไม่มี CORS header | นับ quota ที่ขนาดเต็มจริง แม้จะอ่าน body ไม่ได้ ทำให้ quota หมดเร็วโดยไม่รู้ตัว |
ใช้ cache.addAll() แบบ atomic สำหรับ pre-cache | รับประกันว่า asset ที่ประกาศ install ครบทุกตัวหรือไม่มีเลย ป้องกัน state ที่ asset ขาดหาย | ถ้า asset ตัวเดียว 404 การติดตั้งทั้งหมดล้มเหลว ต้องออกแบบ error handling ให้รอบคอบ |
ตั้งชื่อ cache แบบมี version (เช่น demo-cache-v2) | เปลี่ยน strategy หรืออัปเดต asset ได้โดยไม่ปนกับ cache เก่า | ต้องเขียนโค้ดลบ cache version เก่าเองใน activate event ไม่งั้น storage โตไม่มีที่สิ้นสุด |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- เก็บ opaque response ไว้ใน cache แล้วคิดว่าไม่กินพื้นที่เพราะอ่าน body ไม่ได้ — browser นับขนาดเต็มของ opaque response (มักหลาย MB ต่อรายการ) เข้า quota เหมือน response ปกติ
- ไม่เคยลบ cache version เก่าเมื่อ deploy ใหม่ — ทุกครั้งที่เปลี่ยนชื่อ cache (เช่น v1 → v2) ต้องเรียก
caches.delete()กับชื่อเก่าในactivateevent ไม่งั้น storage สะสมไม่มีวันจบ - ใช้
cache.add()/addAll()กับ request โดยไม่เช็ค response status ก่อน — method เหล่านี้เก็บ response ทุกสถานะรวมถึง error page ที่ server อาจส่งมาโดยไม่ throw ต้องตรวจสอบเองถ้าต้องการความชัวร์