При разработке современных веб-сайтов достаточно часто необходимо сохранять данные на стороне клиента. Для таких целей в браузере существует несколько разных способов, которые появились в разное время и отличаются друг от друга.
Cookie
Первый способ — это хранение данных в cookie. Этот способ — не просто хранилище данных в браузере. Данные, хранящиеся в куках, также передаются на сервер в виде HTTP-заголовка и могут быть им изменены. Cookie являются частью спецификации протокола HTTP, и их поддерживают все браузеры.
У хранения данных в Cookie есть много ограничений. Они передаются при каждом запросе к серверу, их размер ограничен 4096 байтами, а содержимое должно быть закодировано и быть безопасным, чтобы не сломать отправляемый запрос. Cookie не являются постоянным хранилищем, срок хранения данных по умолчанию ограничен длинной сессии, и для продления хранения кук используется дополнительный параметр.
Cookie имеют не самый удобный интерфейс чтения и записи, поэтому в работе многие разработчики чаще используют сторонние библиотеки, а не взаимодействуют с интерфейсом напрямую.
Как правило, этим способом пользуются для хранения авторизационных данных или когда доступ к записанным данным нужен на сервере. Ещё куки используются для отслеживания поведения пользователя на сайте, но браузеры активно с этим борются.
Web Storage
СкопированоWeb Storage – это интерфейс взаимодействия с хранилищем. Есть две реализации этого API: Local Storage и Session Storage. Оба способа имеют идентичный API и ограничения, а основным различием является время хранения данных.
Session Storage похож на краткосрочные Cookie, потому что данные в этом хранилище хранятся только во время жизни текущей сессии.
Local Storage, в теории, является бессрочным хранилищем данных. Хотя данные и должны храниться бессрочно, браузеры все равно вводят свои ограничения.
Так, например, при переполнении хранилища оно полностью очищается. А Safari очищает Local Storage если к нему не обращались в течение семи дней. То есть если пользователь не посещал ваш сайт больше 7 дней, то данные хранящиеся в нем будут удалены.
Максимальный объем хранимых данных — 5 Мб. При этом любой скрипт, загруженный на странице, может иметь доступ к Web Storage на этой странице. Поэтому не стоит хранить там приватную информацию или токены авторизации, так как таким скриптом может являться вредное браузерное расширение, которое ворует информацию пользователя.
Интерфейс взаимодействия с этим видом хранилища очень простой и достаточно удобный. Данные хранятся в виде ключ-значение, и функции названы интуитивно понятно.
// Запись в полеwindow.localStorage.setItem('name', 'value')window.sessionStorage.setItem('name', 'value')// Чтение из поляconst nameFromLocalStorage = window.localStorage.getItem('name')const nameFromSessionStorage = window.sessionStorage.getItem('name')// Удаление поляwindow.localStorage.removeItem('name')window.sessionStorage.removeItem('name')// Очистка хранилищаwindow.localStorage.clear()window.sessionStorage.clear()
// Запись в поле window.localStorage.setItem('name', 'value') window.sessionStorage.setItem('name', 'value') // Чтение из поля const nameFromLocalStorage = window.localStorage.getItem('name') const nameFromSessionStorage = window.sessionStorage.getItem('name') // Удаление поля window.localStorage.removeItem('name') window.sessionStorage.removeItem('name') // Очистка хранилища window.localStorage.clear() window.sessionStorage.clear()
Можно заметить, что данные записываются в виде строк, поэтому если вы хотите сохранить сложную структуру, то сначала нужно сделать из неё строку с помощью JSON
и только после этого записывать.
Запись в Web Storage является синхронной. Это значит, что на время записи браузер не выполняет другие действия. Поэтому избегайте частых записей в этот вид хранилища.
Indexed DB
СкопированоЭто самый новый способ хранения данных. При этом он обладает достаточно сложным API. В отличие от всех остальных способов, это API асинхронное.
Данный способ представляет собой API базы данных, что зачастую излишне для веб-приложений. Существует много разных библиотек, упрощающих работу с этим видом хранилища.
Пример простого взаимодействия с Indexed DB:
let dbconst connection = indexedDB.open('myDatabase', 1)connection.onupgradeneeded = function(event) { db = event.target.result db.createObjectStore('notes', {autoIncrement: true})}connection.onsuccess = function(event) { db = event.target.result addNote(db, 'Прочитать статью "Хранение данных в браузере"')}connection.onerror = function(event) { console.log(`Ошибка при открытии базы данных: ${event.target.errorCode}`)}function addNote(db, text) { const tx = db.transaction(['notes'], 'readwrite') const store = tx.objectStore('notes') const note = { text, timestamp: Date.now() } tx.oncomplete = () => { console.log('Заметка сохранена') } tx.onerror = (event) => { console.log(`Ошибка при записи заметки: ${event.target.errorCode}`) } store.add(note)}
let db const connection = indexedDB.open('myDatabase', 1) connection.onupgradeneeded = function(event) { db = event.target.result db.createObjectStore('notes', {autoIncrement: true}) } connection.onsuccess = function(event) { db = event.target.result addNote(db, 'Прочитать статью "Хранение данных в браузере"') } connection.onerror = function(event) { console.log(`Ошибка при открытии базы данных: ${event.target.errorCode}`) } function addNote(db, text) { const tx = db.transaction(['notes'], 'readwrite') const store = tx.objectStore('notes') const note = { text, timestamp: Date.now() } tx.oncomplete = () => { console.log('Заметка сохранена') } tx.onerror = (event) => { console.log(`Ошибка при записи заметки: ${event.target.errorCode}`) } store.add(note) }
Универсальные решения
СкопированоСуществуют универсальные решения, которые автоматически используют наиболее подходящий способ хранения данных в браузере. Одним из самых удобных решений является библиотека localForage. Она удачна тем, что очень похожа на полифил и не предоставляет возможности записи в какое-то конкретное хранилище, а сама выбирает, куда записывать данные в зависимости от поддержки браузера. По умолчанию она использует IndexedDB, а если оно не поддерживается, то localStorage.
API библиотеки практически идентично Web Storage. Основное его отличие в том, что все методы являются асинхронными.