Хранилище для Интернета

Существует множество различных вариантов хранения данных в браузере. Какой из них лучше всего соответствует вашим потребностям?

Интернет-соединения могут быть нестабильными или вообще отсутствовать в пути, поэтому автономная поддержка и надежная производительность являются общими характеристиками прогрессивных веб-приложений . Даже в идеальных беспроводных средах разумное использование кэширования и других методов хранения может существенно улучшить взаимодействие с пользователем. Существует несколько способов кэширования статических ресурсов приложения (HTML, JavaScript, CSS, изображений и т. д.) и данных (пользовательских данных, новостных статей и т. д.). Но какое решение является лучшим? Сколько вы можете хранить? Как предотвратить его выселение?

Что мне следует использовать?

Вот общие рекомендации по хранению ресурсов:

IndexedDB и API хранилища кэша поддерживаются всеми современными браузерами. Они оба асинхронны и не блокируют основной поток. Они доступны из объекта window , веб-воркеров и сервис-воркеров, что позволяет легко использовать их в любом месте вашего кода.

А как насчет других механизмов хранения?

В браузере доступно несколько других механизмов хранения, но они имеют ограниченное применение и могут вызвать серьезные проблемы с производительностью.

SessionStorage зависит от вкладки и ограничен временем существования вкладки. Это может быть полезно для хранения небольших объемов информации, специфичной для сеанса, например ключа IndexedDB. Его следует использовать с осторожностью, поскольку он синхронен и блокирует основной поток. Его размер ограничен примерно 5 МБ и может содержать только строки. Поскольку он зависит от вкладки, он недоступен для веб-работников или сервисных работников.

Следует избегать использования LocalStorage, поскольку он синхронен и блокирует основной поток. Его размер ограничен примерно 5 МБ и может содержать только строки. LocalStorage недоступен для веб-работников или сервисных работников.

Файлы cookie имеют свое назначение, но их не следует использовать для хранения. Файлы cookie отправляются с каждым HTTP-запросом, поэтому хранение большего объема данных, чем небольшой объем данных, значительно увеличит размер каждого веб-запроса. Они синхронны и недоступны веб-воркерам. Подобно LocalStorage и SessionStorage, файлы cookie ограничиваются только строками.

API файловой системы и API FileWriter предоставляют методы для чтения и записи файлов в изолированную файловую систему. Хотя он является асинхронным, его не рекомендуется использовать, поскольку он доступен только в браузерах на базе Chromium .

API доступа к файловой системе был разработан, чтобы пользователи могли легко читать и редактировать файлы в своей локальной файловой системе. Пользователь должен предоставить разрешение, прежде чем страница сможет читать или записывать любой локальный файл, и разрешения не сохраняются между сеансами.

WebSQL не следует использовать, а существующее использование следует перенести на IndexedDB. Поддержка удалена практически из всех основных браузеров. W3C прекратил поддержку спецификации Web SQL в 2010 году, не планируя дальнейших обновлений.

Кэш приложений не следует использовать, а существующее использование следует перенести на сервисных работников и API кэша. Он устарел , и в будущем его поддержка будет прекращена из браузеров.

Сколько я могу хранить?

Короче говоря, очень много , как минимум пара сотен мегабайт, а потенциально и сотни гигабайт и более. Реализации браузеров различаются, но объем доступного хранилища обычно зависит от объема хранилища, доступного на устройстве.

  • Chrome позволяет браузеру использовать до 80% общего дискового пространства. Источник может использовать до 60% общего дискового пространства. Вы можете использовать API StorageManager, чтобы определить максимальную доступную квоту. Другие браузеры на базе Chromium могут отличаться.
    • В режиме инкогнито Chrome уменьшает объем памяти, которую может использовать источник, примерно до 5 % от общего дискового пространства.
    • Если пользователь включил в Chrome «Очистить файлы cookie и данные сайта при закрытии всех окон», квота хранилища значительно уменьшается до максимального значения, примерно 300 МБ.
    • Подробную информацию о реализации Chrome см. в PR № 3896 .
  • Internet Explorer 10 и более поздние версии могут хранить до 250 МБ и сообщать пользователю, когда используется более 10 МБ.
  • Firefox позволяет браузеру использовать до 50% свободного дискового пространства. Группа eTLD+1 (например, example.com , www.example.com и foo.bar.example.com ) может использовать до 2 ГБ . Вы можете использовать API StorageManager, чтобы определить, сколько места еще доступно.
  • Safari (как для настольных компьютеров, так и для мобильных устройств) позволяет использовать около 1 ГБ. Когда лимит будет достигнут, Safari предложит пользователю увеличить лимит с шагом 200 МБ. Мне не удалось найти никакой официальной документации по этому поводу.
    • Если PWA добавляется на главный экран мобильного Safari, создается впечатление, что он создает новый контейнер хранения, и между PWA и мобильным Safari ничего не используется совместно. После достижения квоты для установленного PWA, похоже, нет никакого способа запросить дополнительное хранилище.

Раньше, если сайт превышал определенный порог хранимых данных, браузер предлагал пользователю предоставить разрешение на использование большего количества данных. Например, если источник использовал более 50 МБ, браузер предложит пользователю разрешить сохранение до 100 МБ, а затем повторит запрос с шагом 50 МБ.

Сегодня большинство современных браузеров не запрашивают пользователя и позволяют сайту использовать выделенную ему квоту. Исключением является Safari, который при превышении квоты хранилища выдает сообщение и запрашивает разрешение на увеличение выделенной квоты. Если источник попытается использовать больше выделенной ему квоты, дальнейшие попытки записи данных потерпят неудачу.

Как я могу проверить, сколько места доступно?

