เปรียบเทียบตัวเลือก storage
Cookies
หัวข้อที่มีชื่อว่า “Cookies”Cookies ถูกนำมาใช้ตั้งแต่ปี 1994 และยังคงเป็น client-side store เพียงอย่างเดียวที่มีส่วนร่วมใน HTTP request cycle browser จะแนบ cookies ที่ตรงกันไปกับทุก request โดยอัตโนมัติ ทำให้เป็นกลไกมาตรฐานสำหรับ session tokens และการยืนยันตัวตนฝั่ง server
- ความจุ: 4 KB ต่อ cookie browser จำกัด cookies รวมต่อ domain ไว้ที่ประมาณ 50 รายการ (แตกต่างกันตาม browser)
- รูปแบบ API: Synchronous อ่านผ่าน
document.cookie(คืนค่าเป็น string ที่คั่นด้วย semicolon) เขียนโดยการกำหนดค่า string ในรูปแบบSet-Cookieให้กับdocument.cookie - Persistence: ปรับแต่งได้ Session cookies หมดอายุเมื่อปิด browser Persistent cookies มี attribute
ExpiresหรือMax-Age - Use case หลัก: Session tokens, identity ผู้ใช้, server-side feature flags และค่าใดก็ตามที่ server ต้องเห็นในทุก request
localStorage
หัวข้อที่มีชื่อว่า “localStorage”localStorage เป็น persistent client-side store ที่ใช้งานง่ายที่สุด ข้อมูลจะคงอยู่แม้ปิด browser และแชร์ร่วมกันระหว่างทุก tab และ window บน origin เดียวกัน
- ความจุ: 5–10 MB ต่อ origin (5 MB เป็น limit ที่ปลอดภัยในทางปฏิบัติ ขึ้นกับ browser)
- รูปแบบ API: Synchronous —
localStorage.setItem(key, value),localStorage.getItem(key),localStorage.removeItem(key),localStorage.clear() - Persistence: ไม่มีวันหมดอายุ ข้อมูลคงอยู่จนกว่าผู้ใช้จะล้าง site data หรือโค้ดเรียก
clear() - Use case หลัก: User preferences, theme settings, cached UI state และค่าเล็กน้อยที่ไม่ต้องส่งไปยัง server
sessionStorage
หัวข้อที่มีชื่อว่า “sessionStorage”sessionStorage ใช้ synchronous API เดียวกับ localStorage แต่ scope อยู่กับ browser tab เดียว
- ความจุ: 5–10 MB ต่อ origin (limit เดียวกับ
localStorage) - รูปแบบ API: Synchronous — interface เหมือนกันทุกประการกับ
localStorage - Persistence: อยู่ได้เพียงตลอดอายุ tab เมื่อปิด tab หรือออกจาก origin ข้อมูลจะถูกล้าง tab อื่นไม่สามารถอ่านได้แม้จะใช้ origin เดียวกัน
- Use case หลัก: สถานะ wizard หรือแบบฟอร์มหลายขั้นตอน, navigation history ต่อ tab, ข้อมูลชั่วคราวที่ไม่ควรแพร่กระจายข้าม tabs
IndexedDB
หัวข้อที่มีชื่อว่า “IndexedDB”IndexedDB เป็น database transactional เต็มรูปแบบภายใน browser เก็บ JavaScript objects ที่มีโครงสร้างได้ (ไม่ใช่แค่ strings) รองรับ secondary indexes และมี Promise-friendly async API (ผ่าน native event model หรือ libraries เช่น idb)
- ความจุ: browser จัดสรร quota แบบ dynamic ในทางปฏิบัติ origins สามารถเก็บข้อมูลได้ตั้งแต่หลายร้อย megabytes ถึงหลาย gigabytes ขึ้นอยู่กับ disk ที่เหลือและนโยบาย browser
- รูปแบบ API: Asynchronous ทุก operation ไม่ block:
IDBObjectStore.put(),IDBObjectStore.get(), cursor iteration ล้วน returnIDBRequestobjects (สามารถ wrap เป็น Promises ได้) - Persistence: Persistent โดย default (best-effort) สามารถอัปเกรดเป็น durable storage ได้ด้วย
navigator.storage.persist() - Use case หลัก: Offline apps, datasets ขนาดใหญ่, records ที่ต้องการ query, draft storage, local-first applications
Cache API
หัวข้อที่มีชื่อว่า “Cache API”Cache API เก็บคู่ Request/Response ออกแบบมาสำหรับ service workers เพื่อให้ network responses สามารถ intercept, cache และ serve ได้ขณะที่อุปกรณ์ offline
- ความจุ: แชร์ quota pool เดียวกับ IndexedDB และ OPFS (“bucket” storage) โดยทั่วไปมีหลายร้อย megabytes
- รูปแบบ API: Asynchronous —
caches.open(name)คืนPromise<Cache>จากนั้นcache.put(request, response),cache.match(request),cache.delete(request) - Persistence: Best-effort (อาจถูก evict ภายใต้ storage pressure) เว้นแต่ origin จะได้รับ persistent storage
- Use case หลัก: Precaching app shells สำหรับ service workers, runtime caching ของ API responses, offline-first PWAs
Origin Private File System (OPFS)
หัวข้อที่มีชื่อว่า “Origin Private File System (OPFS)”OPFS มอบพื้นที่ file system แบบ sandboxed และส่วนตัวของอุปกรณ์แก่แต่ละ origin โดยไม่ต้องขอ permission ต่างจาก public File System Access API ตรงที่ไฟล์ OPFS ไม่ปรากฏใน file picker ของผู้ใช้
- ความจุ: แชร์ quota pool เดียวกับ IndexedDB และ Cache API
- รูปแบบ API: ส่วนใหญ่ asynchronous (
FileSystemDirectoryHandle,FileSystemFileHandle) พร้อม synchronous interface ประสิทธิภาพสูง (createSyncAccessHandle()) ที่ใช้ได้เฉพาะใน Web Workers - Persistence: Best-effort โดย default สามารถทำให้ persistent ได้
- Use case หลัก: SQLite-in-WASM, large binary assets, media files, use cases ที่ต้องการ file-level random access หรือ synchronous I/O path ใน Worker
สรุปแบบเคียงกัน
หัวข้อที่มีชื่อว่า “สรุปแบบเคียงกัน”| Cookies | localStorage | sessionStorage | IndexedDB | Cache API | OPFS | |
|---|---|---|---|---|---|---|
| ความจุโดยประมาณ | 4 KB | 5–10 MB | 5–10 MB | หลายร้อย MB | หลายร้อย MB | หลายร้อย MB |
| รูปแบบ API | Sync | Sync | Sync | Async | Async | Async (+ sync ใน Worker) |
| ส่งพร้อม HTTP? | ใช่ | ไม่ | ไม่ | ไม่ | ไม่ | ไม่ |
| คงอยู่ข้าม tabs | ใช่ | ใช่ | ไม่ | ใช่ | ใช่ | ใช่ |
| คงอยู่ข้าม restarts | ปรับแต่งได้ | ใช่ | ไม่ | ใช่ | ใช่ | ใช่ |
| อาจถูก evict? | ไม่ (หมดอายุ) | ไม่ | ไม่ | ใช่ (best-effort) | ใช่ (best-effort) | ใช่ (best-effort) |
| Use case หลัก | Auth / server | UI state | Per-tab state | Structured app data | Network caching | File / WASM I/O |
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Cookies | ส่งไปกับ HTTP request อัตโนมัติ เหมาะกับ server-side auth | ความจุแค่ 4 KB และเพิ่ม payload ให้ทุก request แม้ไม่จำเป็น |
localStorage / sessionStorage | API ง่าย ใช้งานได้ทันทีโดยไม่ต้อง setup | Synchronous, block main thread และความจุจำกัดแค่ 5–10 MB |
| IndexedDB | รองรับข้อมูลจำนวนมาก, query ได้, async ไม่ block thread | API ซับซ้อนกว่า ต้องจัดการ transactions และ schema versioning เอง |
| Cache API / OPFS | เหมาะกับ offline assets และ binary files ขนาดใหญ่ | ต้องใช้ร่วมกับ service worker หรือ Worker context จึงจะได้ประโยชน์เต็มที่ |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ใช้ cookies เก็บข้อมูล UI state ทั่วไป — cookies ถูกส่งไปกับทุก HTTP request ทำให้ request หนักขึ้นโดยไม่จำเป็น ทั้งที่ข้อมูลแบบนี้ไม่เกี่ยวกับ server เลย ควรใช้
localStorageแทน - ใช้
localStorageเก็บ dataset ขนาดใหญ่ที่ต้อง query —localStorageเก็บได้แค่ string, ไม่มี index และเป็น synchronous ทำให้ scale ไม่ได้ ควรย้ายไป IndexedDB ตั้งแต่ต้น - ลืมว่าทุก store แบบ best-effort อาจถูก evict ได้ — คิดว่า IndexedDB หรือ Cache API เก็บถาวรเหมือน
localStorageทั้งที่ default เป็น best-effort และ browser อาจลบทิ้งได้เมื่อ disk เหลือน้อย
💡 ตัวอย่างจากของจริง
Gmail — ใช้ IndexedDB เก็บ email สำหรับโหมด offline เพราะต้องการความจุมากและ query ที่ซับซ้อนกว่าที่ Web Storage รองรับได้
เว็บไซต์ e-commerce ทั่วไป — ใช้ cookies เก็บ session token และ auth state เพราะต้องส่งไปยัง server ทุก request ส่วน
localStorageใช้เก็บแค่ preference เช่น currency หรือ theme ที่ไม่เกี่ยวกับ server