Реализация хранения данных (chrome.storage) в браузерном расширении
chrome.storage — единственный надёжный способ хранить данные в расширении. localStorage технически доступен в popup и options page, но не в service worker, и не синхронизируется между контекстами расширения. chrome.storage работает везде.
Три типа хранилищ
chrome.storage.local — хранится локально, до 10 МБ (без разрешения unlimitedStorage). Основной выбор для кэшированных данных, пользовательского контента.
chrome.storage.sync — синхронизируется между устройствами пользователя через аккаунт Google, до 100 КБ / 8 КБ на ключ. Для настроек.
chrome.storage.session — только в памяти, очищается при закрытии браузера. В MV3 — для временного состояния SW, которое переживает его перезапуск (в отличие от переменных), но не переживает перезапуск браузера.
Базовые операции
// Запись
await chrome.storage.local.set({
userData: { id: 42, name: 'Alex' },
lastFetch: Date.now(),
items: [1, 2, 3]
});
// Чтение с дефолтными значениями
const result = await chrome.storage.local.get({
userData: null,
lastFetch: 0,
items: []
});
console.log(result.userData); // { id: 42, name: 'Alex' } или null если не было
// Чтение по ключу
const { settings } = await chrome.storage.sync.get('settings');
// Удаление
await chrome.storage.local.remove(['lastFetch', 'tmpData']);
// Полная очистка
await chrome.storage.local.clear();
Подписка на изменения
chrome.storage.onChanged.addListener((changes, areaName) => {
// changes — объект с ключами, у каждого oldValue и newValue
if (areaName !== 'sync') return;
if ('theme' in changes) {
const { oldValue, newValue } = changes.theme;
console.log(`Тема изменена: ${oldValue} → ${newValue}`);
applyTheme(newValue);
}
});
Это работает во всех контекстах расширения — content script тоже получит событие, если подписан.
Утилита-обёртка для типизированного хранилища
В реальном расширении удобно сделать типизированную обёртку:
// storage/store.ts
type Settings = {
theme: 'light' | 'dark' | 'system';
targetLang: string;
autoTranslate: boolean;
ignoredDomains: string[];
};
const defaultSettings: Settings = {
theme: 'system',
targetLang: 'ru',
autoTranslate: false,
ignoredDomains: [],
};
export const settingsStore = {
async get(): Promise<Settings> {
const result = await chrome.storage.sync.get('settings');
return { ...defaultSettings, ...(result.settings ?? {}) };
},
async set(partial: Partial<Settings>): Promise<void> {
const current = await this.get();
await chrome.storage.sync.set({ settings: { ...current, ...partial } });
},
async reset(): Promise<void> {
await chrome.storage.sync.set({ settings: defaultSettings });
},
onChange(callback: (newSettings: Settings) => void): void {
chrome.storage.onChanged.addListener((changes, area) => {
if (area === 'sync' && 'settings' in changes) {
callback({ ...defaultSettings, ...changes.settings.newValue });
}
});
}
};
Хранение больших объёмов данных
Лимит chrome.storage.local в 10 МБ — по сумме всех значений. При хранении списков или кэша следите за размером:
async function getBytesUsed() {
return new Promise((resolve) => {
chrome.storage.local.getBytesInUse(null, resolve);
});
}
async function addToCache(key, data) {
const used = await getBytesUsed();
const MAX_BYTES = 8 * 1024 * 1024; // 8 МБ — оставляем запас
if (used > MAX_BYTES) {
await evictOldCache();
}
await chrome.storage.local.set({ [key]: { data, timestamp: Date.now() } });
}
async function evictOldCache() {
const all = await chrome.storage.local.get(null);
const cacheKeys = Object.keys(all)
.filter(k => k.startsWith('cache:'))
.sort((a, b) => (all[a].timestamp ?? 0) - (all[b].timestamp ?? 0));
// Удаляем старейшие 20%
const toRemove = cacheKeys.slice(0, Math.ceil(cacheKeys.length * 0.2));
await chrome.storage.local.remove(toRemove);
}
Работа с IndexedDB для больших данных
Когда 10 МБ мало (офлайн-кэш, большие файлы) — используйте IndexedDB. Она доступна в content script и popup, но не в service worker напрямую. В SW можно использовать через idb (обёртка на промисах):
// background/sw.js
import { openDB } from 'idb'; // ~1КБ, работает в SW
const db = await openDB('extension-db', 1, {
upgrade(db) {
db.createObjectStore('pages', { keyPath: 'url' });
}
});
await db.put('pages', { url: 'https://example.com', content: '...', savedAt: Date.now() });
const page = await db.get('pages', 'https://example.com');
Разумный подход: настройки и небольшие данные — в chrome.storage.sync, кэш и контент — в chrome.storage.local или IndexedDB.







