Browser Internals

Как работают веб-воркеры? Какие виды бывают?

Web Workers

Основная идея

Воркер — это отдельный поток браузера со своим событийным циклом. Нет доступа к DOM и window. Общение с основным потоком — только через сообщения:

// Основная страница → воркер
worker.postMessage(data);
 
// Воркер → основная страница
onmessage = (e) => postMessage(e.data);

Виды воркеров

Dedicated Worker

const worker = new Worker('script.js');

Один владелец (вкладка/скрипт). Для тяжёлых вычислений — парсинг, крипто, обработка изображений.

Shared Worker

const worker = new SharedWorker('script.js');

Несколько вкладок могут подключаться к одному воркеру. ⚠️ Поддержка в браузерах ограничена.

Service Worker

navigator.serviceWorker.register('/sw.js');

Прокси между сетью и приложением: офлайн, кэш, push-уведомления. Жизненный цикл: install → activate → fetch. Не для тяжёлых вычислений.


Передача данных

СпособКакКогда
КлонированиеpostMessage(data)По умолчанию, делает копию
TransferpostMessage(data, [data])Большие буферы, zero-copy, оригинал становится пустым

Note

Transfer работает только с Transferable: ArrayBuffer, MessagePort, OffscreenCanvas, ReadableStream.


Связанные API

Worklet (AudioWorklet, PaintWorklet и др.) — лёгкие мини-воркеры для узких браузерных задач (звук, рисунок в CSS, анимации). Стабильно работают только в Chrome/Edge.

SharedArrayBuffer + Atomics — разделяемая память между потоками. Нужна редко, в основном для WebAssembly/C++. Требует заголовков на сервере:

Cross-Origin-Opener-Policy: same-origin  
Cross-Origin-Embedder-Policy: require-corp

Что происходит после ввода URL до появления страницы?

URL → DNS → TCP → TLS → HTTP GET → байты HTML → (парсинг + DOM + CSSOM параллельно) → Render Tree → Layout → Paint → Compositing


1. Кэш-проверка Проверяется по каждому ресурсу отдельно. DNS-кэш — есть ли IP для домена (если TTL не истёк, DNS lookup пропускается). HTTP-кэш — три варианта: кэш свежий (max-age не истёк) → файл берётся локально; кэш устарел, файл не изменился → сервер отвечает 304 Not Modified; файл изменился → 200 OK, скачивается новый.

2. DNS lookup Домен превращается в IP-адрес. Порядок: локальный кэш → системный hosts → DNS-сервер провайдера → рекурсивный обход до корневых серверов.

3. TCP handshake Три шага чтобы браузер и сервер убедились что слышат друг друга. SYN — браузер → сервер: «хочу соединение, вот мой стартовый номер пакета». SYN-ACK — сервер → браузер: «принял, я тоже готов, вот мой номер». ACK — браузер → сервер: «принял, начинаем».

4. TLS handshake (только HTTPS) Согласуются алгоритмы шифрования, обмениваются сертификатами и ключами. Начиная с TLS 1.3 — занимает всего 1 round-trip.

5. HTTP GET запрос Браузер отправляет запрос с заголовками (Host, Accept, Cookie и др.).

6. Сервер возвращает HTML Браузер начинает получать байты ответа.

7. Парсинг HTML = построение DOM Это один инкрементальный процесс: байты → символы (декодирование UTF-8) → токены (теги, атрибуты, текст) → DOM-узлы. Дерево строится по мере получения байт, не после.

Если встречается <script> без async/defer или <link rel="stylesheet"> — парсер останавливается и ждёт загрузки/исполнения ресурса.

8. Загрузка CSS = построение CSSOM Строится параллельно с DOM. Не блокирует построение DOM, но блокирует рендер.

9. Загрузка остальных ресурсов JS, изображения, шрифты — браузер обнаруживает их по мере парсинга и запрашивает параллельно (Speculative / Preload Scanner).

10. Render Tree DOM + CSSOM объединяются. Попадают только видимые узлы с вычисленными стилями. display: none — исключается вместе с потомками. visibility: hidden — включается, занимает место. <head>, <script>, <meta> — не попадают, нет визуального представления.

11. Layout (Reflow) Вычисляются точные размеры и позиции каждого элемента на экране.

12. Paint Узлы превращаются в пиксели: цвета, тени, текст, границы — рисуются на слоях.

13. Compositing Слои склеиваются и выводятся на экран в правильном порядке (z-index, трансформации).


Что такое DNS lookup и как работает кэширование?

DNS lookup — процесс получения IP-адреса по доменному имени.

Уровни кэширования (от ближнего к дальнему):

  1. Браузерный кэш DNS.
  2. Кэш операционной системы (/etc/hosts тоже проверяется).
  3. Кэш роутера.
  4. Кэш DNS-резолвера провайдера.
  5. Рекурсивный запрос к корневым DNS-серверам.

У каждой DNS-записи есть TTL (Time To Live) — время, после которого кэш устаревает.


Что такое DOM и CSSOM?

  • DOM (Document Object Model) — дерево объектов, построенное из HTML. Каждый тег становится узлом дерева.
  • CSSOM (CSS Object Model) — дерево, отражающее все CSS-правила и их приоритеты.

