Как да приложите рендиране от страна на сървъра във вашето приложение React в три прости стъпки

От Рохит Кумар

Ето какво ще изградим в този урок: хубава карта на React като тази.

В този урок ще използваме рендиране от страна на сървъра, за да доставим HTML отговор, когато потребител или робот удари URL адрес на страница. Ще обработим последните заявки от страна на клиента.

Защо ни трябва?

Позволете ми да ви насоча към отговора.

Каква е разликата между изобразяването от страна на клиента и изобразяването от страна на сървъра?

При визуализиране от страна на клиента браузърът ви изтегля минимална HTML страница. Той изобразява JavaScript и запълва съдържанието в него.

Рендерирането от страна на сървъра, от друга страна, изобразява React компонентите на сървъра. Резултатът е HTML съдържание.

Можете да комбинирате тези две, за да създадете изоморфно приложение.

Минуси от оказване на React на сървъра

  • SSR може да подобри производителността, ако приложението ви е малко. Но може и да влоши производителността, ако е тежка.
  • Това увеличава времето за реакция (и може да бъде по-лошо, ако сървърът е зает).
  • Това увеличава размера на отговора, което означава, че страницата отнема повече време за зареждане.
  • Това увеличава сложността на приложението.

Кога трябва да използвате визуализация от страна на сървъра?

Въпреки тези последици от SSR, има някои ситуации, в които можете и трябва да го използвате.

1. SEO

Всеки уебсайт иска да се появи в търсенията. Поправете ме, ако греша.

За съжаление, роботите на търсачките все още не разбират / изобразяват JavaScript.

Това означава, че те виждат празна страница, независимо колко полезен е вашият сайт.

Много хора казват, че роботът на Google вече показва JavaScript.

За да тествам това, внедрих приложението на Heroku. Ето какво видях в Google Search Console:

Празна страница.

Това беше най-голямата причина да изследвам визуализацията от страна на сървъра. Особено когато това е крайъгълна страница, като целева страница, блог и т.н.

За да проверите дали Google изобразява вашия сайт, посетете:

Табло за управление на Search Console> Обхождане> Извличане като Google. Въведете URL адреса на страницата или го оставете празно за началната страница.

Изберете FETCH AND RENDER. След като завършите, щракнете, за да видите резултата.

2. Подобряване на производителността

В SSR производителността на приложението зависи от ресурсите на сървъра и скоростта на мрежата на потребителя. Това го прави много полезен за сайтове с голямо съдържание.

Например , кажете, че имате мобилен телефон със средна цена с бавна скорост на интернет. Опитвате се да влезете в сайт, който изтегля 4MB данни, преди да можете да видите каквото и да било.

Бихте ли могли да видите нещо на екрана си в рамките на 2–4 секунди?

Бихте ли посетили този сайт отново?

Не мисля, че бихте го направили.

Друго голямо подобрение е времето за взаимодействие на първия потребител. Това е разликата във времето от това, когато потребителят удари URL адреса, до момента, в който види съдържание.

Ето сравнението. Тествах го на разработващ Mac.

Реагирайте на сървъра

Първото време за взаимодействие е 300ms. Хидратът завършва на 400ms. Събитието на натоварване излиза приблизително на 500ms. Можете да видите това, като проверите изображението по-горе.

Реагирайте, предоставено в браузъра на клиента

Първото време за взаимодействие е 400ms. Събитието на натоварване излиза на 470ms.

Резултатът говори сам за себе си. Има разлика от 100 ms във времето за взаимодействие на първия потребител за такова малко приложение.

Как работи? - (4 прости стъпки)

  • Създайте нов Redux Store при всяка заявка.
  • По желание изпратете някои действия.
  • Изтеглете състоянието от Магазина и извършете SSR.
  • Изпратете състоянието, получено в предишната стъпка, заедно с отговора.

Ще използваме състоянието, предадено в отговора, за създаване на първоначално състояние от страна на клиента.

Преди да започнете, клонирайте / изтеглете пълния пример от Github и го използвайте за справка.

Първи стъпки чрез настройване на нашето приложение

Първо отворете любимия си редактор и черупка. Създайте нова папка за вашето приложение. Да започваме.

npm init --yes

Попълнете подробностите. След като package.jsonбъде създаден, копирайте зависимостите и скриптовете по-долу в него.

Инсталирайте всички зависимости, като изпълните:

npm install

Трябва да конфигурирате Babel и webpack, за да работи нашият скрипт за изграждане.

Babel трансформира ESM и реагира в Node и код, разбираем от браузъра.

Създайте нов файл .babelrcи поставете реда отдолу в него.

