พื้นที่เก็บข้อมูลสำหรับเว็บ

มีตัวเลือกมากมายในการจัดเก็บข้อมูลในเบราว์เซอร์ ตัวเลือกใดเหมาะกับความต้องการของคุณมากที่สุด

การเชื่อมต่ออินเทอร์เน็ตอาจไม่เสถียรหรือไม่มีเลยในขณะเดินทาง ด้วยเหตุนี้ การรองรับการใช้งานออฟไลน์และประสิทธิภาพที่เชื่อถือได้จึงเป็นฟีเจอร์ที่พบได้ทั่วไปในProgressive Web App แม้ในสภาพแวดล้อมแบบไร้สายที่สมบูรณ์แบบ การใช้เทคนิคการแคชและพื้นที่เก็บข้อมูลอื่นๆ อย่างรอบคอบก็ช่วยปรับปรุงประสบการณ์ของผู้ใช้ได้อย่างมาก มีหลายวิธีในการแคชทรัพยากรแอปพลิเคชันแบบคงที่ (HTML, JavaScript, CSS, รูปภาพ ฯลฯ) และข้อมูล (ข้อมูลผู้ใช้ บทความข่าว ฯลฯ) แต่โซลูชันใดดีที่สุด คุณจัดเก็บข้อมูลได้มากแค่ไหน คุณจะป้องกันไม่ให้ระบบนำข้อมูลออกจากแคชได้อย่างไร

ฉันควรใช้ตัวเลือกใด

คำแนะนำทั่วไปสำหรับการจัดเก็บทรัพยากรมีดังนี้

เบราว์เซอร์ที่ทันสมัยทุกเบราว์เซอร์รองรับ IndexedDB, OPFS และ Cache Storage API ซึ่งเป็นแบบอะซิงโครนัสและจะไม่บล็อกเทรดหลัก (แต่ก็มีตัวแปรแบบซิงโครนัสของ OPFS ที่พร้อมใช้งานเฉพาะใน Web Worker ด้วย) โดยสามารถเข้าถึงได้จากออบเจ็กต์ window, Web Worker และ Service Worker ซึ่งทำให้ใช้ได้ทุกที่ในโค้ด

แล้วกลไกการจัดเก็บข้อมูลอื่นๆ ล่ะ

มีกลไกการจัดเก็บข้อมูลอื่นๆ อีกหลายอย่างในเบราว์เซอร์ แต่กลไกเหล่านั้นมีการใช้งานที่จำกัดและอาจทำให้เกิดปัญหาด้านประสิทธิภาพที่สำคัญ

SessionStorage จะเจาะจงแท็บและกำหนดขอบเขตตามอายุการใช้งานของแท็บ ซึ่งอาจเป็นประโยชน์สำหรับการจัดเก็บข้อมูลเฉพาะเซสชันจำนวนเล็กน้อย เช่น คีย์ IndexedDB ควรใช้ด้วยความระมัดระวังเนื่องจากเป็นแบบพร้อมกันและจะบล็อกเทรดหลัก โดยจะจำกัดไว้ที่ประมาณ 5 MB และมีได้เฉพาะสตริงเท่านั้น เนื่องจากเป็นแบบเฉพาะแท็บ จึงไม่สามารถเข้าถึงได้จาก Web Worker หรือ Service Worker

ควรหลีกเลี่ยง LocalStorage เนื่องจากเป็นแบบซิงโครนัสและจะบล็อกเทรดหลัก โดยจะจำกัดไว้ที่ประมาณ 5 MB และมีได้เฉพาะสตริงเท่านั้น LocalStorage ไม่สามารถเข้าถึงได้จาก Web Worker หรือ Service Worker

