Не так давно файлы cookie были единственным жизнеспособным вариантом для постоянного хранения данных в браузере. Говоря о файлах cookie, мы довольно долго говорим об ограниченной строке символов, представляющих возможности хранения.

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

Современные веб-приложения или PWA стремятся конкурировать как с нативными приложениями, так и с веб-сайтами; для этого веб-приложение должно быть надежным, производительным и сохранять даже большие объемы данных, таких как текстовые блоки или изображения. Поэтому новый доступный API файловой системы, принятый Apple WebKit в этом году, изменит правила игры.

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

Поэтому новый доступный API файловой системы, принятый Apple WebKit в этом году, изменит правила игры.

Файлы cookie — надежный дедушка хранения

Файлы cookie — это пары ключ-значение, хранящиеся в строке размером не более 4 КБ. Файлы cookie в основном используются для трех приложений:

  • Хранилище токенов для аутентификации или идентификации сеанса
  • Отслеживающие файлы cookie для целей мониторинга или маркетинга
  • Простые состояния приложений примитивным способом

Файлы cookie по-прежнему жизнеспособны из-за их безопасного характера. Конечно, много хранить нельзя, но можно спокойно делать это в среде браузера и убрать доступ из области видимости JavaScript. Это улучшение безопасности может быть достигнуто с помощью флага httpOnly, который удалит доступ из файла cookie и передаст его только в заголовке запроса на сервер через защищенное соединение HTTPS.

Еще одной функцией безопасности является директива SameSite, которая должна помочь предотвратить атаки с подделкой межсайтовых запросов (CSRF), ограничивая отправку файла cookie только на исходный сайт.

Кэширование с помощью Service Worker

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

С введением сервис-воркера появилась возможность реализовывать стратегии кэширования во время выполнения для определенных маршрутов в вашем приложении. Можно кэшировать и сохранять весь сетевой трафик вашего веб-приложения и повторно использовать его с помощью подхода Stale-While-Revalidate (SWR).

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

В Google Workbox доступные стратегии

  • Stale-While-Revalidate — прежде всего надежность
  • Network-First — приоритет свежести данных
  • Cache-First — локальная доступность в приоритете, откат к сети
  • Только для сети — без кэширования
  • Cache-Only — опция предварительного кэширования, игнорировать сеть

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

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

Индексированная БД — асинхронное хранилище

Для хранения текстовых данных по запросу в браузере рекомендуется использовать indexedDB, если нет конфиденциальных данных. С IndexedDB браузер предоставляет базы данных на основе пар ключ-значение с базовым интерфейсом setItem, getItem, removeItem. Однако важно отметить, что эти действия асинхронны и должны использоваться в JavaScript. В деталях API IndexedDB более сложен, но есть надежные обертки промисов, такие как localForage или IDB.

В отличие от синхронного двоюродного брата LocalStorage, IndexedDB предоставляет несколько баз данных с возможными отдельными версиями базы данных. Таким образом, можно структурировать данные по принципу «сегмента», что в любом случае рекомендуется.

Квоты-Ограничения хранилища

С Indexed DB накладываются ограничения из-за локального хранилища браузера. Это ограничение может отличаться от браузера к браузеру и даже от ОС. Точные ограничения квот — это отдельная тема, которая постоянно меняется. Однако можно с уверенностью сказать, что за последние годы он стал лучше, и он сильно отличается для каждой ОС и браузера. Даже состояние установки (или «Добавить на главный экран») влияет на то, что может хранить приложение. Я настоятельно рекомендую вам быть в курсе последних событий, если квота имеет решающее значение для вашей компании или клиента.

На момент написания статьи Android Chrome позволял хранить около 60–80% свободного места на диске (в приватном режиме этот показатель значительно ниже). В то же время Apple Safari увеличил ограничение с 500 МБ до 1 ГБ данных, и пользователям будет предложено увеличить лимит на 200 МБ с разрешения пользователя.

Интересно, что установленная версия WebApp или PWA в Apple Safari получает отдельное хранилище и квоты, даже если это один и тот же домен. Состояние установки также влияет на сохранение данных. На Android установленная версия использует то же хранилище, что и версия браузера.

LocalStorage — выглядит лучше, чем файлы cookie, но в наши дни его следует избегать.

Функция синхронного LocalStorage выглядит великолепно и на первый взгляд проста в использовании. Но у него есть свои недостатки. Это синхронно, блокирует основной поток и не рекомендуется. Этот тип хранилища может работать для одной строки, но хранение более значительных объемов данных является огромной проблемой и бесполезно. Кроме того, квота относительно мала — 5 МБ.

Безопасность — вторая причина, но этот момент связан с IndexedDB и хранилищем сеансов. Эти хранилища всегда доступны через Javascript и не могут быть защищены, например, с помощью флага httpsOnly. Поэтому вам никогда не следует хранить конфиденциальные данные, такие как JWT, в этом хранилище с учетом этого.