Во многих браузерах вы можете использовать API StorageManager , чтобы определить объем хранилища, доступный источнику, и объем хранилища, который он использует. Он сообщает общее количество байтов, используемых 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.`);
}

StorageManager пока реализован не во всех браузерах, поэтому перед его использованием необходимо обнаружить его. Даже если он доступен, вы все равно должны обнаруживать ошибки превышения квоты (см. ниже). В некоторых случаях доступная квота может превысить фактический объем доступного хранилища.

Осмотреть

Во время разработки вы можете использовать DevTools вашего браузера для проверки различных типов хранилищ и легкого удаления всех сохраненных данных.

В Chrome 88 была добавлена ​​новая функция, которая позволяет вам переопределить квоту хранилища сайта на панели «Хранилище». Эта функция дает вам возможность моделировать различные устройства и тестировать поведение ваших приложений в сценариях с нехваткой дискового пространства. Перейдите в раздел «Приложение» , затем «Хранилище» , установите флажок «Имитировать пользовательскую квоту хранилища» и введите любое допустимое число для имитации квоты хранилища.

Панель «Хранилище DevTools».

Работая над этой статьей, я написал простой инструмент , позволяющий быстро использовать как можно больше места. Это быстрый и простой способ поэкспериментировать с различными механизмами хранения и посмотреть, что произойдет, когда вы используете всю свою квоту.

Как справиться с превышением квоты?

Что делать, если превышена квота? Самое главное, вы всегда должны ловить и обрабатывать ошибки записи, будь то QuotaExceededError или что-то еще. Затем, в зависимости от дизайна вашего приложения, решите, как с ним справиться. Например, удалите контент, к которому не было доступа в течение длительного времени, удалите данные в зависимости от размера или предоставьте пользователям возможность выбирать, что они хотят удалить.

И IndexedDB, и Cache API выдают DOMError с именем QuotaExceededError , когда вы превысили доступную квоту.

ИндекседБД

Если источник превысил свою квоту, попытки записи в IndexedDB завершится неудачей. Будет вызван обработчик onabort() транзакции, передав событие. Событие будет содержать DOMException в свойстве error. Проверка 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
  }
};

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
  }
}

Как происходит выселение?

Веб-хранилище разделено на две категории: «Наилучшее из возможных» и «Постоянное». «Наилучшее усилие» означает, что хранилище может быть очищено браузером, не отвлекая пользователя, но оно менее надежно для долговременных или критически важных данных. Постоянное хранилище не очищается автоматически, когда объем свободного места заканчивается. Пользователю необходимо вручную очистить это хранилище (через настройки браузера).

По умолчанию данные сайта (включая IndexedDB, Cache API и т. д.) попадают в категорию максимальных усилий, что означает, что, если сайт не запросил постоянное хранилище , браузер может удалить данные сайта по своему усмотрению, например, когда объем памяти устройства низкий. .

Политика выселения в духе лучших усилий заключается в следующем:

  • Браузеры на основе Chromium начнут удалять данные, когда в браузере заканчивается место, сначала удаляя все данные сайта из наименее использованного источника, затем из следующего, пока браузер не перестанет превышать лимит.
  • Internet Explorer 10+ не будет удалять данные, но не позволит источнику больше записывать.
  • Firefox начнет удалять данные, когда доступное дисковое пространство будет заполнено, сначала удаляя все данные сайта из наименее использованного источника, затем из следующего, пока браузер не перестанет превышать лимит.
  • Раньше Safari не удалял данные, но недавно ввел новое семидневное ограничение на все записываемые хранилища (см. ниже).

Начиная с iOS и iPadOS 13.4, а также Safari 13.1 на macOS, существует семидневное ограничение на все хранилище, доступное для записи скриптов, включая IndexedDB, регистрацию сервисных работников и Cache API. Это означает, что Safari удалит весь контент из кеша через семь дней использования Safari, если пользователь не взаимодействует с сайтом. Эта политика вытеснения не применяется к установленным PWA , добавленным на главный экран. Подробную информацию см. в разделе «Полная блокировка сторонних файлов cookie и многое другое» в блоге WebKit.

Бонус: зачем использовать оболочку для IndexedDB

IndexedDB — это низкоуровневый API, который требует значительной настройки перед использованием, что может быть особенно болезненно при хранении простых данных. В отличие от большинства современных API-интерфейсов, основанных на обещаниях, он основан на событиях. Обертки обещаний, такие как idb для IndexedDB, скрывают некоторые мощные функции, но, что более важно, скрывают сложный механизм (например, транзакции, управление версиями схемы), который поставляется с библиотекой IndexedDB.

Заключение

Прошли времена ограниченного объема памяти и необходимости хранить все больше и больше данных. Сайты могут эффективно хранить все ресурсы и данные, необходимые для работы. Используя API StorageManager, вы можете определить, какой объем вам доступен и какой объем вы уже использовали. А с постоянным хранилищем , если пользователь не удалит его, вы можете защитить его от выселения.

Дополнительные ресурсы

Спасибо

Особая благодарность Джарриду Гудману, Филу Уолтону, Эйдзи Китамуре, Дэниелу Мерфи, Дарвину Хуангу, Джошу Беллу, Марин Круйссельбринк и Виктору Костану за рецензирование этой статьи. Спасибо Эйдзи Китамуре, Адди Османи и Марку Коэну, написавшим оригинальные статьи, на которых основана эта книга. Эйдзи написал полезный инструмент под названием Browser Storage Abuser , который был полезен при проверке текущего поведения. Это позволяет вам хранить как можно больше данных и видеть ограничения хранилища в вашем браузере. Спасибо Франсуа Бофорту, который покопался в Safari, чтобы выяснить ограничения на объем хранилища.

Изображение героя создано Гийомом Больдуком на Unsplash .