คุกกี้มีประโยชน์ แต่ไม่ควรใช้เพื่อจัดเก็บข้อมูล ระบบจะส่งคุกกี้ไปพร้อมกับคำขอ HTTP ทุกรายการ ดังนั้นการจัดเก็บข้อมูลที่มากกว่าข้อมูลจำนวนเล็กน้อยจะเพิ่มขนาดของคำขอเว็บทุกรายการอย่างมาก โดยเป็นแบบซิงโครนัสและเข้าถึงจาก Web Worker ไม่ได้ คุกกี้จะจำกัดเฉพาะสตริงเท่านั้น เช่นเดียวกับ LocalStorage และ SessionStorage

File System Access API ออกแบบมาเพื่อให้ผู้ใช้สามารถอ่านและแก้ไขไฟล์ในระบบไฟล์ในเครื่องได้ ผู้ใช้ต้องให้สิทธิ์ก่อนที่หน้าเว็บจะอ่านหรือเขียนลงในไฟล์ในเครื่องได้ และสิทธิ์จะไม่คงอยู่ข้ามเซสชัน เว้นแต่จะมีการแคชแฮนเดิลไฟล์ไว้ใน IndexedDB File System Access API เหมาะที่สุดสำหรับกรณีการใช้งานอย่างเช่นเครื่องมือแก้ไข ซึ่งคุณต้องเปิดไฟล์ แก้ไขไฟล์ แล้วอาจบันทึกการเปลี่ยนแปลงกลับไปยังไฟล์

File System API และ FileWriter API มีวิธีการอ่านและเขียนไฟล์ไปยังระบบไฟล์ที่ทำแซนด์บ็อกซ์ แม้ว่าจะเป็นแบบอะซิงโครนัส แต่เราไม่แนะนำให้ใช้เนื่องจากใช้ได้เฉพาะในเบราว์เซอร์ที่ใช้ Chromium

ฉันจะจัดเก็บข้อมูลได้มากเท่าใด

สรุปสั้นๆ คือเยอะมาก อย่างน้อยก็หลายร้อยเมกะไบต์ และอาจถึงหลายร้อยกิกะไบต์หรือมากกว่านั้น การใช้งานเบราว์เซอร์จะแตกต่างกันไป แต่ปริมาณพื้นที่เก็บข้อมูลที่ใช้ได้มักจะขึ้นอยู่กับปริมาณพื้นที่เก็บข้อมูลที่ใช้ได้ในอุปกรณ์

  • Chrome อนุญาตให้เบราว์เซอร์ใช้พื้นที่ในดิสก์ได้สูงสุด 80% ของพื้นที่ทั้งหมด ต้นทางสามารถใช้พื้นที่ในดิสก์ได้สูงสุด 60% ของพื้นที่ทั้งหมด คุณสามารถใช้ StorageManager API เพื่อกำหนดโควต้าสูงสุดที่ใช้ได้ เบราว์เซอร์อื่นๆ ที่ใช้ Chromium อาจแตกต่างออกไป
    • ในโหมดไม่ระบุตัวตน Chrome จะลดปริมาณพื้นที่เก็บข้อมูลที่ต้นทางใช้ได้เหลือประมาณ 5% ของพื้นที่ในดิสก์ทั้งหมด
    • หากผู้ใช้เปิดใช้ "ล้างคุกกี้และข้อมูลเว็บไซต์เมื่อปิดหน้าต่างทั้งหมด" ใน Chrome โควต้าพื้นที่เก็บข้อมูลจะลดลงอย่างมากเหลือสูงสุดประมาณ 300 MB
  • Firefox อนุญาตให้เบราว์เซอร์ใช้พื้นที่ในดิสก์ได้สูงสุด 50% ของพื้นที่ว่าง กลุ่ม eTLD+1 (เช่น example.com, www.example.com และ foo.bar.example.com) ใช้ได้สูงสุด 2 GB คุณสามารถใช้ StorageManager API เพื่อดูว่ายังมีพื้นที่ว่างเหลืออยู่เท่าใด
  • Safari (ทั้งเดสก์ท็อปและอุปกรณ์เคลื่อนที่) ดูเหมือนจะอนุญาตให้ใช้พื้นที่ประมาณ 1 GB เมื่อถึงขีดจำกัด Safari จะแจ้งให้ผู้ใช้ทราบ โดยเพิ่มขีดจำกัดครั้งละ 200 MB เราไม่พบเอกสารประกอบอย่างเป็นทางการเกี่ยวกับเรื่องนี้
    • หากเพิ่ม PWA ลงในหน้าจอหลักบน Safari บนอุปกรณ์เคลื่อนที่ ระบบจะสร้างคอนเทนเนอร์พื้นที่เก็บข้อมูลใหม่ และไม่มีการแชร์ข้อมูลใดๆ ระหว่าง PWA กับ Safari บนอุปกรณ์เคลื่อนที่ เมื่อใช้พื้นที่เก็บข้อมูลจนถึงโควต้าสำหรับ PWA ที่ติดตั้งแล้ว ดูเหมือนว่าจะไม่มีวิธีขอพื้นที่เก็บข้อมูลเพิ่มเติม