Хранилище сеансов — одноуровневое хранилище LocalStorage с деменцией

Этот тип хранилища работает как LocalStorage, но его время жизни привязано к открытой вкладке в браузере. Сеанс может варьироваться от браузера к браузеру; Определение сеанса может быть общебраузерным, со всеми открытыми вкладками для одного и того же домена или одной вкладкой. Кроме того, это хранилище ограничено 5 МБ данных и поэтому не предназначено для файлов.

Файловая система — надежное файловое хранилище, теперь также доступное в Safari.

Я прочитал запись в блоге WebKit API доступа к файловой системе с частной файловой системой Origin в начале этого года. Этот пост ошеломил меня, потому что Apple не слишком поддерживала идею веб-приложений, но после нескольких лет ожидания она, наконец, снова начала двигаться вперед.

Что файловая система делает лучше, чем IndexedDB

Хранение больших двоичных объектов размером до нескольких мегабайт часто было возможно с помощью IndexedDB, но у него есть свои недостатки. У IndexedDB, кажется, есть проблемы со многими транзакциями за короткий промежуток времени, в то время как полезная нагрузка для чтения или записи высока. Мы отслеживали многие проблемы с квотами с Sentry.io на устройствах Apple в одном конкретном приложении, которые мы могли воспроизвести с помощью таких инструментов, как злоупотребление локальным хранилищем (https://demo.agektmr.com/storage/).

Вместо того, чтобы предложить пользователю увеличить текущую квоту, база данных дала сбой; в некоторых случаях перезапуск восстанавливал сохраненные данные после перезапуска веб-просмотра; в других данные были полностью потеряны. Эти проблемы возникали преимущественно на iPhone 11 старшего поколения с iOS 15. Мы устранили проблему, уменьшив «нагрузку» на базы данных количеством запросов и полезной нагрузкой. Кроме того, мы заменили захват фотографий такими пакетами, как «ионный конденсатор», чтобы иметь больший контроль над операциями ввода-вывода.

Чтобы полностью избежать этой проблемы, мы начали внедрять API доступа к файловой системе в наши Progressive-Web-Apps. Это было возможно для нас, начиная с iOS 15.4 или macOS 12.3, где команда WebKit реализовала API удобным способом для приложений производственного уровня.

Хранилище файловой системы действительно постоянное.

Хотя очистка данных веб-сайта приведет к удалению других параметров хранения после его удаления, этого не произойдет с файловой системой. Таким образом, постоянные файлы труднее удалить случайно; неопытные пользователи смогут сохранить свои данные в безопасности даже при неправильном обращении с приложением. (Итак, теория! :) )

«Золотые данные» — это термин для бизнес-приложений с критически важными данными, такими как фотографии или данные JSON, которые можно было захватить или создать только в определенный период времени и в определенном месте с помощью приложения. Таким образом, данные не могут быть восстановлены и должны оставаться в безопасности на устройстве до тех пор, пока приложение не сможет загрузить данные на серверы. Раньше мы добивались этого с помощью IndexedDB, и у нас было много проблем, особенно с двумя основными оговорками, которые я уже упоминал. С файловой системой данные все еще существуют, даже если приложения необходимо переустановить, если пользователь не удалит их намеренно.

Синхронный и асинхронный API файловой системы

Доступ к файловой системе можно получить через дескрипторы файлов. Это можно сделать асинхронно в веб-просмотре или синхронно в веб-воркере. Последний подход должен быть более производительным, но по природе веб-воркеров более сложным в настройке.

Внутри рабочего процесса дескрипторы доступа необходимы для получения дескрипторов файлов, что было реализовано как уровень безопасности. К сожалению, на момент написания этой статьи реализация веб-воркера была доступна только в Safari. (Да, Apple реализовала это, а Google еще нет.)

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

Оба способа актуальны, и разработчик должен понимать подходы, прежде чем работать с ними в продакшене. Веб-воркеры также могут быть сложными при тестировании (Test-Drive-Development или Test-Last-Development). Если вы заинтересованы в этих вещах, вы должны тщательно подготовиться здесь.

В основных инструментах разработчика браузера в настоящее время отсутствуют инструменты для взаимодействия с файловой системой. В нашем случае мы сначала разработали базовый Filesystem-Explorer, основываясь на нашем разнообразном опыте отладки удаленных устройств. С помощью этого инструмента мы подтвердили, что API файловой системы работает стабильно.

Мы будем первыми последователями.

API доступа к файловой системе можно использовать, но он еще не полностью реализован со всеми аспектами и деталями безопасности. Я очень ценю текущее развитие; на мой взгляд, это огромная веха и переломный момент, особенно для PWA. Мы будем использовать этот API в качестве первопроходца в производстве на основных платформах.

Поскольку Progressive-Web-Apps являются прогрессивными, в настоящее время мы разрабатываем оболочку файловой системы, которая использует IndexedDB, если новый API не реализован. Этот подход кажется солидным и многообещающим, и я сообщу об этом в будущем.