Подключение в браузере без сборщика

В среде браузера без сборщика основным способом подключения становится загрузка библиотеки напрямую из CDN с использованием <script>-тега. В этом режиме localForage добавляется в глобальную область видимости и становится доступен через window.localforage.

<script src="https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js"></script>
<script>
  console.log(window.localforage);
</script>

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


Доступ к глобальному API

В классическом режиме без модулей библиотека становится доступна через идентификатор localforage. Он идентичен window.localforage, но предпочтительнее использовать прямую ссылку для читаемости кода.

localforage.setItem('key', 'value');

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

  • IndexedDB (приоритетный вариант)
  • WebSQL (устаревший, но поддерживаемый в некоторых браузерах)
  • localStorage (резервный вариант)

Выбор происходит автоматически при инициализации.


Базовое использование API

Все операции в localForage асинхронны и возвращают Promise.

Сохранение значения

localforage.setItem('user', {
  name: 'Alex',
  age: 30
}).then(value => {
  console.log('Сохранено:', value);
});

Метод setItem поддерживает любые типы данных, совместимые с алгоритмом structured clone: объекты, массивы, строки, числа, даты, Blob и другие структуры.


Получение значения

localforage.getItem('user').then(value => {
  console.log('Получено:', value);
});

Если ключ отсутствует, возвращается null.


Удаление значения

localforage.removeItem('user').then(() => {
  console.log('Удалено');
});

Очистка хранилища

localforage.clear().then(() => {
  console.log('Хранилище очищено');
});

Получение всех ключей

localforage.keys().then(keys => {
  console.log(keys);
});

Количество элементов

localforage.length().then(numberOfKeys => {
  console.log(numberOfKeys);
});

Настройка экземпляра хранилища

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

const userStore = localforage.createInstance({
  name: 'appDatabase',
  storeName: 'users'
});

const settingsStore = localforage.createInstance({
  name: 'appDatabase',
  storeName: 'settings'
});

Параметры конфигурации

  • name — имя базы данных (используется IndexedDB)
  • storeName — имя хранилища внутри базы
  • description — описание (используется редко, но поддерживается)

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


Настройка драйверов

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

localforage.config({
  driver: [
    localforage.INDEXEDDB,
    localforage.WEBSQL,
    localforage.LOCALSTORAGE
  ],
  name: 'appDatabase',
  storeName: 'mainStore'
});

Основные драйверы

  • INDEXEDDB — основной современный механизм
  • WEBSQL — устаревший, но иногда доступен
  • LOCALSTORAGE — синхронное хранилище с ограничениями

Асинхронная модель и особенности выполнения

Несмотря на наличие localStorage как fallback, API localForage всегда остаётся асинхронным. Это унифицирует работу с данными вне зависимости от выбранного драйвера.

console.log('A');

localforage.setItem('x', 1).then(() => {
  console.log('B');
});

console.log('C');

Порядок вывода будет:

A
C
B

Такой подход позволяет избежать блокировки основного потока выполнения.


Работа с различными типами данных

В отличие от localStorage, который хранит только строки, localForage использует сериализацию, основанную на structured clone algorithm.

Поддерживаемые типы:

  • Object и Array
  • Date
  • Blob и File
  • ArrayBuffer
  • TypedArray
const data = {
  title: 'Document',
  created: new Date(),
  buffer: new Uint8Array([1, 2, 3])
};

localforage.setItem('doc', data);

Обработка ошибок

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

localforage.setItem('bigData', hugeObject)
  .then(() => {
    console.log('OK');
  })
  .catch(err => {
    console.error('Ошибка записи:', err);
  });

Типичные причины ошибок:

  • превышение лимита IndexedDB или localStorage
  • работа в приватном режиме браузера
  • блокировка cookies или storage API
  • повреждённое состояние базы данных

Проверка поддержки хранилищ

Перед активным использованием полезно проверить доступные драйверы.

localforage.supports(localforage.INDEXEDDB);
localforage.supports(localforage.WEBSQL);
localforage.supports(localforage.LOCALSTORAGE);

Возвращается true или false.


Получение текущего драйвера

localforage.getDriver().then(driver => {
  console.log(driver);
});

Это полезно при диагностике поведения приложения в разных браузерах.


Использование с ES-модулем через CDN

Даже без сборщика можно использовать модульную загрузку:

<script type="module">
  import localforage from 'https://cdn.jsdelivr.net/npm/localforage/+esm';

  await localforage.setItem('test', 123);
  const value = await localforage.getItem('test');

  console.log(value);
</script>

В этом режиме библиотека ведёт себя как ES-модуль, а код становится совместимым с современным синтаксисом async/await.


Особенности работы в разных браузерах

В браузерной среде без сборщика поведение зависит от движка:

  • Chrome / Edge — полная поддержка IndexedDB, стабильная работа
  • Firefox — стабильная работа IndexedDB, строгие политики приватности
  • Safari — возможны ограничения квоты и нестабильность WebSQL fallback
  • мобильные браузеры — частые ограничения storage quota

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


Очистка и миграция данных

При изменении структуры приложения важно учитывать, что разные версии приложения могут использовать разные storeName или name.

localforage.config({
  name: 'app_v2'
});

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


Особенности использования без сборщика

При работе без bundler-системы (Webpack, Vite, Rollup) возникают специфические ограничения:

  • отсутствует tree-shaking — загружается вся библиотека целиком
  • зависимости подключаются только через CDN
  • нет возможности импортировать подмодули
  • глобальное пространство имён становится источником API

Поэтому важным становится контроль порядка загрузки и явная инициализация конфигурации до первого обращения к API.


Поведение при повторной инициализации

Повторное вызовы config или createInstance не сбрасывают уже сохранённые данные, но могут изменить контекст доступа:

localforage.config({ name: 'app1' });

localforage.config({ name: 'app2' });

После этого операции будут выполняться уже в новой базе, а старая останется неизменной.


Особенности сериализации

В отличие от JSON-сериализации, используемой в localStorage, механизм хранения localForage сохраняет структуру объектов более точно.

Однако некоторые типы всё же теряют часть данных:

  • функции не сериализуются
  • DOM-элементы не поддерживаются
  • циклические ссылки приводят к ошибкам
const obj = {};
obj.self = obj; // циклическая ссылка

localforage.setItem('bad', obj); // ошибка сериализации

Порядок инициализации в реальном приложении

При использовании без сборщика критически важно соблюдать последовательность:

  1. загрузка <script> с библиотекой
  2. настройка config
  3. создание createInstance (при необходимости)
  4. выполнение операций setItem/getItem

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


Работа в offline-режиме

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

localforage.setItem('offlineQueue', [
  { action: 'save', id: 1 },
  { action: 'delete', id: 2 }
]);

Данные сохраняются независимо от сетевого состояния и доступны при следующей загрузке страницы.


Поведение при очистке браузера

Если пользователь очищает данные сайта, все хранилища localForage удаляются вместе с IndexedDB и localStorage. Библиотека не предоставляет механизмов восстановления, так как работает поверх браузерного слоя хранения.