ในอดีต หากเว็บไซต์มีข้อมูลที่จัดเก็บไว้เกินเกณฑ์ที่กำหนด เบราว์เซอร์จะแจ้งให้ผู้ใช้ให้สิทธิ์ใช้ข้อมูลเพิ่มเติม เช่น หากต้นทางใช้พื้นที่มากกว่า 50 MB เบราว์เซอร์จะแจ้งให้ผู้ใช้อนุญาตให้จัดเก็บข้อมูลได้สูงสุด 100 MB จากนั้นจะถามอีกครั้งเมื่อมีการจัดเก็บข้อมูลเพิ่มขึ้นทีละ 50 MB

ปัจจุบันเบราว์เซอร์ที่ทันสมัยส่วนใหญ่จะไม่แจ้งผู้ใช้ และจะอนุญาตให้เว็บไซต์ใช้พื้นที่เก็บข้อมูลได้สูงสุดตามโควต้าที่จัดสรรไว้ ข้อยกเว้นดูเหมือนจะเป็น Safari ซึ่งจะแสดงข้อความแจ้งเมื่อใช้โควต้าพื้นที่เก็บข้อมูลเกิน โดยขอสิทธิ์เพื่อเพิ่มโควต้าที่จัดสรร หากต้นทางพยายามใช้เกินโควต้าที่จัดสรรไว้ ความพยายามเขียนข้อมูลเพิ่มเติมจะล้มเหลว

ฉันจะตรวจสอบได้อย่างไรว่ามีพื้นที่เก็บข้อมูลเหลืออยู่เท่าใด

ในเบราว์เซอร์จำนวนมาก คุณสามารถใช้ StorageManager API เพื่อระบุปริมาณพื้นที่เก็บข้อมูลที่พร้อมใช้งานสำหรับต้นทาง และปริมาณพื้นที่เก็บข้อมูลที่ใช้ไป โดยจะรายงานจำนวนไบต์ทั้งหมดที่ IndexedDB และ Cache API ใช้ และช่วยให้คำนวณพื้นที่เก็บข้อมูลที่เหลืออยู่โดยประมาณได้

if (navigator.storage && navigator.storage.estimate) {
  const quota = await navigator.storage.estimate();
  // quota.usage -> Number of bytes used.
  // quota.quota -> Maximum number of bytes available.
  const percentageUsed = (quota.usage / quota.quota) * 100;
  console.log(`You've used ${percentageUsed}% of the available storage.`);
  const remaining = quota.quota - quota.usage;
  console.log(`You can write up to ${remaining} more bytes.`);
}

คุณต้องตรวจจับข้อผิดพลาดที่เกิดจากโควต้าเกิน (ดูด้านล่าง) ในบางกรณี โควต้าที่ใช้ได้อาจเกินจำนวนพื้นที่เก็บข้อมูลที่มีอยู่จริง

