3. Resumability vs Hydration
Resumability — это центральная концепция Qwik, которая принципиально отличает его от всех остальных фреймворков. Чтобы по-настоящему понять resumability, нужно детально разобраться с тем, как работает традиционная гидратация и почему Qwik предлагает принципиально другой подход.
Проблема с гидратацией в деталях
Заголовок раздела «Проблема с гидратацией в деталях»Что происходит при гидратации?
Заголовок раздела «Что происходит при гидратации?»Когда пользователь заходит на React/Vue/Angular сайт с SSR:
Фаза 1: Сервер рендерит HTML───────────────────────────────────────────────const html = renderToString(<App />)// Результат: <div id="root"><button>Count: 0</button></div>// Состояние потеряно! Сервер не знает что это Counter с value=0
Фаза 2: Браузер получает HTML (страница выглядит готовой)───────────────────────────────────────────────// Пользователь ВИДИТ кнопку, но она НЕ РАБОТАЕТ// onClick ещё не привязан!
Фаза 3: Браузер загружает JS (200-500 КБ)───────────────────────────────────────────────<script src="/bundle.js"></script> // Весь код приложения!
Фаза 4: React гидратирует (воссоздаёт то, что уже сделал сервер)───────────────────────────────────────────────ReactDOM.hydrateRoot(document, <App />)// React обходит ВСЁ дерево компонентов заново// Это избыточная работа — HTML уже есть!
Фаза 5: Страница становится интерактивной ✅Ключевая проблема: браузер проделывает работу, которую уже сделал сервер. Это называется «дублирование работы».
Почему нельзя просто не делать гидратацию?
Заголовок раздела «Почему нельзя просто не делать гидратацию?»Без гидратации браузер не знает:
- Какие функции привязаны к каким DOM-элементам
- Какое состояние у компонентов
- Какие компоненты существуют и где они начинаются/заканчиваются
React не может передать эту информацию в HTML, потому что функции JavaScript не сериализуемы.
Решение Qwik: Resumability
Заголовок раздела «Решение Qwik: Resumability»Идея сериализации состояния
Заголовок раздела «Идея сериализации состояния»Qwik решает проблему, сохраняя все необходимые данные прямо в HTML:
<!-- Обычный React SSR HTML --><div id="root"> <button>Count: 0</button></div><!-- Обработчик события потерян! -->
<!-- Qwik SSR HTML --><div> <button on:click="./chunk-abc.js#Counter_button_onClick_0BkQ6" q:id="1"> Count: 0 </button></div>
<!-- Сериализованное состояние --><script type="qwik/json">{ "objs": [0, "#1"], "subs": [["3 #1 count 0"]]}</script>Что именно сериализует Qwik?
Заголовок раздела «Что именно сериализует Qwik?»1. Ссылки на обработчики событий (как URL на чанки) on:click="./chunk-abc.js#handler_name"
2. Состояние компонентов (через useSignal/useStore) <script type="qwik/json">{...}</script>
3. Дерево компонентов (через q:id атрибуты) q:id="0", q:id="1", q:id="2"...
4. Связи между состоянием и DOM Какой сигнал управляет каким элементомПроцесс Resumability
Заголовок раздела «Процесс Resumability»Фаза 1: Сервер рендерит HTML + сериализует состояние───────────────────────────────────────────────────HTML + <script type="qwik/json"> = полное описание приложения
Фаза 2: Браузер получает HTML───────────────────────────────────────────────────✅ Страница СРАЗУ интерактивна!Qwik регистрирует один глобальный обработчик событий.
Фаза 3: Пользователь кликает кнопку───────────────────────────────────────────────────Qwik runtime (~1 КБ) перехватывает событие.Читает URL обработчика из on:click атрибута.Загружает нужный чанк (только этот обработчик!).Десериализует состояние из qwik/json.Выполняет обработчик.Обновляет только нужные DOM-узлы.Ленивая загрузка с QRL
Заголовок раздела «Ленивая загрузка с QRL»QRL (Qwik Resource Locator) — это URL-ссылка на функцию вместо самой функции:
// React — функция передаётся напрямую (не сериализуемо)<button onClick={() => { // Весь этот код в начальном бандле const result = heavyComputation(); setState(result);}}> Click</button>
// Qwik — функция преобразуется в QRL (URL)<button onClick$={() => { // Этот код в ОТДЕЛЬНОМ чанке // Загружается только при клике! const result = heavyComputation(); state.value = result;}}> Click</button>Символ $ в Qwik — это магический суффикс, который говорит оптимизатору: «вынеси эту функцию в отдельный чанк».
Сравнение поведения при взаимодействии
Заголовок раздела «Сравнение поведения при взаимодействии»React: пользователь кликает кнопку┌─ Все обработчики уже загружены (гидратация) ─┐│ handler уже в памяти → выполняется сразу ││ Но: 2-5 секунд ожидания ДО этого момента │└──────────────────────────────────────────────┘
Qwik: пользователь кликает кнопку┌─ Обработчик загружается лениво ──────────────┐│ 1. Перехват события (~0 мс) ││ 2. Загрузка чанка (~50-100 мс) ││ 3. Выполнение (~1 мс) ││ Но: страница интерактивна СРАЗУ │└──────────────────────────────────────────────┘