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

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

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

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

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

  • หากต้องการจัดเก็บทรัพยากรเครือข่ายที่จำเป็นต่อการโหลดแอป ให้ใช้ Cache Storage API (ซึ่งเป็นส่วนหนึ่งของ Service Worker)
  • หากต้องการจัดเก็บเนื้อหาที่อิงตามไฟล์ ให้ใช้ Origin Private File System (OPFS)
  • หากต้องการจัดเก็บข้อมูลอื่นๆ ให้ใช้ IndexedDB (พร้อม Wrapper แบบ Promise)

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

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

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

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 มีเมธอดสำหรับการ อ่านและเขียนไฟล์ลงในระบบไฟล์แบบแซนด์บ็อกซ์ แม้ว่า API เหล่านี้จะทำงานแบบไม่พร้อมกัน แต่เราไม่แนะนำให้ใช้เนื่องจาก พร้อมใช้งานในเบราว์เซอร์แบบ Chromium เท่านั้น

ฉันจัดเก็บข้อมูลได้มากน้อยเพียงใด

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

  • 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 เพื่อกำหนดปริมาณพื้นที่เก็บข้อมูล ที่ต้นทางใช้ได้และปริมาณพื้นที่เก็บข้อมูลที่ต้นทางใช้อยู่ 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 จะถูกปฏิเสธด้วย DOMException ของ QuotaExceededError

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 กลุ่ม ได้แก่ "พยายามอย่างเต็มที่" และ "ถาวร" "พยายามอย่างเต็มที่" หมายความว่าเบราว์เซอร์สามารถล้างพื้นที่เก็บข้อมูลได้โดยไม่ขัดขวางผู้ใช้ แต่ข้อมูลที่จัดเก็บไว้จะมีความคงทนน้อยกว่าสำหรับการจัดเก็บข้อมูลระยะยาวหรือข้อมูลสำคัญ ส่วนพื้นที่เก็บข้อมูล "ถาวร" ระบบจะไม่ล้างข้อมูลโดยอัตโนมัติเมื่อพื้นที่เก็บข้อมูลเหลือน้อย ผู้ใช้ต้องล้างพื้นที่เก็บข้อมูลนี้ด้วยตนเอง (ผ่านการตั้งค่าเบราว์เซอร์)

โดยค่าเริ่มต้น ข้อมูลของเว็บไซต์ (รวมถึง 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

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

บทสรุป

ยุคที่พื้นที่เก็บข้อมูลมีจำกัดและต้องแจ้งให้ผู้ใช้จัดเก็บข้อมูลมากขึ้นเรื่อยๆ ได้ผ่านพ้นไปแล้ว เว็บไซต์สามารถจัดเก็บทรัพยากรและข้อมูลทั้งหมดที่จำเป็นต่อการทำงานได้อย่างมีประสิทธิภาพ คุณสามารถใช้ 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 ที่เพิ่มข้อมูลเกี่ยวกับ Origin Private File System, ที่เก็บข้อมูลของพื้นที่เก็บข้อมูล, SQLite Wasm และการอัปเดตเนื้อหาโดยรวมในปี 2024