Процесс:

  • HTML → токенизация → парсинг → DOM.
  • CSS → токенизация → парсинг → CSSOM.
  • DOM + CSSOM → Render Tree (только видимые элементы).

display: none исключает элемент из Render Tree. visibility: hidden — нет.


Что такое layout (reflow)?

Layout — этап вычисления геометрии: размеры, позиции, отступы всех элементов.

Что влияет на layout:

  • width, height, padding, margin, border
  • font-size, line-height
  • position, float, flex, grid

Важно: layout — глобальная операция. Изменение одного элемента может затронуть соседей и родителей. Особенно дорого это в больших деревьях.


Что такое painting и compositing?

Painting — браузер рисует каждый элемент попиксельно: текст, фон, границы, тени, градиенты. Результат — набор слоёв.

Compositing — слои собираются в финальное изображение на экране. Часть этой работы выполняет GPU, а не CPU.

Оптимизация: свойства transform и opacity меняются только на этапе compositing, минуя layout и paint — это делает их анимацию наиболее производительной.


Чем reflow отличается от repaint?

ReflowRepaint
Что пересчитываетсяГеометрия (размеры, позиции)Внешний вид (цвет, тень)
Затрагивает соседейДа, можетНет
СтоимостьВысокаяСредняя
Примерwidth, margin, font-sizecolor, background, border-color

Каждый reflow влечёт repaint, но не наоборот.


Что вызывает reflow и как его минимизировать?

Причины:

  • Добавление / удаление / перемещение DOM-узлов.
  • Изменение геометрических CSS-свойств.
  • Чтение offsetWidth, scrollTop, getBoundingClientRect() после DOM-изменений.
  • Ресайз окна браузера.

Как минимизировать:

  • Батчить DOM-изменения (менять разом, не по одному).
  • Читать layout-свойства до изменений, а не между ними.
  • Использовать documentFragment для вставки множества элементов.
  • Анимировать через transform/opacity вместо top/left.

Что такое SPA, как работает, что передаётся с сервера?

SPA (Single Page Application) — веб-приложение, которое загружает одну HTML-страницу один раз, а затем динамически обновляет содержимое без перезагрузки страницы.

Как работает:

  • При первом запросе сервер отдаёт один index.html + бандл JS (и CSS)
  • Все переходы между «страницами» управляются JS в браузере (client-side routing)
  • Данные подгружаются через AJAX/fetch в виде JSON, без HTML с сервера
  • URL обновляется через History API (pushState)

Что передаётся с сервера:

  • Первый запрос: index.html, bundle.js, styles.css
  • Последующие запросы: только JSON-данные через API (REST / GraphQL)

Плюсы: быстрые переходы, десктоп-подобный UX
Минусы: плохой SEO «из коробки», долгая первая загрузка (TTI), весь JS грузится сразу


Как браузер использует кэш при загрузке страницы?

Типы кэширования:

  • Memory cache — самый быстрый, живёт до закрытия вкладки.
  • Disk cache — файлы сохраняются на диске.
  • Service Worker cache — программируемый кэш через Cache API.

Управление через HTTP-заголовки:

  • Cache-Control: max-age=31536000 — кэшировать на год.
  • ETag — сервер может вернуть 304 Not Modified, если ресурс не изменился.
  • Last-Modified — аналогично, по дате изменения.

Что такое WebAssembly (WASM)?

WebAssembly (WASM) — бинарный формат исполняемого кода для браузера, результат компиляции с C/C++/Rust и других языков.

Ключевые факты:

  • Работает почти с нативной скоростью
  • Выполняется в изолированной песочнице
  • Может взаимодействовать с JS через API
  • Поддерживается во всех современных браузерах
  • Figma, AutoCAD Web, Google Earth — используют WASM

Связь с SharedArrayBuffer: для многопоточного WASM используют SharedArrayBuffer + Atomics — разделяемая память между потоками. Требует заголовков на сервере:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

MutationObserver и IntersectionObserver

MutationObserver

Отслеживает изменения в DOM: добавление/удаление узлов, изменение атрибутов, изменение текста.

const observer = new MutationObserver((mutations) => {
  mutations.forEach(m => console.log(m.type, m.target));
});
 
observer.observe(element, {
  attributes: true,    // изменение атрибутов (в т.ч. style, class)
  childList: true,     // добавление/удаление детей
  subtree: true,       // включать всех потомков
  characterData: true  // изменение текстовых узлов
});

Можно ли отслеживать изменение стилей?

  • Да, если стиль меняется через element.style.color = 'red' — это меняет атрибут style, и { attributes: true } это поймает
  • Да, если меняется класс{ attributes: true } поймает изменение атрибута class
  • Нет, если нужны вычисленные стили (getComputedStyle) — MutationObserver их не отслеживает. CSS-переменные, медиа-запросы, анимации — за ними так не следить

IntersectionObserver

Отслеживает попадание элемента в область видимости (viewport или другой контейнер).

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.src = entry.target.dataset.src; // lazy load
    }
  });
}, { threshold: 0.5 }); // 50% элемента должно быть видно
 
observer.observe(img);

Применение: lazy loading, infinite scroll, анимации при скролле, трекинг показов.

MutationObserverIntersectionObserver
Что отслеживаетИзменения DOM (структура, атрибуты)Видимость элемента в viewport
ПрименениеРеакция на DOM-измененияLazy load, scroll-анимации

См. также