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

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

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

ฉันควรใช้อะไร

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

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

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

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

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

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

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

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

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

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

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

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

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

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

พิเศษ: SQLite Wasm

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

บทสรุป

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

รูปภาพหลักโดย Guillaume Bolduc จาก Unsplash