Комментарии 18

Метод hydrate учитывает, что данные для рендера могут подгружаться асинхронно? С этим будет из коробки работать Redux?

Эту логику вы должны реализовать на сервере, прежде чем вызывать метод renderToString или renderToNodeStream — загружаете нужные данные согласно текущему url, формируете из них store и уже все это готовое отдаете в компонент Provider, который затем рендерите через renderToString или renderToNodeStream.

Понятно. prerender.io по прежнему в фаворитах. Он готовит страницу как браузер и может передавать её nginx прокси например для кеширования.


Это избавляет от жонглирования датастором и решает проблемы индексации. Google кстати в нём не нуждается и сам исполняет JS о чём prerender.io знает и ему лишний трафик не отдаёт.


Иначе двойной трафик получается. Вёрстку загрузи с датастором, потом бандл загрузи, датастор снова загрузи. И всё это время вместо favicon — кругляш загрузки.


Конечно время до показа первого экрана важная метрика, но велика плата за неё в виде дополнительного трафика который по сути не нужен клиенту.

Зачем двойной трафик? Если вы используете редакс — нужно загрузить все данные на сервере, потом отправить заполненный стор на клиент (как часть HTML-страницы). Затем, на клиенте, можно легко проверить, что данные уже есть в сторе и ничего не загружать

Ок. Из api можно и правда дважды не грузить. Дважды загрузится только вёрстка. Вернее результат и бандл по которому он построен. Возможно это совсем крохотная разница, а излишки вёрстки в виде датастора в конце страницы можно удалять после его восстановления в redux. А может так статься, что вёрстка превысит размеры бандла, тогда это всё будет иметь смысл только на крайне медленных девайсах, на которых время JS рендера страницы критично.


Моя позиция связана скорее с той болью которая возникает когда приходится постоянно перезагружать дев сервер из-за застрявшего в серверном рендере чего-то и попутно следить, чтобы на сервере загрузились все данные из десятка методов API, а потом решать экзотические проблемы возникающие из-за того, что у тебя серверный рендер вообще есть, тем более дебажится он не так просто (я знаю про --inspect, но не панацея).


В общем мы были рады переходу на prerender.io, вдоволь налюбившись с рендером на сервере.


Идея рендера на сервере мне импонирует, но мне кажется она далека от своего завершения. Вместо того чтобы плеваться целиком страницей, стоит выделять важные части за которыми пришёл пользователь.


Я думаю врятли ему интересен в первую очередь хедер и подвал, а пришёл он скорее за конкретным контентом, будь то список товаров или статья. Так показав ему основной контент можно дальше загружать всё остальное. На это время пользователь занят поглощением контента за которым пришёл.


Вопросом магии и ловкости рук остаётся положение контента на странице, чтобы он не скаканул и не изменился после загрузки. А также особое меню для тех у кого отключен JS. Но это совсем другая история.


Зато мы получаем настоящую доступность и сокращение трафика даже для тех девайсов которые будут читать HTML в чистом виде. Ведь ради доступности всё, да?


                                Всем любви

Простите, но prepender.io — это просто генератор статики. Если у вас простой кейз в виде статичных страниц, то может вам и не нужен серверный рендеринг? Вы сами можете в CI или руками генерить когда захотите и что захотите.

P.S. разметка заранее сгенерированной странички занимает столько же места, сколько разметка, выплюнутая серверным рендером. Подскажите пожалуйста, где здесь дополнительный трафик в случае SSR?
‣ SSR включен

index.html 1Mb
+bundle.js 1Mb


‣ CSR (SSR выключен)

index.html 10 kb
+bundle.js 1 Mb


Prerender.io следит за клиентом, и если рендер ему не нужен отдаёт только коротенький index.html и несколько js/css файлов для самостоятельного рендера на клиенте.


Возможно я чего то не понимаю и у вас есть LiveView на которых от рендера на сервере количество трафика не увеличилось, а скорость загрузки и работы сайта возросла.


Я бы посмотрел

У нас сейчас два параллельно развивающихся проекта на SSR, и в обоих рендерится только то, что нужно (включая критический css). Статическая генерация (если бы она нам подошла, но не подходит из-за высокой динамики контента) никак не помогла бы выиграть в объёме.

Расскажите, в чём причина разных объёмов для index.html в вашем случае?

В моём случае серверный рендер прибавляет к весу страницы вёрстку. Эти +400кб прилетели конечно почти мгновенно, но похоже было больше на бутафорию.


Не всё жмётся (кликается) и не всё отображено так как должно быть (некоторые штуки хотят window. Так сложилось).


А потом прилетели 512кб ДжаваСкрипта и всё встало на свои места, но осадочек остался.


Я понимаю это мой частный случай и в ином пришлось бы ждать нескольких мегабайт скриптов, но это ещё более оттянуло бы момент нормальной работы кнопок.


