ReactJS рендеринг на стороне сервера против рендеринга на стороне клиента


120

Я только начал изучать ReactJS и обнаружил, что он дает вам 2 способа визуализации страниц: на стороне сервера и на стороне клиента. Но я не могу понять, как их использовать вместе. Это два разных способа создания приложения или их можно использовать вместе?

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


1
Короткий ответ: НЕТ - вы можете разделить, отправить статический html и полностью изменить его в клиентском рендере. Добавили подробности в свой ответ.
Kira

Ответы:


108

Для данного веб - сайта / веб-приложения, вы можете использовать либо реагировать на стороне клиента , на стороне сервера или обоих .

Сторона клиента

Здесь вы полностью запускаете ReactJS в браузере. Это простейшая установка, включающая большинство примеров (в том числе на http://reactjs.org ). Исходный HTML-код, отображаемый сервером, является заполнителем, и весь пользовательский интерфейс отображается в браузере после загрузки всех ваших скриптов.

Серверное

Думайте о ReactJS как о движке шаблонов на стороне сервера (например, jade, handlebars и т. Д.). HTML-код, отображаемый сервером, содержит пользовательский интерфейс в том виде, в каком он должен быть, и вам не нужно ждать загрузки каких-либо скриптов. Ваша страница может быть проиндексирована поисковой системой (если она не выполняет какой-либо javascript).

Поскольку пользовательский интерфейс отображается на сервере, ни один из ваших обработчиков событий не будет работать, и интерактивность отсутствует (у вас есть статическая страница).

Обе

Здесь первоначальный рендер находится на сервере. Следовательно, HTML, полученный браузером, имеет пользовательский интерфейс, каким он должен быть. После загрузки сценариев виртуальная модель DOM повторно визуализируется для настройки обработчиков событий ваших компонентов.

Здесь вам нужно убедиться, что вы повторно визуализируете тот же самый виртуальный DOM (корневой компонент ReactJS) с тем же, propsкоторый вы использовали для визуализации на сервере. В противном случае ReactJS будет жаловаться на несовпадение виртуальных DOM на стороне сервера и на стороне клиента.

Поскольку ReactJS различает виртуальные модели DOM между повторными рендерингами, реальная модель DOM не изменяется. Только обработчики событий привязаны к реальным элементам DOM.


1
Так что в случае «обоих» мне нужно дважды написать один и тот же код: один для серверного рендеринга, а второй - для воспроизведения этого DOM на клиенте? Не так ли?
Симча

10
Вам нужно запустить один и тот же код дважды. Один раз на сервере и один раз на клиенте. Однако вам необходимо написать свои компоненты, чтобы учесть это - например, вам не следует выполнять асинхронную выборку данных componentWillMount(), поскольку это будет запускать и клиент, и сервер. Вам также понадобится стратегия для получения данных заранее на сервере и предоставления их для первоначального рендеринга на клиенте, чтобы убедиться, что вы получаете тот же результат.
Джонни Бьюкенен

3
Вы также можете проверить, используется ли выполняемый код на стороне сервера или на стороне клиента, typeof window == "undefined"а затем соответственно получить свои данные.
Gautham Badhrinathan

У вас есть ссылка на пример, соответствующий вашей реализации?
Sawtaytoes

1
@IanW Обычно в этом случае HTML, возвращаемый сервером, очень "голый", он просто импортирует ваш JavaScript и стили и содержит объект, в <div>который React будет писать.
Мэтт Холланд

48

Источник изображения: инженерный блог Walmart Labs

SSR

КСО

NB: SSR (рендеринг на стороне сервера), CSR (рендеринг на стороне клиента).

Основное отличие состоит в том, что при использовании SSR ответ сервера клиентскому браузеру включает HTML-код страницы, которая должна отображаться. Также важно отметить, что хотя с SSR страница отображается быстрее. Страница не будет готова к взаимодействию с пользователем, пока файлы JS не будут загружены и браузер не выполнит React.

Одним из недостатков является то, что SSR TTFB (время до первого байта) может быть немного длиннее. Это понятно, потому что серверу требуется некоторое время для создания HTML-документа, что, в свою очередь, увеличивает размер ответа сервера.


4

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

Вам нужно будет писать свои компоненты с учетом обоих способов, таким образом, в основном помещая ifпереключатели повсюду, чтобы определить, находитесь ли вы на клиенте или на сервере, а затем выполнять либо запрос БД (или что-то подходящее на сервере), либо вызов REST (на сервере клиент). Затем вам нужно будет написать конечные точки, которые генерируют ваши данные и открывают их клиенту, и все готово.

И снова рад узнать о более чистом решении.


2

Это два разных способа создания приложения или их можно использовать вместе?

Их можно использовать вместе.

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

Лучше иметь тот же макет, чтобы избежать операций перекомпоновки и перерисовки, меньше мерцания / миганий, ваша страница будет более плавной. Однако это не ограничение. Вы могли бы очень хорошо кэшировать HTML-код SSR (что-то, что делает Electrode для сокращения времени отклика) / отправлять статический HTML-код, который перезаписывается CSR (рендеринг на стороне клиента).

Если вы только начинаете работать с SSR, я бы рекомендовал начать с простого, SSR может очень быстро стать очень сложным. Создание html на сервере означает потерю доступа к таким объектам, как окно, документ (они есть у вас на клиенте), потерю возможности включать асинхронные операции (из коробки) и, как правило, множество правок кода для обеспечения совместимости кода с SSR ( так как вам нужно будет использовать webpack для упаковки вашего bundle.js). Такие вещи, как импорт CSS, require vs import, внезапно начинают вас кусать (это не так в приложении React по умолчанию без веб-пакета).

Общая картина SSR выглядит так. Экспресс-сервер, обслуживающий запросы:

const app = Express();
const port = 8092;

// This is fired every time the server side receives a request
app.use(handleRender);
function handleRender(req, res) {
    const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
    console.log('fullUrl: ', fullUrl);
    console.log('req.url: ', req.url);

    // Create a new Redux store instance
    const store = createStore(reducerFn);

    const urlToRender = req.url;
    // Render the component to a string
    const html = renderToString(
        <Provider store={store}>
            <StaticRouter location={urlToRender} context={{}}>
                {routes}
            </StaticRouter>
        </Provider>
    );
    const helmet = Helmet.renderStatic();

    // Grab the initial state from our Redux store
    const preloadedState = store.getState();

    // Send the rendered page back to the client
    res.send(renderFullPage(helmet, html, preloadedState));
}

Мое предложение людям, начинающим с SSR, заключалось в предоставлении статического HTML. Вы можете получить статический HTML, запустив приложение CSR SPA:

document.getElementById('root').innerHTML

Не забывайте, что единственными причинами использования SSR должны быть:

  1. SEO
  2. Более быстрые загрузки (я бы сбрасывал со счетов это)

Взломать: https://medium.com/@gagan_goku/react-and-server-side-rendering-ssr-444d8c48abfc

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.