ข้ามไปยังเนื้อหา

เปรียบเทียบตัวเลือก storage

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 เป็น 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 ใช้ 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 เป็น 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 ล้วน return IDBRequest objects (สามารถ 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 เก็บคู่ 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

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
CookieslocalStoragesessionStorageIndexedDBCache APIOPFS
ความจุโดยประมาณ4 KB5–10 MB5–10 MBหลายร้อย MBหลายร้อย MBหลายร้อย MB
รูปแบบ APISyncSyncSyncAsyncAsyncAsync (+ sync ใน Worker)
ส่งพร้อม HTTP?ใช่ไม่ไม่ไม่ไม่ไม่
คงอยู่ข้าม tabsใช่ใช่ไม่ใช่ใช่ใช่
คงอยู่ข้าม restartsปรับแต่งได้ใช่ไม่ใช่ใช่ใช่
อาจถูก evict?ไม่ (หมดอายุ)ไม่ไม่ใช่ (best-effort)ใช่ (best-effort)ใช่ (best-effort)
Use case หลักAuth / serverUI statePer-tab stateStructured app dataNetwork cachingFile / WASM I/O
ตัวเลือกBenefitCost
Cookiesส่งไปกับ HTTP request อัตโนมัติ เหมาะกับ server-side authความจุแค่ 4 KB และเพิ่ม payload ให้ทุก request แม้ไม่จำเป็น
localStorage / sessionStorageAPI ง่าย ใช้งานได้ทันทีโดยไม่ต้อง setupSynchronous, block main thread และความจุจำกัดแค่ 5–10 MB
IndexedDBรองรับข้อมูลจำนวนมาก, query ได้, async ไม่ block threadAPI ซับซ้อนกว่า ต้องจัดการ 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 ขนาดใหญ่ที่ต้อง querylocalStorage เก็บได้แค่ 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

storage ประเภทใดที่ถูกรวมเข้ากับ HTTP requests ที่ส่งไปยัง domain ที่ตรงกันโดยอัตโนมัติ?
ผู้ใช้ปิด browser tab หนึ่ง storage ใดยังคงเก็บข้อมูลไว้?
storage API สองตัวใดที่ใช้ synchronous read/write interface เดียวกัน?
แอปต้องการเก็บ records ที่มีโครงสร้างขนาด 200 MB และต้องคงอยู่หลัง browser restart API ใดเหมาะสมที่สุด?