Cache API vs IndexedDB vs localStorage
เลือก storage mechanism ที่เหมาะสม
หัวข้อที่มีชื่อว่า “เลือก storage mechanism ที่เหมาะสม”browser มี storage API หลักสามตัวสำหรับข้อมูลถาวร แต่ละตัวมีวัตถุประสงค์ต่างกันและเสริมกัน — สิ่งสำคัญคือต้องเลือกให้ถูกกรณี
| Storage | เหมาะสำหรับ | ประเภทข้อมูล | Async? | ขนาดโดยประมาณ |
|---|---|---|---|---|
| Cache API | HTTP response, static asset | Request/Response | ใช่ | ขนาดใหญ่ (GB ได้) |
| IndexedDB | ข้อมูลแอปที่มีโครงสร้าง, ข้อมูลออฟไลน์ | JS object, blob | ใช่ | ขนาดใหญ่ (GB ได้) |
| localStorage | string config ขนาดเล็ก, preferences | string เท่านั้น | ไม่ (synchronous) | ~5 MB |
Cache API
หัวข้อที่มีชื่อว่า “Cache API”Cache API จัดเก็บคู่ Request/Response มีรูปแบบเหมือน HTTP — key คือ URL และ value คือ Response เหมาะสำหรับ:
- Pre-caching static asset (HTML, CSS, JS, รูปภาพ) เพื่อใช้ออฟไลน์
- Runtime caching ของ API response ภายใน Service Worker
- ให้บริการเนื้อหา stale ขณะดึงข้อมูลใหม่ในพื้นหลัง
Cache API มีประโยชน์สูงสุดเมื่อใช้ร่วมกับ Service Worker ดูรูปแบบการแคชด้วย Service Worker ได้ที่ PWA course
IndexedDB
หัวข้อที่มีชื่อว่า “IndexedDB”IndexedDB จัดเก็บ JavaScript value ใด ๆ (object, array, blob, typed array) ใน object store พร้อม index ที่เลือกได้ เหมาะสำหรับ:
- ข้อมูลแอปออฟไลน์: ข้อมูลผู้ใช้, ข้อความ, เอกสาร
- Blob ขนาดใหญ่: เสียง, วิดีโอ, รูปภาพที่เป็นส่วนหนึ่งของโมเดลข้อมูลแอป
- ข้อมูลที่ต้องการ query, เรียงลำดับ หรือกรองฝั่ง client
localStorage
หัวข้อที่มีชื่อว่า “localStorage”localStorage จัดเก็บคู่ key/value ที่เป็น string แบบ synchronous โดยบล็อก main thread ทุกครั้งที่อ่านหรือเขียน เหมาะสำหรับ:
- Preference ขนาดเล็ก: เลือก theme, ภาษา, token เดียว
- ค่าที่อ่านทุกครั้งที่โหลดหน้า โดยยอมรับการเข้าถึงแบบ synchronous
- ข้อมูลที่มีขนาดไม่กี่ kilobyte
ห้ามจัดเก็บ object ขนาดใหญ่หรือเขียนบ่อยใน localStorage เนื่องจากจะทำให้ rendering หยุดชะงัก
แผนภาพการตัดสินใจ
หัวข้อที่มีชื่อว่า “แผนภาพการตัดสินใจ”flowchart TD
Q[What do you need to store?]
Q --> A{HTTP responses
or assets?}
A -->|Yes| CacheAPI[Cache API
caches.open / put / match]
A -->|No| B{Structured
app data?}
B -->|Yes| IDB[IndexedDB
object stores + indexes]
B -->|No| C{Tiny string
preference?}
C -->|Yes| LS[localStorage
setItem / getItem]
C -->|No| IDB ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Cache API สำหรับ HTTP response | จับคู่กับโมเดล Request/Response โดยตรง เหมาะกับ asset และ API response แบบ pre-cache | ไม่เหมาะกับข้อมูลที่มีโครงสร้าง (structured data) — ถ้าต้อง query หรือ index ควรใช้ IndexedDB แทน |
| IndexedDB สำหรับข้อมูลแอป | query, index และ transaction รองรับข้อมูลซับซ้อนได้ | API ใช้งานยากกว่า ต้องจัดการ schema version และ object store เอง |
| localStorage สำหรับ preference เล็ก ๆ | เขียนอ่านง่าย ใช้ syntax synchronous | บล็อก main thread ทุกครั้งที่เข้าถึง ไม่เหมาะกับข้อมูลขนาดใหญ่หรือเขียนถี่ |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ใช้ Cache API เก็บข้อมูล JS object ทั่วไปโดยแปลงเป็น JSON string ใส่ใน Response เอง — เพิ่มความซับซ้อนโดยไม่จำเป็น ถ้าข้อมูลไม่ใช่ HTTP request/response ควรใช้ IndexedDB ตั้งแต่แรก
- ใช้ localStorage เก็บข้อมูลขนาดใหญ่หรือ cache ทั้งชุด — synchronous I/O ของ localStorage บล็อก main thread ทำให้ UI ค้าง ควรย้ายไป IndexedDB หรือ Cache API
- คิดว่า Cache API และ IndexedDB แข่งกัน ต้องเลือกอย่างใดอย่างหนึ่ง — ในแอป PWA ส่วนใหญ่ใช้ร่วมกัน: Cache API เก็บ asset, IndexedDB เก็บข้อมูลแอป
💡 ตัวอย่างจากของจริง
Twitter Lite — ใช้ Cache API เก็บ app shell (HTML/CSS/JS) ให้โหลดเร็ว และใช้ IndexedDB เก็บ timeline กับข้อมูลผู้ใช้ที่ต้อง query
Wikipedia — โหมดอ่านออฟไลน์ใช้ Cache API เก็บหน้าบทความที่ผู้ใช้บันทึกไว้ ร่วมกับ Service Worker เพื่อ serve เนื้อหาโดยไม่ต้องพึ่ง network