А поговорить я хочу сегодня про VirtualDOM.
Вот небольшой JS Bin с илююстрацией того о чем я вчера говорил про HTML-в-JS: https://t.co/30cEuWYd61
Код можно запустить и посмотреть в консоли (браузерной, не JS Bin'овской) что именно отдает рендер и как они комбинируются.
Главное что нужно понимать из этого примера:
-
Компоненты возвращают объект с описанием какого-то куска HTML.
-
Никакого HTML до того как вы вызываете ReactDOM.render нету.
-
ReactDOM.render берет объект который вы дали ему на вход, сравнивает с тем объектом который ему давали в прошлый раз и ищет разницу.
-
Если ничего не изменилось – в DOM ничего не идет.
-
Если что-то изменилось – создается патч, который минимальным количеством операций приводит DOM к новому состоянию.
Пока вы делаете все это в браузере и для SPA все хорошо и замечательно, но вот вам понадобилось сделать интернет-магазин.
И вы вспоминаете, а ведь Реакт-то умеет server side render! Давайте возьмем наши любимы компоненты и все Реакте напишем.
Пишете, рендерите, все работает, но есть один маааленкьий нюанс...
На странице интернет-магазина мало динамики. Возможно только счетчик товаров в корзине и попап с похожими товарами.
И вот тут оказывается, что если вы решили счетчик и попап сделать на Реакте, то вам придется на клиент тащить вообще все шаблоны страницы.
Да, даже если почти все шаблоны это dumb components и никогда не поменяются. Почему так?
Смотрим пример, видим один вызов ReactDOM.render и видим что ему на вход приходит корневая точка нашего дерева компонетов.
И чтобы получить diff страницы и сделать патч нам нужно иметь весь кусок дерева между кнопкой "Добавить в корзину" и счетчиком товаров.
Также с попапом, чтобы показать попап сразу внутри body нам нужно иметь все дерево шаблонов между body и кнопкой показа.
К сожалению это делает Реакт совершенно не пригодным для большого класса проектов: Интернет-магазинов, каталогов, справочников, etc.
Можно конечно генерить на выходе просто html, а динамику делать, простите, через jQuery. Но это какое-то извращение.
Все это, как мне кажется, из-за того что в реакте VirtualDOM, шаблоны и логика взаимодействия очень тесно вместе объединены.
Это упрощает работу с ними и упрощает создание SPA, но накладывает большие ограничения на возможности его серверного использования.
Производные от Реакта, такие как Riot или VueJS тоже этому подвержены. Web Components тоже требуют подгрузки кучи всего.
И как в рамках концепции Реакте сделать возможным использования похожих библиотек для классических сайтов мне не очень ясно.
В связи с этим вопос сегодняшний основной. Сталкивались ли вы с таким? Думали как решать? Может видели какие-то варианты решения?
Рендерить реакт можно не только в боди же.