В начале мая, Misko Hevery, создатель фреймворка Angular, объявил о своем уходе из Google и команды Angular - в компанию builder.io. Всего через полтора месяца, на его странице в dev.to, появился Анонс нового фреймворка - Qwik. Я решил разобраться, что он из себя представляет и зачем нужен. Qwik сейчас на стадии proof of concept, доков очень мало и нет соответствующей инфраструктуры, и даже неясно, выстрелит он или нет, но уже понятны основные идеи, и можно потрогать код. Давайте разберемся, что интересного он нам принесет, и придется ли нам учить новый фреймворк (спойлер: пока рановато). Основная задача Qwik, - как можно догадаться из названия, - быть очень быстрым ​!  Дело в том, что с мая этого года, Google начал учитывать производительность приложения при поисковой выдаче. В частности, оценка считается с помощью набор метрик Web Vitals. Большинство современных фреймворков могут, с помощью Server Side Rendering, получить быстрые First Contentful Paint и большинство других метрик, однако одна метрика им пока не покоряется - Time to interactive. Все дело в том, что после отправки HTML сгенерированного на сервере, необходимо также загрузить фреймворк и код приложения, запустить его, и только после этого можно обрабатывать события. Эту проблему и пытается решить Qwik. Qwik позволяет написать код который будет переиспользован на сервере и на клиенте, при этом на клиент код будет подгружаться непосредственно перед выполнением. Работает это вот так: При первом рендере, сервер сериализует все данные в атрибуты HTML узлов Затем подгружается маленький (0.5 кб, 1ms запуск) загрузчик Qwik, который подписывается на все события. Все обработчики событий хранят в себе только текстовую ссылку на файл с обработчиком, никакого кода. Сам код подгружается только по мере необходимости, например когда пользователь запускает событие. Если клиенту нужен доступ к состоянию используемому на сервере,  его можно получить из DOM дерева. На данный момент - да. В будущем это можно будет оптимизировать, - например, подгружать обработчики кликов при наведении мыши, или загружать заранее наиболее используемые обработчики (как guess.js) Метрика Time to interactive названа не очень удачно, на самом деле она меряет время последней задачи которая заняла более 50 миллисекунд.  Чтобы понять, насколько она важна, можно глянуть на калькулятор и посмотреть, как именно эта метрика влияет на конечную оценку.  Хотя вес в оценке всего 10%, можно предположить, что остальные метрики будут легко доводиться до максимальных значений с помощью обычного SSR и, в этом случае, именно Time to interactive может позволить получить преимущество. Решение такой проблемы, будет наиболее востребовано в интернет магазинах и в коммерческих сайтах, особенно учитывая что у крупнейших игроков рынка результат сейчас в пределах 20-70 из 100.  Свой сайт в можете проверить тут, а Habr.com  получил оценку 29. Про остальные метрики Web Vitals можно прочитать тут.  На данный момент, архитектура других фреймворков, не позволяет им реагировать на события без инициализации фреймворка и приложения на клиенте.  Возможно в будущем, после добавления соответствующих архитектурных изменений, подобная функциональность появится и у других фреймворков.  Мишко даже выступал на эту тему несколько лет назад по отношению к Angular, но отметил, что он просто размышляет и конкретных планов на имплементацию на тот момент не было. Qwik - не первый фреймворк, который пытается победить Time to Interactive. Например есть Markojs.com - от Ebay, который пытался решить эту задачу другим способом, но его создатель покинул проект, и сейчас в core team лишь пара человек, которые сфокусированы на поддержке внутри компании. Кстати, один из core разработчиков Marko теперь помогает с Qwik.  Также есть Astro.js, но они пытаются решить эту проблему не на уровне обработчиков событий, а на уровне кусков приложения (islands) Фреймворк решили назвать Qwik,  по аналогии со словом скорость (quick), как по мне - название не очень удобное:  Плохо гуглится, т.к. Есть несколько компаний с похожим названием Github адрес занят (monorepo лежит в организации builder.io), та же фигня с npm. Изначально фреймворк хотели называть qoot, но потом переименовали. Разработчики выложили TODO приложение, в котором можно покопаться  и оценить часть архитектурных решений, глянуть можно в StackBlitz, (ура, отличная возможность потестить новые Web Containers) или на Github.  Весь код, и клиента и сервера, лежит в одном месте и переиспользуется, давайте посмотрим на компонент заголовка - Header: Первое что бросается в глаза - JSX (что забавно видеть от создателя Angular), с одной стороны это хорошо, потому что синтаксис многим знаком, с другой стороны, это может усложнить жизнь разработчика фреймворка. Скорее всего, по мере развития, когда понадобится дополнительная гибкость, им придется писать свой собственный трансформатор. (Так же см. новую статью @nin-jin про шаблоны, где он ругает JSX) В каждом шаблоне обязательно присутствует такой код:  Но он уйдет, когда разработчики начнут использовать новый JSX transform Также разработчики не забывают про директивы (как в Angular), например в коде есть такой TODO Все обработчики событий лежат в своих собственных файлах, и при добавления событий используется ссылка на этот файл#имя функции: Подробно про формат этой  сложнющей штуки можно прочесть тут, а пока давайте разберем что мы видим:  QRL - Специальный Template Literal Tag, используемый для всех ссылок ui:/ - Namespace, может быть задан пользователем, или прийти из либы, наприме qwik:/ для методов фрейворка. /Header_addTodo - путь к файлу где лежит обаботчик #addTodo - имя функции, которую нудно запустить ?value= - Как и в обычной ссылке можно передать какие-то параметры (query params) .target.value - значение инпута, относительно Event Сам код обработчика выглядит так, и использует внедрение зависимостей: Dependency Injection в Qwik используется повсеместно (привет из Angular) Есть несколько методов позволяющих внедрить зависимости, например:  InjectFunction - Помимо основных зависимостей позволяет получить доступ к параметрам переданным по ссылке (?value=.target.valueв примере выше), для этого можно использовать токен provideQrlExp<string>('value'). injectMethod - (как раз в примере выше) то же самое, только дополнительно внедряет контекст функции (this), это позволяет  функциям лежать в отдельных файлах, но при этом вести себя будто они часть класса. InjectEventListener - то же самое, плюс доступ к значению Event события Подробнее можно посмотреть в коде. Чтобы переиспользовать код, между клиентом и сервером, Qwik использует умную систему сущностей (Enitity): Каждая сущность, уходящая с севера (например TodoListEntity, или TodoItemEntity) привязана к DOM узлу. Её состояние сериализуется и сохраняется в атрибуте этого узла, привязанном к ID сущности. Это позволяет восстановить на клиенте сущность, которая была сгенерирована на сервере. Интересно сделано Change Detection: при изменении данных необходимо вызвать функцию  markDirty (прямо как в Angular Ivy), передав туда DOM элемент, Entity или компонент. Функция найдет все затронутые DOM узлы, добавит им атрибут on:q-render и запланирует change detection cycle через requestAnimationFrame . Во время change detection cycle , узлы, которые нужно обновить, будут получены с помощью простого querySelectorAll('[on:q-render]') Так как все сущности привязаны к DOM, мы можем пометить сущность как измененную и все соотвествующие DOM  элементы также обновятся Передача значений детям: Передавать значения, как и в большинстве фреймворков, можно  через свойства: А получать в обработчике через DI: Получение значений от детей В примере ниже, мы используем функцию emitEvent из Qwik, которая позволяет отправить событие open родительскому компоненту. Родительский компонент может слушать on:open и запустить соответствующий обработчик Проект находится в очень ранней стадии, v1 за горами, так что на настоящем проекте использовать это не рекомендуется никому:  Документация минимальная, хотя код неплохо прокоментирован Поддержки IDE нет, а тут она явно нужна (можно глянуть, как подсветка синтаксиса сломана в примерах, в этой статье) Не работает в Firefox  Не используется нигде  Angular поддерживается Google,  React поддерживается Facebook, но даже большая компания   не позволяет на 100% предсказать судьбу проекта, достаточно глянуть на flow или killedbygoogle Qwik поддерживается компанией Builder.io, они основаны в 2017 и у них на гитхабе есть несколько небольших проектов, которые они успешно поддерживают сохраняя количество Issues в разумных пределах, например jsx-lite или builder,  Смогут ли они справиться с большим проектом, если Qwik выстрелит - покажет время.   Резонный вопрос, видимо пока применения тут не нашлось. Вся документация тут, а Мишко обещал целый цикл статей в своем блоге, можно также зайти в Discord проекта, задать вопросы и может быть даже чем-то помочь. В этой статье мы рассмотрели идеи, предложенные разработчиками Qwik.  К API и к некоторым техническим решениям есть много вопросов, да и учить новый фреймворк пока рано, а вот задуматься над идеями и перестроить свою ментальную модель - самое время. Эта статья была написано публично на моем стриме, там можно глянуть весь процесс, и много интересных деталей, не вошедших в эту статью. Я также хочу выразить благодарность ​ всем, кто участвовал в написании, подсказывал и задавал вопросы, ну и большое спасибо всем, кто дочитал это до конца!