И вот вся эта бутафория стоит батхерта синхронизации стора? Мне кажется штука крутая конечно, но требует доработки. В первую очередь Promise Midleware, а во вторых акцента на <main></main> / <article></article> секциях.


Нужно быть готовым к тому, что исходник будут читать читалки, боты или программисты c собакой, которые знают где ты живёшь, в терминале через cat.
Не всё жмётся (кликается) и не всё отображено так как должно быть (некоторые штуки хотят window. Так сложилось).
То есть у вас неконсистентность рендеринга между клиентом и сервером из-за неправильной реализации или технического долга.

И вот вся эта бутафория стоит батхерта синхронизации стора? Мне кажется штука крутая конечно, но требует доработки. В первую очередь Promise Midleware, а во вторых акцента на
main / article секциях.
Не очень понял, что вы имеете ввиду про main/article. А про доработку: вам наверно подойдёт redux-saga вместе с redux-wait-for-action.

И я по-прежнему не понял, почему у вас отличается размер, и что же такого добавляет серверный рендер по сравнению со статической генерацией. Зачем отправлять лишнее, если это не нужно. Возможно проблема опять же из-за неправильной реализации? Ну тогда нет никакого смысла грешить на другие библиотеки.

Вы всё правильно не поняли. Разницы нет в размере между статической генерацией и рендером на сервере. Разница с генерацией разметки на клиенте.


redux-wait-for-action

thx

В случае наличия сзади сервера на Node.JS, Вы можете отдавать favicon и критический css сразу, а остальное подгружать постепенно через метод renderToNodeStream. Никакого двойного трафика и двойных походов к API не нужно, initial state для Вашего store Вы можете загрузить на сервере, отрендерить контент, а затем сохранить store внутри какого-нибудь window.__initialState__, после чего уже забрать это состояние на клиенте.

Погорячился с двойными походами на API. Но вёрстку таки дважды загрузить придётся (+1 раз в качестве внутренностей bundle.js).


А favicon какой не отдавай, все равно такой будет пока бандлы грузятся.


window.initialState мы конечно сохраняли. И данные на сервере загружали. Но это сопряжено с временными затратами. После ещё одного потерянного дня на отлов багов серверного рендера, которые сложнее дебажить, мы перешли на prerender.io и довольны.


Возможно мы опять вернёмся к рендеру на сервере, но когда прогресс пройдётся кремниевыми сапогами по этому раздолью для деятельности. И он идёт, прогресс этот. Шаг ему на встречу React 16 и эта статья. Я верю в то, что сейчас является примером рутины через некоторое время сократится до единого флага в настройках.

А почему вам не подошёл изначально любой генератор статики?

Мне нравится, как это реализовано в ASP.NET Core: все фетчи, от которых зависит рендер страницы, добавляются с помощью addTask в общий список, и, по завершении выполнения всех записанных задач выполняется повторный рендеринг в строку и сохранение стора (и других сторонних переменных, если нужно).
Правда, чтобы работали методы, требующие авторизации, необходимо пробрасывать куки из запроса в фетч, использующийся при серверрендеринге, но зато благодаря этому полностью переиспользуется клиентский код, не надо думать о том, что надо запихнуть в стор.

Хотелось бы ссылку на статью описывающую эту функциональность ASP Core. Может знаете потолковей? Так на лету я не понял о чем речь, а о Core хочется знать поболее. Фетч это видимо Fetch api, но далее уже не понятно: «от которых зависит рендерер »… Фетч в броузере, рендерер Core (razor?) сервер сайд, что общего? И как может не зависить рендерер от фетчей (кто и как определяет)?

К сожалению, ничего толковее https://github.com/aspnet/JavaScriptServices/blob/dev/README.md и шаблонного примера не знаю. Хоть самому писать :)


Имеются ввиду фетчи, загружающие данные для отрисовки страницы. Если просто использовать renderToString, то везде зарендерится, что данные загружаются, и всё. Обычно, чтобы такого не было, в стор принудительно заливают нужные данные. SpaServices же предлагает все такие фетчи в клиентском коде сохранить в отдельный список с помощью функции addTask, и, во время сервер-рендеринга, по выполнении всех этих фетчей renderToString выполняется повторно. Благодаря тому, что стор уже заполнен фетчами, второй вызов рендера уже генерирует страницу с данными. При этом, фактически, никакого специального серверного кода для подстановки данных писать не надо, просто надо не забывать кидать в общий список нужные фетчи.


Более того, с помощью пары обходных манёвров, таким же образом можно рендерить и данные, требующие авторизации (этого стандартный шаблон, к сожалению, не показывает).

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.
Информация
Дата основания

27 августа 2015

Местоположение

Россия

Сайт

ruvds.com

Численность

11–30 человек

Дата регистрации

18 марта 2016

Блог на Хабре