Как очистить локал сторадж в браузере
Привет! В этой статье я бы хотел поговорить про LocalStorage, его методы и особенности. Статью можно посмотреть в формате видео по этой ссылке. Ну что, приступим?
И так, что же это такое. LocalStorage это свойство объекта window, предназначенное для хранения пар ключ/значение в браузере. В зависимости от браузера, мы можем сохранять до 5 мб данных. Но тогда возникает логичный вопрос, зачем нам localStorage, если данные мы можем сохранять данные в обычных переменных? Ответ очень прост, все что мы запишим в localStorage, останется там после перезагрузки страницы и даже после закрытия браузера. Теперь поговорим о том как мы можем взаимодействовать с localStorage.
Запись в LocalStorage
Чтобы сохранить данные можем использовать метод setItem(key, value) у localStorage. Этод метод принимает два аргумента: ключ по которому мы будем сохранять информацию и само значение, которое мы хотим сохранить. Например:
Для просмотра наших записей надо открыть DevTools там найти вкладку Application и там обязательно будет LocalStorage
Чтение из LocalStorage
Теперь конечно же хочется получить эти данные. Для этого воспользуемся методом getItem(key) . Результат можно вывести в консоль, или сохранить в переменную.
Только строки
Как видите, все просто, но есть один маленький нюанс. Значение, которое мы записываем должно быть строкой. Давайте попробуем добавить поле age со значением 5. Для этого напишем:
Сохраняем файл. И что мы видим? Ошибок никаких нет, а если перейти во вкладку Application, то мы увидим что запись прошла успешно. Это конечно же так, но при записи пятерка стала строкой, то есть была автоматически приведена к типу string. Это не то чтобы плохо, но может привести к неожиданному поведению, к примеру при строгом сравнении. Я бы советовал привести строку к числу, это можно сделать вот так:
Если с примитивами все просто, то что на счет объектов? Создадим объект user и попробуем записать его в LocalStorage:
Переходим во вкладку Application и видим [objectObject] .
И есть одна небольшая проблемка у этой строки не будет полей, которые мы определили в объекте user. Это просто обычная строка. И в исходный вид это уже никак не вернуть. Для того, чтобы записать объект в localStorage надо сделать его строкой. У нас как раз есть прекрасный формат под это, и имя его json . Для преобразования объекта в строку нужно использовать JSON.stringify :
Теперь все записалось корректно:
Чтобы получить объект в первозданном состоянии используем метод parse у JSON :
Полученый результат можем записать в консоль, или сохранить в переменную.
Удаление из LocalStorage
Мы научились записывать и получать элементы, теперь надо научится их удалять. Для этого будем использовать метод removeItem(key) который удалит поле с ключом key .
Так же во вкладке Application мы можем выделить нужный нам рядок и нажать на крестик, что тоже приведет к удалению.
Очистка LocalStorage
Чтобы очистить все поля мы можем использовать метод clear() :
Вариант из Application:
Я рекомендую так делать, только тогда, когда вы на 200% уверены что все данные заносили только вы, и после удаления чего либо ваш сайт не начнет вести себя некорректно.
Событие storage
Если у вас есть потребность, или желание прослушивать изменение в localStorage, то можно просто добавить слушатель событий на 'storage' :
При каждом изменении localStorage генерируется событие storage. Оно отрабатывает на всех вкладках, на которых открыт наш сайт, кроме той, где мы создали это событие. В event хранятся название поля которое мы затронули, старое значение, новое значение, url документа и storageArea. Если интересно, крайне рекомендую переписать этот кусок кода себе, открыть две вкладки вашего локалхоста и посмотреть как это работает.
Также, надо держать в голове что самый "топовый" браузер, то бишь IE вызывает событие 'storage' даже если данные не изменились, что является некорректным поведением. Поэтому если вам не пофиг на екплоер и вы не хотите каких-то нежданчиков, то надо явно сравнивать новое и старое значение, которые мы можем получить из event .
Один из наших читателей прислал статью с рассказом о HTML5 LocalStorage в браузерах. Передаём ему слово.
Я постарался написать самое простое и понятное руководство по использованию технологии localStorage. Статья получилась совсем небольшой, в силу того, что и сама технология и средства работы с ней не несут ничего сложного. Для старта вам достаточно чуть-чуть знать JavaScript. Итак, уделите этой статье 10 минут и вы смело сможете добавить себе в резюме строчку «умею работать с localStorage».
Что такое localStorage?
Так выглядит JavaScript объект:
А так выглядит JSON. Почти так же как обычный js-объект, только все свойства должны быть заключены в кавычки.
Чтобы понять, что такое localStorage, просто представьте, что где-то у вас в браузере встроен такой объект, которым мы можем пользоваться. При этом данный объект не очищает значения, которые мы туда запишем, если мы перезагрузим страницу или даже совсем закроем браузер.
Если говорить языком JavaScript, то localStorage это свойство глобального объекта браузера (window). К нему можно обращаться как window.localStorage или просто localStorage.
Еще стоит сказать, что у браузера существует клон localStorage, который называется sessionStorage. Их разница только в том, что последний хранит данные только для одной вкладки (сессии) и просто очистит свое пространство как только мы закроем вкладку
Давайте посмотрим на него вживую. Например, в Google Chrome вам надо открыть DevTools (F12), перейти на вкладку «Resourses» и на левой панели вы увидите localStorage для данного домена и все значения, что оно содержит.
Зачем мне нужен localStorage?
LocalStorage нужен только для одного — хранить определенные данные между сессиями пользователя. Можно придумать тысячу и одну вещь, которую можно хранить в локальном хранилище браузера. Например, браузерные игры, которые используют его как сохраненку, или записать момент, на котором пользователь остановился при просмотре видео, различные данные для форм и т.д.
Как мне начать работать с localStorage?
Работа с localStorage очень напоминает работу с объектами в JavaScript. Существует несколько методов для работы с ним.
Метод который добавляет в localStorage новый ключ со значением (а если такой ключ уже существует, то перезаписывает новым значением). Пишем, например, localStorage.setItem(‘myKey’, ‘myValue’);
Берем определенное значение из хранилища по ключу.
Очищаем все хранилище
Сейчас вы можете открыть вкладку с localStorage вашего браузера и самостоятельно потренироваться записывать и извлекать данные из этого хранилища. Если что — весь код пишем в js-файл.
Также хочется отметить, что localStorage отлично работает и с вложенными структурами, например, объектами.
Вы также должны знать, что браузеры выделяют 5мб под localStorage. И если вы его превысите — получите исключение QUOTA_EXCEEDED_ERR. Кстати, c его помощью можно проверять есть ли в вашем хранилище еще место.
Вместо заключения
Мне бы хотелось, чтобы из этой небольшой статьи разработчики сделали для себя простой вывод, что данная технология уже вовсю может использоваться у вас на проектах. У нее хорошая стандартизация и отличная поддержка, которая со временем только развивается.
Как долго я могу ожидать, что данные будут храниться в localStorage. Как долго будут сохраняться данные локального хранилища среднего пользователя? Если пользователь не очистит его, будет ли он длиться до переустановки браузера?
является ли это согласованным в браузерах?
проект W3C говорит это
агенты пользователей должны истекать данные из локальных областей хранения только по соображениям безопасности или по запросу пользователя. Агенты пользователей всегда должны избегать удаления данных во время выполнения сценария, который может получить доступ к этим данным.
поэтому, если браузеры следуют спецификации, она должна сохраняться до тех пор, пока пользователь не удалит ее во всех браузерах, я не нашел ни одного, который удалил на любом из моих проектов.
localStorage также известен как веб-хранилище, хранилище HTML5 и хранилище DOM (все они означают одно и то же).
localStorage похож на sessionStorage,кроме этого данные, хранящиеся в localStorage, не имеют срока действия, в то время как данные, хранящиеся в sessionStorage, очищаются, когда сеанс просмотра заканчивается (т. е. когда браузер закрыт).
localStorage доступен во всех браузерах, но постоянство не реализуется последовательно. В частности, localStorage может быть очищен действием пользователя и может быть очищен непреднамеренно (кто бы подумал, что очистка всех файлов cookie также очищает localStorage?).
в Firefox localStorage очищается, когда выполняются эти три условия: (a) пользователь очищает недавнюю историю, (b) файлы cookie выбираются для очистки, (c) диапазон времени - "все"
в IE, чтобы очистить хранилище localStorage: (а) инструменты--настройки интернета, (б) вкладка "Общие", (с) удалять журнал браузера при выходе (D) для обеспечения "файлы cookie и данные веб-сайтов" (или "временные файлы интернета и веб-файлы") выбран (е) рассмотреть убрав галочку "Сохранить данные избранных веб-сайтов данных" сверху
в Safari: (A) нажмите Safari (b) настройки (c) выберите вкладку Конфиденциальность (d) нажмите Удалить все данные веб-сайта (e) нажмите Удалить сейчас
Opera: несмотря на отличные статьи о localStorage с сайта Opera, я еще не нашел четких (не программных) инструкций для пользователей о том, как очистить localStorage. Если кто-то найдет, пожалуйста, оставьте комментарий ниже этого ответа со ссылкой.
мой случай: localStorage с ключом + значение, которое должно быть удалено, когда браузер закрыт, а не одна вкладка.
пожалуйста, посмотрите мой код, если он правильный и что можно улучшить:
должно быть сделано так, а не с оператором delete:
вы можете использовать beforeunload событие в JavaScript.
используя vanilla JavaScript, вы можете сделать что-то вроде:
это удалит ключ перед закрытием окна/вкладки браузера и предложит вам подтвердить действие закрыть окно/вкладку. Надеюсь, это решит вашу проблему.
Примечание: onbeforeunload метод должен возвращать строку.
С window ключевое слово Global:-
вы должны использовать sessionStorage вместо этого, если вы хотите, чтобы ключ был удален при закрытии браузера.
надеюсь, что это работает для вас
существует очень конкретный вариант использования, в котором любое предложение использовать sessionStorage вместо localStorage не очень помогает. Прецедент будет таким же простым, как сохранение чего-то, пока у вас открыта хотя бы одна вкладка, но аннулирует ее, если вы закроете последнюю оставшуюся вкладку. Если вам нужно, чтобы ваши значения были сохранены в кросс-вкладке и окне, sessionStorage не поможет вам, если вы не усложните свою жизнь со слушателями, как я пытался. В то же время localStorage будет идеально подходит для этого, но он делает работу "слишком хорошо", так как ваши данные будут ждать там даже после перезагрузки браузера. В итоге я использовал пользовательский код и логику, которые используют оба преимущества.
Я лучше объясню, чем дам код. Сначала сохраните то, что вам нужно в localStorage, затем также в localStorage создайте счетчик, который будет содержать количество открытых вкладок. Это будет увеличиваться при каждой загрузке страницы и уменьшаться при каждой выгрузке страницы. Вы можете выбрать здесь событий, я предлагаю загружать и разгружать. Во время выгрузки вам нужно выполнить задачи очистки, которые вы хотели бы, когда счетчик достигает 0, то есть вы закрываете последнюю вкладку. Вот сложная часть: я не нашел надежного и общего способа определить разницу между перезагрузкой страницы или навигацией внутри страницы и закрытием вкладки. Поэтому, если данные, которые вы храните, не являются чем-то, что вы можете перестроить при загрузке после проверки того, что это ваш сначала вкладка, затем вы не можете удалить ее при каждом обновлении. Вместо этого вам нужно сохранить флаг в sessionStorage при каждой загрузке перед увеличением счетчика вкладок. Перед сохранением этого значения вы можете проверить, имеет ли оно уже значение, а если нет, это означает, что вы загружаетесь в этот сеанс впервые, что означает, что вы можете выполнить очистку при загрузке, если это значение не установлено, а счетчик равен 0.
объект sessionStorage равен объекту localStorage, за исключением того, что он хранит данные только для одного сеанса. Данные удаляются, когда пользователь закрывает окно браузера.
в следующем примере подсчитывается количество раз, когда пользователь нажимает кнопку, в текущем сеансе:
вот простой тест, чтобы узнать, есть ли у вас поддержка браузера при работе с локальным хранилищем:
Я не думаю, что представленное здесь решение на 100% правильно, потому что окно.onbeforeunload событие вызывается не только при закрытии браузера/вкладки(что требуется), но и на всех других нескольких событиях. (ЧТО МОЖЕТ НЕ ПОТРЕБОВАТЬСЯ)
см. эту ссылку для получения дополнительной информации о списке событий, которые могут запускать окно.onbeforeunload:-
Почему бы не использовать sessionStorage?
"объект sessionStorage равен объекту localStorage, за исключением того, что он хранит данные только для одного сеанса. Данные удаляются, когда пользователь закрывает окно браузера."
хотя некоторые пользователи уже ответили на этот вопрос, я даю пример настроек приложения для решения этой проблемы.
Статья состоит из двух частей: теоретической и практической.
В теоретической части мы кратко рассмотрим карту импортов и более подробно Clear-Site-Data .
В практической части мы поднимем два сервера — один будет запускаться локально и, помимо прочего, обслуживать статические файлы нашего приложения, другой мы развернем на Heroku . Сначала мы запросим данные (включая куки) от серверов, сохраним эти данные в браузере с помощью трех наиболее популярных механизмов (локальное хранилище, индексированная база данных и интерфейс кеширования), затем попробуем очистить их с помощью заголовков Clear-Site-Data . Для разрешения путей импортируемых в приложении модулей мы будем использовать карту импортов.
Исходный код проекта находится здесь.
Ресурсы
О механизмах для хранения данных на стороне клиента, которые мы будем использовать в приложении, я рассказывать не буду. Вот ссылки на отличные ресурсы, посвященные каждому из них:
Инструменты
При разработке приложения мы будем использовать несколько инструментов, основными из которых являются следующие:
Теория
Карта импортов
Карта импортов (imports map) позволяет использовать так называемые голые спецификаторы импорта (bare import specifiers) в инструкциях import и выражениях import() без участия сборщиков типа Webpack или других инструментов для разрешения путей импортируемых модулей во время выполнения кода.
Предположим, что в нашем проекте используются библиотека lodash и утилита very-simple-fetch :
Для того, чтобы импортировать эти модули без помощи "бандлера", необходимо указать полный путь к соответствующим файлам, хранящимся в директории node_modules :
Карта импортов позволяет связать кастомные ключи — названия модулей — с их расположением. Для этого в теге с типом importmap определяется объект с ключом imports и парами ключ / значение, где значение — это путь к модулю, а ключ — синоним (алиас) для этого пути:
После определения карты импортов, у нас появляется возможность импортировать наши модули следующим образом:
Карты импортов также предоставляют много других интересных возможностей. К сожалению, в настоящее время они поддерживаются только Chrome . Если вы пользуетесь другим агентом, при разработке приложения в практической части статьи импортируйте модули напрямую из node_modules .
Clear-Site-Data
Данный заголовок принимает следующие директивы:
Директивы могут указываться как по одной:
так и через запятую:
Последний пример аналогичен следующему:
К сожалению, в настоящее время данный заголовок не поддерживается Safari (ох уж этот современный IE :)).
Вот как это должно работать в теории. Скоро мы выясним, что на практике это работает немного по-другому, а кое-что и вовсе не работает.
Практика
Фронтенд и локальный сервер
Создаем директорию для проекта, переходим в нее, инициализируем проект и устанавливаем зависимости:
Создаем файл server.js для локального сервера и директорию public для статических файлов, а в ней файлы index.html , style.css и script.js :
Не забудьте создать файл .gitignore с node_modules .
Начнем с public/index.html . Создаем контейнер для UI и секцию с кнопками для взаимодействия с локальным сервером:
Обратите внимание на атрибуты data-action кнопок. Это небольшая хитрость позволит нам сильно упростить и сократить код скрипта. А по классам, вы, наверное, догадались, какой CSS-фреймворк мы используем для стилизации.
Добавляем карту импортов для модулей very-simple-fetch и idb :
Честно говоря, поиск нужного файла в директории node_modules — занятие не из приятных. К тому же приходится искать не просто основной файл, но нужную версию файла. Например, ES-модуль idb хранится в директории esm .
Подключаем наш скрипт с типом module :
С вашего позволения файл со стилями style.css я пропущу.
Переходим к public/script.js .
Давайте подумаем, что должен делать наш скрипт.
Вот мои идеи на этот счет:
- записать данные в локальное хранилище
- записать данные в индексированную БД
- записать данные в кеш с помощью Cache API
- получить куки от локального сервера
- при нажатии кнопки отправлять на сервер запрос, в ответ на который сервер будет устанавливать заголовок Clear-Site-Data с соответствующей директивой.
Приступим к реализации ( // -> — означает сигнатуру):
Обратите внимание на то, как мы формируем URL запроса. Мы добавляем к адресу сервера значение атрибута data-action кнопки. Это первая половина хитрости.
Теперь займемся сервером ( server.js ).
Что он должен делать?
Я хочу, чтобы он делал следующее:
Мы передаем клиенту куки вместе с загружаемыми модулями. Получается, что мы делаем это дважды, но это не критично. Поскольку у нас один домен и названия куки совпадают, мы в итоге получим только одно куки.
Обратите внимание на то, как мы извлекаем тип операции — директиву для Clear-Site-Data — из тела запроса. Мы разбиваем строку в массив по символу - и извлекаем второй элемент (элемент по индексу 1). Таким образом, если сервер получил clear-storage , то типом операции (директивой) будет storage .
Также обратите внимание на то, что директива должна быть закавычена, причем кавычки обязательно должны быть двойными ( " ).
Пришло время запустить сервер и убедиться в том, что все работает.
Добавляем в файл package.json команду для запуска сервера для разработки:
Выполняем эту команду в терминале:
Открываем инструменты разработчика, переходим в раздел Application (“Приложение”) и проверяем, что все наши данные успешно сохранены в браузере:
Видим, что данные из локального хранилища, индексированной БД и локального кеша были успешно удалены.
Кажется, что все хорошо, однако нажатие кнопки Reload contexts приводит к возникновению ошибки:
Текст ошибки говорит нам о том, что браузер не может распознать тип операции (тип данных для очистки).
Дело в том, что директива "executionContexts" в настоящее время поддерживается только Samsung Internet , т. е. можно сказать, что не поддерживается. В сети можно найти информацию о том, что данная директива, скорее всего, будет удалена из спецификации.
Дальше интересней: нажатие кнопки Clear all site data также приводит к ошибке:
Хотя должно приводить к очистке данных всех типов.
Здесь мы имеем дело с багом Chrome . Вот все, что мне удалось найти по данному багу. Кажется, в ближайшее время никто не собирается его фиксить.
В Firefox это работает:
Кажется, что эти директивы правильно интерпретируются браузером, т. е. приводят к очистке данных указанного типа.
Но что насчет определения принадлежности данных к источнику ответа перед их очисткой? Для того, чтобы убедиться в том, что удаляются только такие данные необходимо поднять еще один сервер. Для чистоты эксперимента развернем этот сервер на Heroku .
Удаленный сервер
Начнем с самого сервера. Создаем для него директорию, переходим в нее, инициализируем проект и устанавливаем зависимости:
Определяем команду для запуска сервера в package.json :
Создаем файл index.js следующего содержания:
- origin — заголовок Access-Control-Allow-Origin
- credentials — заголовок Access-Control-Allow-Credentials
- allowHeaders — заголовок Access-Control-Allow-Headers
Без этих настроек и еще одной на клиенте мы не сможем получить куки от "удаленного" сервера.
Для того, чтобы иметь возможность разворачивать приложения на Heroku , необходимо создать там аккаунт, а также глобально установить heroku-cli :
Инициализируем репозиторий и добавляем в него файлы приложения:
Создаем проект на Heroku :
Проверяем, что наш проект привязан к Heroku-проекту, и отправляем файлы:
Полную инструкцию по деплою приложения на Heroku можно найти здесь.
Добавляем в public/index.html раздел с кнопками для взаимодействия с удаленным сервером:
И вносим несколько изменений в public/script.js :
В разделе Application находим кешированные данные и куки от heroku:
И это не баг Chrome (или баг не только Chrome ), точно такой же результат мы получаем в Firefox :
Директива * также не удаляет кешированные данные, полученные от heroku:
К сожалению, по этой проблеме информации найти не удалось. Если вдруг вы знаете, в чем дело, пожалуйста, сообщите в комментариях.
Вывод
Итак, что мы имеем в сухом остатке?
Карта импортов в настоящее время поддерживается только Chrome . Будет ли она поддерживаться другими браузерами, и, если будет, когда это произойдет, неизвестно. Поэтому, несмотря на интересные возможности, использовать ее при разработке реальных приложений пока нельзя.
Что касается заголовка Clear-Site-Data , то, в целом, он неплохо справляется со своей задачей, однако тот факт, что он не поддерживается Safari , а также учитывая баг в Chrome и не очень понятное поведение браузеров по очистке кешированных данных, говорить о возможности его использования в продакшне также преждевременно.
Читайте также: