Проблема: данные в расширении теряются или не синхронизируются
При разработке браузерного расширения для Chrome одна из самых частых ошибок — потеря данных при перезапуске service worker или несинхронизация настроек между устройствами пользователя. Многие начинающие разработчики полагаются на localStorage, но он не работает в background-скриптах Manifest V3 и не уведомляет об изменениях в других контекстах. В результате пользователь меняет тему на ноутбуке — на десктопе тема остаётся старой, а кэш переводов исчезает после 30 секунд бездействия. В одном из наших проектов — расширении для переводчика с 10 000 активных пользователей — мы столкнулись с потерей кэша при каждом перезапуске service worker. Решение оказалось простым: комбинация chrome.storage.sync для настроек и chrome.storage.local для кэша. Мы реализовали хранилища более чем для 50 расширений и имеем 5-летний опыт в этой области.
Какие проблемы решаем
Несинхронизация настроек возникает, когда пользователь меняет тему на одном устройстве, а на другом она остаётся прежней. chrome.storage.sync автоматически синхронизирует данные через аккаунт Google, лимит — 100 КБ, но для конфигурации этого хватает.
Потеря кэша при перезапуске service worker — типичная проблема в MV3, так как SW выгружается через 30 секунд бездействия. Если хранить кэш в переменных, он исчезнет. chrome.storage.local или session решают проблему.
Отсутствие типизации приводит к ошибкам при чтении данных, особенно при миграции структуры. Мы создаём типизированные обёртки на TypeScript с дефолтными значениями, что исключает неопределённое поведение.
Как мы реализуем хранилище: разбор кейса
Для расширения-переводчика с 10 000 пользователей мы спроектировали систему хранения: настройки (тема, язык, авто-перевод) — в chrome.storage.sync, кэш переводов — в chrome.storage.local с вытеснением старых записей при достижении 8 МБ. Код типизированной обёртки для настроек:
// 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 }); } }); } }; Благодаря этому расширение гарантированно сохраняет выбор пользователя и мгновенно реагирует на изменения. Кэш занимает в среднем 3 МБ, но при необходимости мы внедрили механизм вытеснения LRU: удаляем записи, к которым не обращались более 30 дней.
Почему chrome.storage надёжнее localStorage и других методов?
| Характеристика | localStorage | chrome.storage.local | chrome.storage.sync | IndexedDB |
|---|---|---|---|---|
| Доступен в SW | Нет | Да | Да | Нет (нужна обёртка) |
| Синхронизация | Нет | Нет | Да (через Google) | Нет |
| Лимит | ~5-10 МБ | 10 МБ (до 1 ГБ с разрешением) | 100 КБ | Ограничен диском |
| Уведомления об изменениях | Нет | Да (onChanged) | Да | Нет |
Отметим: как видно, chrome.storage — единственный вариант для service worker и синхронизации. Согласно документации Google, chrome.storage.sync автоматически синхронизирует данные (developer.chrome.com).
| Лимит | storage.local | storage.sync | storage.session |
|---|---|---|---|
| Стандартный | 10 МБ | 100 КБ | Ограничен памятью |
| С разрешением unlimitedStorage | до 1 ГБ | — | — |
Процесс работы над вашим расширением
- Анализ: определяем типы данных, объём (до 10 МБ или больше, если нужно синхронизировать), требования к синхронизации и офлайн-режиму.
- Проектирование: выбираем комбинацию хранилищ (local, sync, session, IndexedDB), проектируем типизированные обёртки, продумываем стратегию вытеснения (LRU, TTL).
- Реализация: пишем код на TypeScript с полным покрытием unit-тестами (Jest), используем паттерн Repository и фабрики для разных типов хранилищ.
- Тестирование: проверяем поведение при перезапуске SW, при превышении лимитов, при множественных вкладках и одновременных записях.
- Деплой: публикуем расширение в Chrome Web Store с полной документацией по API хранилища.
Что входит в работу
- Полный код хранилища с типизацией и обёртками (TypeScript).
- Документация по API и архитектуре (README).
- Инструкция по миграции с localStorage (если нужно).
- Обучение команды поддержке и доработкам (1 час консультации).
- Гарантия: мы поддерживаем код в течение 3 месяцев после сдачи (исправляем ошибки).
Сроки и стоимость
Сроки разработки хранилища — от 3 до 10 рабочих дней в зависимости от сложности (один тип хранилища или комбинация). Стоимость рассчитывается индивидуально после анализа требований. Свяжитесь с нами — получите консультацию и предварительную оценку бесплатно.
Как обеспечить синхронизацию между устройствами?
Для синхронизации настроек и других небольших данных используйте chrome.storage.sync. Лимит — 100 КБ на всё хранилище, но для конфигурации этого достаточно. При каждом изменении данные автоматически распространяются на все устройства, где установлено расширение. Если нужно синхронизировать большие объёмы (например, закладки), используйте chrome.storage.local с собственным сервером синхронизации или облачным сервисом.
Как подписаться на изменения и избежать гонок данных?
Используйте событие onChanged. Подписка во всех контекстах расширения позволяет синхронизировать UI и фоновые процессы. Пример:
chrome.storage.onChanged.addListener((changes, areaName) => { if (areaName !== 'sync') return; if ('theme' in changes) { const { newValue } = changes.theme; applyTheme(newValue); } }); Этот паттерн предотвращает гонки данных, так как изменения обрабатываются последовательно.
Дополнительные рекомендации
Хранилище chrome.storage.sync позволяет хранить до 100 КБ данных, при этом один ключ не может превышать 8 КБ. Для больших объёмов используйте chrome.storage.local или IndexedDB. Очистить все данные можно вызовом clear(), но учтите, что sync очистит данные на всех устройствах. chrome.storage автоматически сериализует объекты в JSON, поэтому функции, undefined и символы недопустимы. Для бинарных данных используйте IndexedDB или конвертацию в base64 с учётом лимитов. При обновлении расширения внедряйте версионирование и миграции — храните версию схемы отдельно.
Надёжное хранение данных — основа любого расширения. Закажите разработку хранилища для вашего проекта. Свяжитесь с нами — получите консультацию и предварительную оценку.







