Хранилища и cookies

Обмен данными между окнами и iframe

window.postMessage — основной способ для общения между разными origin. Работает между iframe и родителем, между window.open и opener, между попапами. Всегда указывай точный targetOrigin вместо * в продакшене — иначе сообщение получит любой сайт. Данные сериализуются структурированным клоном (поддерживает объекты, массивы, Map, Set, но не функции и классы).

// Отправитель (родитель → iframe)
iframe.contentWindow.postMessage({ type: 'USER', id: 1 }, 'https://trusted.example.com');
 
// Получатель (внутри iframe)
window.addEventListener('message', (e) => {
  if (e.origin !== 'https://trusted.example.com') return;
  console.log(e.data);
});

BroadcastChannel — простой pub/sub между вкладками одного origin. Сообщение получают все вкладки, подписанные на канал с тем же именем, кроме отправителя. Не работает в Safari до версии 15.4. Доступен в Window, Worker и Service Worker.

const ch = new BroadcastChannel('app-sync');
ch.postMessage({ event: 'cart-updated' });
ch.onmessage = (e) => console.log(e.data); // все остальные вкладки
ch.close(); // освобождать канал когда не нужен

localStorage + storage event — синхронизация состояния между вкладками одного origin. Событие storage срабатывает только в других вкладках, не в той, что записала значение. Подходит как fallback если BroadcastChannel не поддерживается.

// Запись
localStorage.setItem('sync', JSON.stringify({ ts: Date.now() }));
 
// Другие вкладки
window.addEventListener('storage', (e) => {
  if (e.key === 'sync') console.log(JSON.parse(e.newValue));
});

SharedWorker — общий воркер, к которому подключаются несколько вкладок одного origin. Позволяет хранить общее состояние и проксировать сообщения между вкладками. Слабее поддерживается чем остальные способы (нет в Firefox в приватном режиме, ограничена поддержка в мобильных браузерах).

contentWindow (same-origin) — если родитель и iframe на одном origin, можно напрямую обращаться к DOM и переменным через iframe.contentWindow. При cross-origin — только postMessage.

МеханизмSame-originCross-originПрименение
postMessageiframe ↔ родитель, попапы, window.open
BroadcastChannelСинхронизация нескольких вкладок
localStorage + storageСинхронизация состояния между вкладками
SharedWorkerОбщее состояние между вкладками
contentWindowПрямой доступ к DOM/переменным iframe

В чём разница между localStorage и sessionStorage?

localStoragesessionStorage
Срок жизниПостоянно (до ручной очистки)До закрытия вкладки
Доступ из других вкладокДа (один origin)Нет
Объём~5 MB~5 MB
Отправка на серверНетНет

Общее:

  • Оба работают как синхронное key-value хранилище.
  • Доступны только через JavaScript (window.localStorage).
  • Привязаны к origin (протокол + домен + порт).

Какие ограничения по размеру у localStorage, sessionStorage и cookies?

  • localStorage / sessionStorage~5 MB (зависит от браузера).
  • Cookies — ~4 KB на одну cookie.
  • IndexedDB — сотни MB и более (лучше для больших объёмов данных).

Если нужно хранить большие объёмы — используй IndexedDB, а не localStorage.


Чем cookies отличаются от localStorage/sessionStorage?

CookieslocalStorage / sessionStorage
Отправка на серверАвтоматическиНет
Размер~4 KB~5 MB
УправлениеJS + серверТолько JS
Срок жизниExpires / Max-AgeSession или persistent
БезопасностьHttpOnly, Secure, SameSiteНет встроенных флагов

Что означают флаги Secure, HttpOnly и SameSite у cookies?

  • Secure — cookie передаётся только по HTTPS.
  • HttpOnly — cookie недоступна из JavaScript. Защищает от XSS.
  • SameSite — управляет отправкой при кросс-сайтовых запросах:
    • Strict — только с того же сайта.
    • Lax — с того же сайта + GET-переходы извне.
    • None — любые запросы (требует Secure).

Для сессионных токенов рекомендуется: HttpOnly; Secure; SameSite=Strict.


Кто может устанавливать cookies?

  • Сервер — через заголовок Set-Cookie в HTTP-ответе.
  • Клиент — через document.cookie = "key=value" (если не стоит HttpOnly).

См. также

  • security — XSS, CSRF и безопасность cookies
  • fetch-cors — same-origin policy и CORS