ตรวจสอบ

ในระหว่างการพัฒนา คุณสามารถใช้เครื่องมือสำหรับนักพัฒนาเว็บของเบราว์เซอร์เพื่อตรวจสอบพื้นที่เก็บข้อมูลประเภทต่างๆ และล้างข้อมูลที่จัดเก็บไว้ทั้งหมด

มีการเพิ่มฟีเจอร์ใหม่ใน Chrome 88 ที่ช่วยให้คุณลบล้างโควต้าพื้นที่เก็บข้อมูลของเว็บไซต์ในแผงพื้นที่เก็บข้อมูลได้ ฟีเจอร์นี้ช่วยให้คุณจำลองอุปกรณ์ต่างๆ และทดสอบลักษณะการทำงานของแอปในสถานการณ์ที่มีพื้นที่ดิสก์เหลือน้อยได้ ไปที่แอปพลิเคชัน แล้วไปที่พื้นที่เก็บข้อมูล เปิดใช้ช่องทำเครื่องหมายจำลองโควต้าพื้นที่เก็บข้อมูลที่กำหนดเอง และป้อนตัวเลขที่ถูกต้องเพื่อจำลองโควต้าพื้นที่เก็บข้อมูล

วิธีจัดการเมื่อใช้ข้อมูลเกินโควต้า

คุณควรทำอย่างไรเมื่อใช้พื้นที่เก็บข้อมูลเกินโควต้า ที่สำคัญที่สุดคือคุณควรดักจับและจัดการข้อผิดพลาดในการเขียนเสมอ ไม่ว่าจะเป็น QuotaExceededError หรืออื่นๆ จากนั้นให้ตัดสินใจว่าจะจัดการอย่างไร ทั้งนี้ขึ้นอยู่กับการออกแบบแอปของคุณ เช่น ลบเนื้อหาที่ไม่ได้เข้าถึงเป็นเวลานาน นำข้อมูลออกตามขนาด หรือให้ผู้ใช้เลือกสิ่งที่ต้องการลบ

ทั้ง IndexedDB และ Cache API จะแสดง DOMError ชื่อ QuotaExceededError เมื่อคุณใช้พื้นที่เก็บข้อมูลเกินโควต้าที่มีอยู่

IndexedDB

หากต้นทางใช้โควต้าเกินขีดจำกัด การพยายามเขียนลงใน IndexedDB จะไม่สำเร็จ ระบบจะเรียกใช้แฮนเดิล onabort() ของธุรกรรม โดยส่งเหตุการณ์ เหตุการณ์จะมี DOMException ในพร็อพเพอร์ตี้ข้อผิดพลาด การตรวจสอบข้อผิดพลาด name จะแสดงผลเป็น QuotaExceededError

const transaction = idb.transaction(['entries'], 'readwrite');
transaction.onabort = function(event) {
  const error = event.target.error; // DOMException
  if (error.name == 'QuotaExceededError') {
    // Fallback code goes here
  }
};

Cache API

หากต้นทางใช้โควต้าเกินขีดจำกัด ความพยายามในการเขียนไปยัง Cache API จะถูกปฏิเสธด้วย QuotaExceededError DOMException

try {
  const cache = await caches.open('my-cache');
  await cache.add(new Request('/sample1.jpg'));
} catch (err) {
  if (error.name === 'QuotaExceededError') {
    // Fallback code goes here
  }
}

การขับไล่ทำงานอย่างไร

พื้นที่เก็บข้อมูลบนเว็บแบ่งออกเป็น 2 กลุ่ม ได้แก่ "Best Effort" และ "Persistent" Best effort หมายความว่าเบราว์เซอร์สามารถล้างพื้นที่เก็บข้อมูลได้โดยไม่รบกวนผู้ใช้ แต่จะมีความทนทานน้อยกว่าสำหรับข้อมูลระยะยาวหรือข้อมูลสำคัญ ระบบจะไม่ล้างพื้นที่เก็บข้อมูลถาวรโดยอัตโนมัติเมื่อพื้นที่เก็บข้อมูลเหลือน้อย ผู้ใช้ต้องล้างพื้นที่เก็บข้อมูลนี้ด้วยตนเอง (ผ่านการตั้งค่าเบราว์เซอร์)

