Веб-разработка

DOM и браузерные API

2004 год. Google Maps запускается. Весь картографический рынок в шоке: карты двигаются без перезагрузки страницы. Под капотом - XMLHttpRequest и интенсивные DOM манипуляции. Этот момент определил архитектуру веба на следующие 20 лет.

  • **React Virtual DOM:** абстракция над DOM API, batch updates и minimal reflows - причина популярности. React DOM diffing экономит 10-100x reflow операций на сложных UI
  • **Service Workers + Cache API:** Progressive Web Apps кэшируют fetch-запросы для offline работы. Twitter Lite работает при скорости 2G через aggressive caching
  • **ResizeObserver, IntersectionObserver:** современные браузерные API без polling. Infinite scroll, lazy loading изображений, responsive компоненты - без setTimeout интервалов

Исторический контекст

В 1998 году Алекс Хопманн из Microsoft разработал XMLHttpRequest как ActiveX компонент для Outlook Web Access - первого корпоративного webmail. Mozilla реализовала нативный XHR в 2002. Google использовала XHR в Gmail (2004) и Google Maps (2005). Этот паттерн назвали AJAX (Asynchronous JavaScript and XML) - термин предложен Джесси Джеймс Гарретом в 2005. Fetch API появился в 2015 как современная замена XHR. DOM Level 1 стандартизован W3C в 1998, Virtual DOM изобретён командой React в 2013.

DOM: структура, парсинг и layout reflow

**2004 год. Gmail запускается. Для 2004-го это шок: веб-приложение которое работает как десктопное - без перезагрузки страницы.** Секрет - JavaScript манипуляция DOM (Document Object Model). DOM - дерево объектов, представляющих HTML. Браузер парсит HTML в DOM tree, применяет CSS (CSSOM), объединяет в Render Tree, вычисляет layout (размеры и позиции) и рисует (paint). Любая манипуляция DOM потенциально запускает этот цикл заново.

**Critical Rendering Path:** HTML -> DOM -> CSSOM -> Render Tree -> Layout -> Paint -> Composite. JavaScript блокирует парсинг HTML (если нет defer/async). Изменение `width` или `display` запускает Layout (дорого). Изменение `color` или `opacity` - только Paint (дешевле). Изменение `transform` или `opacity` через CSS animation - только Composite (дёшево, GPU-accelerated).

Какой CSS property выгоднее анимировать для плавности: `left/top` или `transform: translate()`?

Events: bubbling, capturing и делегирование

**Event propagation в DOM - одна из самых частых причин багов у начинающих.** Когда кликаешь на кнопку внутри div - событие распространяется в двух фазах: capturing (от window вниз к цели) и bubbling (от цели вверх к window). addEventListener принимает третий параметр: `true` = capturing фаза, `false` (default) = bubbling. Это позволяет перехватывать события на родительских элементах - Event Delegation.

**Memory leaks через event listeners:** если DOM-элемент удаляется но listener остаётся - утечка памяти. Решение: removeEventListener при удалении элемента или использование AbortController. В React/Vue это автоматически - framework управляет lifecycle.

Список из 10 000 элементов. Какой подход к event handling правильный?

Fetch API и async/await: HTTP-запросы в браузере

**XMLHttpRequest (XHR) - API 1999 года, придуманный командой Microsoft для Outlook Web Access.** Callback hell из вложенных обработчиков. Fetch API (2015) заменил XHR: Promise-based, чистый синтаксис, поддержка async/await. С 2022: встроен в Node.js. Fetch - стандарт для браузерных HTTP запросов.

**CORS (Cross-Origin Resource Sharing):** браузер блокирует fetch к другому origin (домен, порт, протокол). Сервер должен вернуть заголовок `Access-Control-Allow-Origin: *` или конкретный origin. Preflight: браузер сначала отправляет OPTIONS запрос для 'unsafe' методов (DELETE, PUT) и custom headers. CORS - браузерная защита, не серверная: curl игнорирует его.

Fetch возвращает Response с status 404. Попадёт ли выполнение в catch блока?

Браузерное хранилище: cookies, localStorage, IndexedDB

**2009 год. HTML5 Web Storage API.** До этого единственный способ хранить данные в браузере - cookies (4 KB, отправляются с каждым запросом). localStorage/sessionStorage: 5-10 MB, синхронные, только строки. IndexedDB: гигабайты, асинхронный, structured data. Cache API (Service Workers): кэш сетевых ответов для offline.

StorageЛимитАсинхронныйОтправляется с запросамиИспользование
cookie4 KBНетДаAuth tokens, tracking (HttpOnly)
localStorage5-10 MBНетНетUser preferences, app state
sessionStorage5-10 MBНетНетВременные данные формы
IndexedDB~1 GB+ДаНетOffline data, файлы, кэш
Cache APIГибкоДаНетService Worker, offline стратегии

localStorage безопасен для хранения токенов потому что нельзя прочитать из другого домена

localStorage изолирован по origin (Same-Origin Policy), но уязвим к XSS атакам: любой JS-код на странице (включая вредоносный из CDN или через XSS) читает localStorage.

XSS (Cross-Site Scripting) - одна из топ-5 уязвимостей OWASP. Если в приложении есть XSS, атакующий выполняет `document.cookie` (без HttpOnly) или `localStorage.getItem('token')`. HttpOnly cookie недоступен для JavaScript - это ключевое отличие. Для production: refresh token в HttpOnly cookie + SameSite=Strict.

Нужно сохранить JWT access token (короткоживущий) и refresh token (долгоживущий) в браузере. Где хранить каждый?

DOM и браузерные API: главное

  • DOM manipulation: batch updates через DocumentFragment или innerHTML. Каждый отдельный insert запускает reflow
  • Event bubbling: события всплывают от target к document. Event Delegation - один listener на родителе вместо N на детях
  • Fetch: Promise-based HTTP. Не кидает ошибку при 4xx/5xx - проверять response.ok явно. AbortController для timeout
  • Storage: localStorage (5MB, синхронный) vs IndexedDB (гигабайты, асинхронный). JWT в HttpOnly cookie, не localStorage
  • CSS animation через transform/opacity - GPU composite. left/top - Layout reflow - janky animations

Вопросы для размышления

  • React использует Virtual DOM для оптимизации DOM манипуляций. Но инициализация React занимает 200-400 КБ JS и дополнительное время parse/execution. Когда прямые DOM манипуляции без фреймворка будут быстрее чем React?

Связанные уроки

  • web-03
  • web-05
  • bt-04-dns-tls
  • mob-04
  • devops-04
  • comp-01-intro
DOM и браузерные API

0

1

Войти