{ "presets": ["@babel/env", "@babel/react"] } 

webpack обединява нашето приложение и неговите зависимости в един файл. Създайте друг файл webpack.config.js със следния код в него:

const path = require('path');module.exports = { entry: { client: './src/client.js', bundle: './src/bundle.js' }, output: { path: path.resolve(__dirname, 'assets'), filename: "[name].js" }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" } ] } }

Изходът на процеса на изграждане е два файла:

  1. assets/bundle.js — pure client side app.
  2. assets/client.js — client side companion for SSR.

The src/ folder contains the source code. The Babel compiled files go into views/. views directory will be created automatically if not present.

Why do we need to compile source files?

The reason is the syntax difference between ESM & CommonJS. While writing React and Redux, we heavily use import and export in all files.

Unfortunately, they don’t work in Node. Here comes Babel to rescue. The script below tells Babel to compile all files in the src directory and put the result in views.

"babel": "babel src -d views",

Now, Node can run them.

Copy Precoded & Static files

If you have already cloned the repository, copy from it. Otherwise download ssr-static.zip file from Dropbox. Extract it and keep these three folders inside your app directory. Here’s what they contain.

  1. React App and components resides in src/components.
  2. Redux files in src/redux/.
  3. assets/ & media/: Contain static files such as style.css and images.

Server Side

Create two new files named server.js and template.js inside the src/ folder.

1. src/server.js

Magic happens here. This is the code you’ve been searching for.

import React from 'react'; import { renderToString } from 'react-dom/server'; import { Provider } from 'react-redux'; import configureStore from './redux/configureStore'; import App from './components/app'; module.exports = function render(initialState) { // Model the initial state const store = configureStore(initialState); let content = renderToString(); const preloadedState = store.getState(); return { content, preloadedState }; };

Instead of rendering our app, we need to wrap it into a function and export it. The function accepts the initial state of the application.

Here’s how it works.

  1. Pass initialState to configureStore(). configureStore()returns a new Store instance. Hold it inside the store variable.
  2. Call renderToString() method, providing our App as input. It renders our app on the server and returns the HTML produced. Now, the variable content stores the HTML.
  3. Get the state out of Redux Store by calling getState() on store. Keep it in a variable preloadedState.
  4. Return the content and preloadedState. We will pass these to our template to get the final HTML page.

2. src/template.js

template.js exports a function. It takes title, state and content as input. It injects them into the template and returns the final HTML document.

To pass along the state, the template attaches state to window.__STATE__ inside a pt> tag.

Now you can read state on the client side by accessing window.__STATE__.

We also include the SSR companion assets/client.js client-side application in another script tag.

If you request the pure client version, it only puts assets/bundle.js inside the script tag.

The Client Side

The client side is pretty straightforward.

1. src/bundle.js

This is how you write the React and Redux Provider wrap. It is our pure client-side app. No tricks here.

import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; import configureStore from './redux/configureStore'; import App from './components/app'; const store = configureStore(); render(   , document.querySelector('#app') );

2. src/client.js

Looks familiar? Yeah, there is nothing special except window.__STATE__. All we need to do is grab the initial state from window.__STATE__ and pass it to our configureStore() function as the initial state.

Let’s take a look at our new client file:

import React from 'react'; import { hydrate } from 'react-dom'; import { Provider } from 'react-redux'; import configureStore from './redux/configureStore'; import App from './components/app'; const state = window.__STATE__; delete window.__STATE__; const store = configureStore(state); hydrate(   , document.querySelector('#app') );

Let’s review the changes:

  1. Replace render() with hydrate(). hydrate() is the same as render() but is used to hydrate elements rendered by ReactDOMServer. It ensures that the content is the same on the server and the client.
  2. Read the state from the global window object window.__STATE__. Store it in a variable and delete the window.__STATE__.
  3. Create a fresh store with state as initialState.

All done here.

Putting it all together

Index.js

This is the entry point of our application. It handles requests and templating.

It also declares an initialState variable. I have modelled it with data in the assets/data.json file. We will pass it to our ssr() function.

Note: While referencing a file that is inside src/ from a file outside src/ , use normal require() and replace src/ by views/. You know the reason (Babel compile).

Routing

  1. /: By default server-rendered homepage.
  2. /client: Pure client-side rendering example.
  3. /exit: Server stop button. Only available in development.

Build & Run

It’s time to build and run our application. We can do this with a single line of code.

npm run build && npm run start

Now, the application is running at //localhost:3000.

Ready to become a React Pro?

I am starting a new series from next Monday to get your React skills blazing, immediately.

Original text


Thank you for reading this.

If you like it and find it useful, follow me on Twitter & Webflow.