FlipFlag Persist
Плагин для локального кэширования флагов
Пакет @flipflag/persist позволяет сохранять значения feature flags в локальном хранилище браузера. Это обеспечивает:
- Офлайн-устойчивость — флаги работают даже при отсутствии сети
- Мгновенную загрузку — кэшированные значения доступны сразу
- Снижение нагрузки — меньше запросов к серверу
Установка
npm install @flipflag/persist @flipflag/sdk
# или
yarn add @flipflag/persist @flipflag/sdkБыстрый старт
import { FlipFlag } from "@flipflag/sdk";
import { withLocalStorage } from "@flipflag/persist";
const sdk = new FlipFlag({ publicKey: "YOUR_PUBLIC_KEY" });
const persistedSdk = withLocalStorage(sdk);
await persistedSdk.init();
// Значение флага автоматически кэшируется
if (persistedSdk.isEnabled("newFeature")) {
console.log("Feature enabled!");
}API
withLocalStorage
Обёртка для сохранения флагов в localStorage:
import { withLocalStorage } from "@flipflag/persist";
const persistedSdk = withLocalStorage(sdk, {
prefix: "flipflag:", // префикс ключей (по умолчанию)
ttlMs: 86400000, // время жизни кэша в мс (по умолчанию 24 часа)
});withSessionStorage
Аналогично withLocalStorage, но использует sessionStorage (данные удаляются при закрытии вкладки):
import { withSessionStorage } from "@flipflag/persist";
const persistedSdk = withSessionStorage(sdk);withCookies
Сохраняет флаги в cookies (полезно для SSR и доступа на сервере):
import { withCookies } from "@flipflag/persist";
const persistedSdk = withCookies(sdk, {
prefix: "flipflag:",
ttlMs: 86400000,
// Опции cookie:
path: "/",
domain: undefined,
secure: true, // по умолчанию в production
sameSite: "lax",
});withPersistence
Базовая функция для создания обёртки с кастомным адаптером:
import { withPersistence, localStorageAdapter } from "@flipflag/persist";
const persistedSdk = withPersistence(sdk, {
adapter: localStorageAdapter(),
prefix: "myapp:",
ttlMs: 3600000, // 1 час
onRestore: (flagName, value) => {
console.log(`Restored ${flagName}: ${value}`);
},
onPersist: (flagName, value) => {
console.log(`Persisted ${flagName}: ${value}`);
},
onError: (error) => {
console.error("Persistence error:", error);
},
});Конфигурация
| Опция | Тип | По умолчанию | Описание |
|---|---|---|---|
adapter | StorageAdapter | — | Адаптер хранилища (обязательный для withPersistence) |
prefix | string | "flipflag:" | Префикс ключей в хранилище |
ttlMs | number | 86400000 | Время жизни кэша в миллисекундах (24 часа) |
onRestore | function | — | Колбэк при восстановлении из кэша |
onPersist | function | — | Колбэк при сохранении в кэш |
onError | function | — | Колбэк при ошибках |
Формат хранения
Каждый флаг сохраняется под отдельным ключом:
flipflag:myFeature → { "value": true, "persistedAt": 1234567890, "expiresAt": 1234654290 }
flipflag:anotherFlag → { "value": false, "persistedAt": 1234567890, "expiresAt": 1234654290 }Кастомные адаптеры
Вы можете создать свой адаптер, реализовав интерфейс StorageAdapter:
import type { StorageAdapter, PersistedFlagEntry } from "@flipflag/persist";
const myAdapter: StorageAdapter = {
get(key: string): PersistedFlagEntry | undefined {
// Получить данные по ключу
const data = myStorage.get(key);
return data ? JSON.parse(data) : undefined;
},
set(key: string, entry: PersistedFlagEntry): void {
// Сохранить данные
myStorage.set(key, JSON.stringify(entry));
},
remove(key: string): void {
// Удалить данные
myStorage.delete(key);
},
isAvailable(): boolean {
// Проверить доступность хранилища
return typeof myStorage !== "undefined";
},
};Интеграция с React
Используйте опцию instance в FlipFlagProvider:
"use client";
import { FlipFlag } from "@flipflag/sdk";
import { withLocalStorage } from "@flipflag/persist";
import { FlipFlagProvider, useFlag } from "@flipflag/react";
// Создаём SDK с persistence
const sdk = new FlipFlag({ publicKey: "YOUR_PUBLIC_KEY" });
const persistedSdk = withLocalStorage(sdk);
function App() {
return (
<FlipFlagProvider options={{ instance: persistedSdk }}>
<MyComponent />
</FlipFlagProvider>
);
}
function MyComponent() {
const enabled = useFlag("newFeature", false);
return <div>{enabled ? "Новая версия" : "Старая версия"}</div>;
}Поведение при ошибках
Когда SDK не может получить данные с сервера (офлайн, ошибка сети), плагин автоматически возвращает кэшированное значение:
isEnabled("flag")пытается получить значение из SDK- Если успешно — значение кэшируется и возвращается
- Если ошибка — возвращается значение из кэша (если не истёк TTL)
- Если кэш пуст или истёк — возвращается
false
Встроенные адаптеры
| Адаптер | Описание |
|---|---|
localStorageAdapter() | Сохраняет в localStorage |
sessionStorageAdapter() | Сохраняет в sessionStorage |
cookieAdapter(options?) | Сохраняет в cookies |
memoryAdapter() | Сохраняет в памяти (для тестов) |