โดยค่าเริ่มต้น ข้อมูลของเว็บไซต์ (รวมถึง IndexedDB, Cache API ฯลฯ) จะอยู่ในหมวดหมู่ "พยายามอย่างเต็มที่" ซึ่งหมายความว่าหากเว็บไซต์ไม่ได้ขอพื้นที่เก็บข้อมูลถาวร เบราว์เซอร์อาจลบข้อมูลเว็บไซต์ตามที่เห็นสมควร เช่น เมื่อพื้นที่เก็บข้อมูลของอุปกรณ์เหลือน้อย

นโยบายการขับออกสำหรับการพยายามอย่างเต็มที่มีดังนี้

  • เบราว์เซอร์ที่ใช้ Chromium จะเริ่มนำข้อมูลออกเมื่อเบราว์เซอร์มีพื้นที่ไม่เพียงพอ โดยจะล้างข้อมูลเว็บไซต์ทั้งหมดจากต้นทางที่ใช้ล่าสุดก่อน จากนั้นจึงล้างข้อมูลถัดไปจนกว่าเบราว์เซอร์จะไม่เกินขีดจำกัดอีกต่อไป
  • Firefox จะเริ่มลบข้อมูลเมื่อพื้นที่ในดิสก์ที่ใช้ได้เต็ม โดยจะล้างข้อมูลเว็บไซต์ทั้งหมดจากต้นทางที่ใช้ล่าสุดก่อน จากนั้นจึงล้างข้อมูลเว็บไซต์ถัดไปจนกว่าเบราว์เซอร์จะไม่เกินขีดจำกัดอีกต่อไป
  • ก่อนหน้านี้ Safari ไม่ได้ลบข้อมูล แต่เมื่อเร็วๆ นี้ได้ใช้ขีดจำกัดใหม่ 7 วันกับพื้นที่เก็บข้อมูลที่เขียนได้ทั้งหมด (ดูด้านล่าง)

ตั้งแต่ iOS และ iPadOS 13.4 และ Safari 13.1 บน macOS เป็นต้นมา มีการจำกัดพื้นที่เก็บข้อมูลที่สคริปต์เขียนได้ทั้งหมดไว้ที่ 7 วัน ซึ่งรวมถึง IndexedDB, การลงทะเบียน Service Worker และ Cache API ซึ่งหมายความว่า Safari จะนำเนื้อหาทั้งหมดออกจากแคชหลังจากใช้ Safari ไปแล้ว 7 วันหากผู้ใช้ไม่ได้โต้ตอบกับเว็บไซต์ นโยบายการลบนี้ไม่มีผลกับ PWA ที่ติดตั้งไว้ซึ่งเพิ่มลงในหน้าจอหลักแล้ว ดูรายละเอียดทั้งหมดได้ที่การบล็อกคุกกี้ของบุคคลที่สามอย่างเต็มรูปแบบและอื่นๆ ในบล็อก WebKit

ที่เก็บข้อมูลของพื้นที่เก็บข้อมูล

แนวคิดหลักของ Storage Buckets API คือการให้สิทธิ์เว็บไซต์ในการสร้างที่เก็บข้อมูลหลายที่เก็บ ซึ่งเบราว์เซอร์อาจเลือกลบที่เก็บข้อมูลแต่ละที่เก็บแยกจากที่เก็บข้อมูลอื่นๆ ซึ่งช่วยให้นักพัฒนาแอปสามารถระบุลำดับความสำคัญของการลบเพื่อไม่ให้ข้อมูลที่มีค่าที่สุดถูกลบ

