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

Eviction และ Persistence

storage ของทุก origin อยู่ในหนึ่งในสองโหมด:

  • Best-effort — โหมดเริ่มต้น browser อาจ ลบข้อมูลจาก origin โดยไม่มีการแจ้งเตือนหากอุปกรณ์มีพื้นที่ดิสก์ไม่เพียงพอ
  • Persistent — browser จะ ไม่ ลบข้อมูลของ origin โดยอัตโนมัติ ข้อมูลจะถูกลบเมื่อผู้ใช้ลบเองเท่านั้น

แอปพลิเคชันเว็บส่วนใหญ่ทำงานในโหมด best-effort ซึ่งเพียงพอสำหรับ cache ที่ไม่สำคัญ หากแอปของคุณต้องพึ่งพาข้อมูล cache เพื่อการทำงานออฟไลน์ คุณควรร้องขอ persistent storage

Eviction เป็นการตัดสินใจของ browser ที่เกิดจาก storage pressure ขั้นตอนทั่วไปคือ:

  1. อุปกรณ์มีพื้นที่ว่างน้อยลง
  2. browser ตัดสินใจว่าต้องคืน storage
  3. เดินผ่าน origin ตามลำดับ least-recently-used (LRU) โดยประมาณ — origin ที่ไม่ได้เข้าชมมานานเป็นผู้สมัครก่อน
  4. origin แบบ best-effort ถูกล้าง; origin แบบ persistent ถูกปล่อยไว้

Eviction ส่งผลต่อ storage ทั้งหมด ของ origin พร้อมกัน: Cache API, IndexedDB และกลไกอื่น ๆ ที่นับ quota ถูกล้างพร้อมกัน

การเรียก navigator.storage.persist() ส่งคำขอไปยัง browser เพื่อย้าย origin ไปยังโหมด persistent browser อาจอนุมัติหรือไม่อนุมัติ:

const granted = await navigator.storage.persist();
if (granted) {
console.log('Storage is persistent — data is safe');
} else {
console.log('Best-effort only — browser may evict under pressure');
}

ปัจจัยที่มีอิทธิพลต่อการตัดสินใจของ browser ได้แก่ การที่ผู้ใช้ติดตั้ง PWA ไว้ที่ home screen คะแนน engagement ของ site และการที่ผู้ใช้ได้ให้สิทธิ์ permission อื่น ๆ ไว้แล้ว

ใช้ navigator.storage.persisted() เมื่อเริ่มต้นแอป:

const isAlreadyPersistent = await navigator.storage.persisted();
if (!isAlreadyPersistent) {
const granted = await navigator.storage.persist();
if (!granted) {
console.warn('Could not get persistent storage. Cached data may be lost.');
}
}
  • อย่าสมมติ ว่า persist() จะคืนค่า true เสมอ — จัดการกรณี false ให้เหมาะสม
  • เรียก persisted() ก่อนเพื่อหลีกเลี่ยงการแจ้งเตือนซ้ำซ้อน
  • สำหรับแอปที่ต้องทำงานออฟไลน์ ควรเก็บข้อมูล diagnostic ไว้ใน localStorage เพื่อตรวจจับการสูญเสียข้อมูลเมื่อโหลดหน้าครั้งถัดไป
ตัวเลือกBenefitCost
อยู่ในโหมด best-effort (ค่าเริ่มต้น)ไม่ต้องขอ permission จากผู้ใช้ ใช้งานได้ทันที เหมาะกับ cache ที่ไม่สำคัญbrowser อาจ evict ข้อมูลได้ตลอดเวลาโดยไม่แจ้งเตือนเมื่อดิสก์ตึง
เรียก navigator.storage.persist() เพื่อขอ persistent storageข้อมูลปลอดภัยจากการ evict อัตโนมัติ เหมาะกับแอปที่พึ่งพาข้อมูลออฟไลน์ต้องผ่านเงื่อนไขของ browser (เช่น engagement, การติดตั้ง PWA) และอาจถูกปฏิเสธ ทำให้โค้ดต้อง handle ทั้งสองกรณี
เช็ค persisted() ก่อนขอ persist() ทุกครั้งหลีกเลี่ยงการขอ permission ซ้ำซ้อนที่รบกวนผู้ใช้เพิ่ม async call หนึ่งจังหวะก่อนเริ่ม flow หลัก
  • สมมติว่า persist() คืนค่า true เสมอโดยไม่เช็คผลลัพธ์ — browser อาจปฏิเสธคำขอเงียบ ๆ ต้อง handle กรณี false และแจ้งเตือนผู้ใช้หรือ fallback ตามความเหมาะสม
  • ไม่เคยเรียก navigator.storage.persisted() ก่อน persist() — ทำให้เรียกขอ permission ซ้ำทุกครั้งที่โหลดแอป ทั้งที่อาจได้รับสิทธิ์ไปแล้ว
  • เข้าใจว่า eviction ลบเฉพาะ cache ที่เก่าที่สุด — จริง ๆ แล้ว browser ล้าง storage ทั้งหมดของ origin พร้อมกัน ทั้ง Cache API และ IndexedDB ไม่ได้เลือกลบทีละรายการ

💡 ตัวอย่างจากของจริง

Twitter Lite — ขอ persistent storage เพื่อป้องกันไม่ให้ app shell ที่ cache ไว้ถูก evict ระหว่างที่ผู้ใช้ engagement ต่ำ

Wikipedia — บทความที่ผู้ใช้บันทึกไว้อ่านออฟไลน์ต้องพึ่ง persistent storage ไม่งั้นอาจถูกลบทิ้งเมื่อดิสก์ของอุปกรณ์ใกล้เต็ม

โหมด storage เริ่มต้นของ web origin ใหม่คืออะไร?
เมื่อ browser evict origin แบบ best-effort เนื่องจาก storage pressure อะไรถูกล้าง?
navigator.storage.persist() คืนค่าอะไรถ้า browser ปฏิเสธคำขอ?