Из комментариев к статье стало понятно, что очень многие люди склоняются в сторону экосистемы Create React App (он же React Scripts). Это вполне разумно, т.к. это самый популярный и простой в использовании продукт (благодаря отсутствию конфигурации и поддержке ведущих людей React-сообщества), в котором, к тому же, есть почти все необходимое — сборка, режим разработки, тесты, статистика покрытия. Не хватает только серверного рендеринга. В качестве одного из способов в официальной документации предлагается либо вбивать начальные данные в шаблон либо воспользоваться статическими слепками. Первый подход не позволит поисковикам нормально индексировать статичный HTML, а второй — не поддерживает проброс никаких начальных данных, кроме HTML (фраза из документации: this doesn't pass down any state except what's contained in the markup). Поэтому если используется Redux, то придется для рендеринга использовать что-то другое. Я адаптировал пример из статьи для использования с Create React App, теперь он называется Create React Server и умеет запускать серверный рендеринг командой: При таком запуске никакой особой конфигурации не требуется, все делается через параметры командной строки. Если нужно — можно подсунуть так же свои шаблоны и обработчики. Небольшое лирическое отступление. Как говорят авторы React Router — их сайты индексируются Гуглом без проблем и без всякого серверного рендеринга. Может это и так. Но одной из главных проблем является не только Гугл, но и быстрая доставка контента юзеру, и это может даже поважнее индексации, которую можно обмануть. Для начала установим требующийся для этого примера пакеты: Пресет babel-preset-react-app ставится вместе с react-scripts, но для серверного рендеринга нам надо явно на него сослаться. Как и прежде, суть серверного рендеринга довольно проста: на сервере нам нужно определить на основе правил роутера, какой компонент будет показан на странице, выяснить, какие данные ему нужны для работы, запросить эти данные, отрендерить HTML, и выслать этот HTML вместе с данными на клиент. Сервер берет конечный компонент, вызывает у него getInitialProps, внутри которого можно сделать диспатч экшнов Redux'а и вернуть начальный набор props (на случай, если Redux не используется). Метод вызывается как на клиенте, так и на сервере, что позволяет сильно упростить начальную загрузку данных. Переменная initialError будет иметь значение, если в функции getInitialProps возникла ошибка, причем не важно где — на клиенте или на сервере, поведение одинаково. Страница, которая будет использоваться как заглушка для 404 ошибок должна иметь статическое свойство notFound: Функция createRoutes должна возвращать правила роутера, асинхронные роуты тоже поддерживаются, но для простоты это пока опустим: Функция createStore должна принимать начальное состояние в качестве параметра и возвращать новый Store: Когда функция вызывается на сервере, второй параметр будет иметь объекты Request и Response из NodeJS, можно вытащить некую информацию и вложить ее в начальное состояние. Соберем все воедино, а также добавим специальную обертку для получения initialProps с сервера: Добавим скрипты в секцию scripts файла package.json: И запустим Теперь если мы откроем http://localhost:3000 в браузере — мы увидим страницу, подготовленную на сервере. В этом режиме результат сборки сервера нигде не хранится и каждый раз вычисляется на лету. Если возможностей командной строки стало мало, или требуется хранить результаты сборки сервера, то всегда можно создать сервер не через CLI, а через API. Установим в дополнение к предыдущим пакетам babel-cli, он понадобится для сборки сервера: Добавим скрипты в секцию scripts файла package.json: Таким образом клиентская часть будет по-прежнему собираться Create React App (React Scripts), а серверная — с помощью Babel, который заберет все и src и положит в build-lib. Запустим: Теперь если мы снова откроем http://localhost:3000 в браузере — то мы опять увидим ту же страницу, подготовленную на сервере. Полный код примера можно посмотреть тут: https://github.com/kirill-konshin/react-router-redux-middleware/tree/master/examples/create-react-app. Principal Software Developer