Работа с localStorage

SvelteKit предоставляет мощный и гибкий подход к работе с данными в браузере, включая работу с localStorage. LocalStorage — это механизм веб-хранилища, который позволяет сохранять данные в виде ключ-значение на стороне клиента и обеспечивает их доступ между перезагрузками страницы. В отличие от sessionStorage, данные в localStorage сохраняются постоянно, пока не будут удалены вручную или через код.

Основы использования localStorage

LocalStorage доступен только в клиентском окружении, что важно учитывать при работе с SvelteKit, так как серверный рендеринг (SSR) не имеет доступа к объекту window.

Простейший пример записи и чтения данных:

// Запись данных
localStorage.setItem('username', 'Ivan');

// Чтение данных
const username = localStorage.getItem('username'); 
console.log(username); // "Ivan"

// Удаление данных
localStorage.removeItem('username');

// Полная очистка localStorage
localStorage.clear();

Реактивное связывание с localStorage

В SvelteKit удобно использовать реактивные переменные и stores для синхронизации состояния с localStorage. Основной подход — создать store, который автоматически читает и записывает данные в localStorage.

import { writable } from 'svelte/store';

function localStorageStore(key, initialValue) {
    const storedValue = typeof window !== 'undefined' 
        ? localStorage.getItem(key) 
        : null;

    const store = writable(storedValue ? JSON.parse(storedValue) : initialValue);

    store.subscribe((value) => {
        if (typeof window !== 'undefined') {
            localStorage.setItem(key, JSON.stringify(value));
        }
    });

    return store;
}

// Использование
export const username = localStorageStore('username', 'Гость');

Преимущества такого подхода:

  • Автоматическая сериализация и десериализация данных через JSON.
  • Состояние всегда синхронизировано с localStorage.
  • Подходит для любых типов данных: строки, объекты, массивы.

Обработка ошибок и совместимость

Работа с localStorage может вызвать ошибки в некоторых ситуациях:

  • Приватный режим браузера может блокировать запись.
  • Превышение лимита памяти (обычно 5-10 МБ).

Рекомендуется оборачивать доступ в блок try/catch:

function safeSetItem(key, value) {
    try {
        localStorage.setItem(key, JSON.stringify(value));
    } catch (e) {
        console.warn(`Не удалось записать в localStorage: ${e}`);
    }
}

function safeGetItem(key, defaultValue = null) {
    try {
        const item = localStorage.getItem(key);
        return item ? JSON.parse(item) : defaultValue;
    } catch (e) {
        console.warn(`Не удалось прочитать localStorage: ${e}`);
        return defaultValue;
    }
}

Синхронизация между вкладками

LocalStorage поддерживает событие storage, которое срабатывает в других вкладках браузера при изменении данных. Это позволяет синхронизировать состояние между открытыми окнами:

window.addEventListener('storage', (event) => {
    if (event.key === 'username') {
        console.log('Новое значение username:', event.newValue);
    }
});

В связке с SvelteKit store можно обновлять локальное состояние:

window.addEventListener('storage', (event) => {
    if (event.key === 'username') {
        username.set(event.newValue ? JSON.parse(event.newValue) : 'Гость');
    }
});

Интеграция с компонентами SvelteKit

Stores на базе localStorage удобно использовать для реализации:

  • Темной/светлой темы.
  • Авторизации и хранения токенов (только если данные не чувствительные).
  • Настроек пользовательского интерфейса.
  • Корзины товаров в интернет-магазине.

Пример привязки к переключателю темы:

<script>
    import { writable } from 'svelte/store';

    const theme = localStorageStore('theme', 'light');

    function toggleTheme() {
        theme.update(value => value === 'light' ? 'dark' : 'light');
    }
</script>

<button on:click={toggleTheme}>
    Переключить тему
</button>

<style>
    :global(body.light) { background: #fff; color: #000; }
    :global(body.dark) { background: #121212; color: #fff; }
</style>

<script>
    $: document.body.className = $theme;
</script>

Рекомендации по архитектуре

  • Хранить в localStorage только небольшие и не чувствительные данные.
  • Сохранять структуры данных через JSON для удобной работы.
  • Использовать отдельный модуль для работы с localStorage и stores, чтобы минимизировать дублирование кода.
  • Проверять наличие объекта window перед доступом к localStorage, чтобы избежать ошибок на сервере.

Расширенные возможности

Можно комбинировать localStorage с SvelteKit endpoints, чтобы данные синхронизировались с сервером при необходимости:

  • Локальные изменения сразу отображаются в UI.
  • Серверное API периодически обновляет данные.
  • Store объединяет локальные и серверные данные для гибкого управления состоянием.

Такая схема позволяет создавать offline-friendly приложения, где пользовательский интерфейс остаётся интерактивным даже без подключения к интернету, а данные сохраняются между сессиями.