โบนัส: เหตุใดจึงควรใช้ Wrapper สำหรับ IndexedDB

IndexedDB เป็น API ระดับต่ำที่ต้องมีการตั้งค่าที่สำคัญก่อนใช้งาน ซึ่งอาจเป็นเรื่องที่ยุ่งยากเป็นพิเศษสำหรับการจัดเก็บข้อมูลที่มีความซับซ้อนต่ำ API นี้อิงตามเหตุการณ์ ซึ่งต่างจาก API ที่อิงตามสัญญา (Promise) สมัยใหม่ส่วนใหญ่ Wrapper ของ Promise เช่น idb สำหรับ IndexedDB จะซ่อนฟีเจอร์ที่มีประสิทธิภาพบางอย่าง แต่ที่สำคัญกว่านั้นคือซ่อนกลไกที่ซับซ้อน (เช่น ธุรกรรม การกำหนดเวอร์ชันสคีมา) ที่มาพร้อมกับไลบรารี IndexedDB

โบนัส: SQLite Wasm

หลังจากเลิกใช้งานและนำ SQL ในเว็บออกจาก Chrome แล้ว Google ได้ร่วมมือกับผู้ดูแลฐานข้อมูล SQLite ยอดนิยมเพื่อเสนอทางเลือกแทน SQL ในเว็บที่อิงตาม SQLite อ่านรายละเอียดเกี่ยวกับวิธีใช้ได้ที่ SQLite Wasm ในเบราว์เซอร์ที่สนับสนุนโดยระบบไฟล์ส่วนตัวของต้นทาง

บทสรุป

ยุคที่พื้นที่เก็บข้อมูลมีจำกัดและต้องแจ้งให้ผู้ใช้จัดเก็บข้อมูลมากขึ้นเรื่อยๆ ได้ผ่านพ้นไปแล้ว เว็บไซต์สามารถจัดเก็บทรัพยากรและข้อมูลทั้งหมดที่จำเป็นต่อการทำงานได้อย่างมีประสิทธิภาพ คุณสามารถใช้ StorageManager API เพื่อดูปริมาณพื้นที่เก็บข้อมูลที่พร้อมใช้งานและปริมาณพื้นที่เก็บข้อมูลที่ใช้ไปแล้ว และด้วยพื้นที่เก็บข้อมูลถาวร คุณสามารถป้องกันไม่ให้ระบบนำข้อมูลออกได้ เว้นแต่ผู้ใช้จะนำออกเอง

แหล่งข้อมูลเพิ่มเติม

ขอขอบคุณ

ขอขอบคุณ Jarryd Goodman, Phil Walton, Eiji Kitamura, Daniel Murphy, Darwin Huang, Josh Bell, Marijn Kruisselbrink และ Victor Costan เป็นพิเศษที่ช่วยตรวจสอบคู่มือนี้ ขอขอบคุณ Eiji Kitamura, Addy Osmani และ Marc Cohen ผู้เขียนบทความต้นฉบับซึ่งเป็นที่มาของบทความนี้ Eiji ได้เขียนเครื่องมือที่มีประโยชน์ชื่อ Browser Storage Abuser ซึ่งมีประโยชน์ในการตรวจสอบลักษณะการทำงานปัจจุบัน ซึ่งจะช่วยให้คุณจัดเก็บข้อมูลได้มากที่สุดและดูขีดจำกัดของพื้นที่เก็บข้อมูลในเบราว์เซอร์ได้ ขอขอบคุณ François Beaufort ที่เจาะลึกข้อมูลเกี่ยวกับ Safari เพื่อค้นหาขีดจำกัดพื้นที่เก็บข้อมูล และ Thomas Steiner ที่เพิ่มข้อมูลเกี่ยวกับระบบไฟล์ส่วนตัวต้นทาง, บัケットพื้นที่เก็บข้อมูล, SQLite Wasm และการอัปเดตเนื้อหาโดยรวมในปี 2024