Skip to content

Latest commit

 

History

History

peter-chang-break-down-isomorphic-and-universal-boilerplate-react-redux-server-rendering

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

Укрощаем изоморфный и универсальный шаблон: серверный рендеринг на React-Redux

Перевод статьи Peter Chang: Break Down Isomorphic and Universal Boilerplate: React-Redux server rendering.

Серверный рендеринг с помощью React Redux

Серверный рендеринг с помощью React Redux

Ищите шаблон на React-Redux? Если да, то вряд ли у вас проблемы с поиском. Потому что вы нашли ТОННЫ шаблонов. Andrew Farmer

Вам также может понравиться


С момента релиза React и Redux я находился на седьмом небе от счастья потому что 1) Изоморфность React даёт преимущества к скорости загрузки и SEO при серверном рендеренге и позволяет рендерить компоненты на клиенте уже после загрузки страницы и 2) Идеи Flux-архитектуры расширяют компоненты React с помощью использования однонаправленного потока данных.

Однако, после анализа тысячи шаблонов, мне пришлось выпить не одну чашку чая, чтобы успокоиться. Потому что ни один из шаблонов не оказался простым в освоении. Так что мне пришлось изучать разработку шаблонов с нуля. Эта статья представляет собой заметку, где я пояснил, как разбить шаблон на понятные части шаг за шагом. В конце концов, я выделил пять пунктов и они являются причиной такого большого разнообразия изоморфных шаблонов:

  1. Dev-сервер и сборка проекта

Настройка и создание среды разработки для решения таких проблем, как горячее обновление (HMR), слежение за изменением файлов, сборка бандлов и так далее. Популярные инструменты для этого: webpack, gulp, nodenpm, broserify, grunt.

  1. React-Redux-компоненты и поток данных

  2. Роутинг

Чтобы решить, какую иерархию роутинга использовать, нужно ответить на вопросы: это SPA? Должен ли сервер иметь CORS? Может быть стоит запускать приложение внутри express-сервера, а не на клиенте?

  1. Общие редюсеры/ создатели экшенов

Зависит от роутинга

  1. Тесты

Пока будем говорить о втором пункте, потому что он является неизменным от шаблона к шаблону. Остальные пункты меняются в зависимости от предпочтений разработчиков. SSR, общие компоненты и Redux модули — это ядро изоморфной flux-архитектуры - причина того, почему в каждом шаблоне используются пакеты react, redux и react-redux.

Склонируйте из репозитория helloWorld-пример на React-Redux. Мы будем разбивать его на части, чтобы понять, как работает каждый файл:

Серверный рендеринг с помощью React Redux

Серверный рендеринг с помощью React Redux

Выше представлена структура работы приложения. Приложение использует Express, который работает только с одним роутом, отображая с помощью функции res.sendFile index.html в браузере. Особое внимание следует уделить части, обведенной голубым контуром. Там показано взаимодействие React, Redux, корневого компонента, стора и редюсера.

React-Redux-структура данных, стора, пропсов, стейта и компонентов

React-Redux-структура данных, стора, пропсов, стейта и компонентов

Это пример, предоставленный официальной документацией, Facebook даёт некоторые советы по организации иерархии компонентов: использование «умных» и «глупых» компонентов, использование connect() вместо store.subscribe() и так далее.

index.js — это вершина иерархии, корневой компонент, содержащий в себе все остальные компоненты в виде виртуального DOM, также это единственный компонент, использующий большое число зависимостей. Помимо этого, другие компоненты также включают в себя сторонние зависимости, обеспечивающие чистоту кода.

До сих пор я чувствую, как много Facebook сделал для нас, разработчиков.

Ниже расположены функции, играющие ключевую роль в React-Redux-компонентах:

Provider

Этот компонент волшебным образом делает стор доступным сразу во всех умных компонентах, не передавая его явно напрямую.

import { Provider } from 'react-redux'
let store = createStore(todoApp)
render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

connect(...)

Подключает React-компонент к Redux, позволяя компоненту использовать стор верхнего уровня. При этом отпадает необходимость получать стор в виде пропсов от родителя. (взято отсюда).

Условно работу connect(...) можно разбить на следующие стадии:

  1. Передача стора внутрь корневого компонента

Чтобы начать подключать компоненты, нужно обернуть корневой компонент в Provider и передать в него переменную store:

  import helloReducer from './reducers'
  import { Provider } from 'react-redux'
  import { createStore } from 'redux'
  let store = createStore(helloReducer)
  render(
   <Provider store={store}>
      <App />
   </Provider>,
   document.getElementById('root')
)
  1. Подключение стора к умным компонентам

Документация React-Redux описывает множество способов использования connect. Для моей цели понадобятся только mapStateToProps и mapDispatchToProps, чтобы покрыть всю функциональность.

  • преобразование стейта в пропсы (mapStateToProps) позволит компоненту Hello использовать this.props.message из Redux-стора.

  • преобразование диспатчинга экшенов (mapDispatchToProps) для HELLO_WORLD позволяет использовать this.props.onClick, как функцию внутри компонента Hello.

const mapStateToProps = (state, ownProps) => {
   return {
      message: state.helloWorld.message
   }
}
const mapDispatchToProps = (dispatch, ownProps) => {
   return {
      onClick: () => {
         dispatch({ type: HELLO_WORLD })
      }
   }
}
const HelloWorld = connect(
   mapStateToProps,
   mapDispatchToProps
)(Hello)

NPM модули, которые вы должны знать

Ниже представлены некоторые из npm модулей, о которых знают не все:

react-redux

По умолчанию Redux не включен в React, поэтому пакет react-redux нужно устанавливать дополнительно. Это предполагает, что вы должны использовать сборщики модулей типа Webpack или Browserify, которые работают с CommonJS.

webpack-dev-middleware

Это простая миддлвара для Webpack. Служит для обработки файлов, загружающихся из npm-пакетов. Используется только при разработке (узнать больше).

webpack-hot-server-middleware

Миддлвара, работающая в паре с webpack-dev-middleware, для горячего обновления (HMR) webpack-бандлов на сервере (узнать больше).

Пояснения

Ниже раскрыты некоторые термины и концепции:

HMR

Означает горячая замена (обновление) модулей или хотрелоад. Это фишка Webpack, позволяющая обновлять ваш JavaScript-код без перезагрузки браузера (узнать больше).

combineReducers(...)

Создает объект, содержащий значение нескольких редюсеров, который затем можно передать в createStore.

createStore(reducer, [preloadedState], [enhancer])

  1. Создает Redux-стор, хранящий стейт-дерево вашего приложения.
  2. Создание функции createStore(reducer, [initialState], [enhancer]), которая затем передаётся в <Provider>:
import { createStore, combineReducers } from 'redux'
function todos(state = [], action) {
   switch (action.type) {
      case 'ADD_TODO':
      return state.concat([ action.text ])
   default:
      return state
   }
}
function prefixTodos(state = [], action) {
   switch (action.type) {
      case 'PRE_ADD_TODO':
      return state.concat([ 'pre_'+action.text ])
   default:
      return state
   }
}
const mixReducers= combineReducers({todos, prefixTodos})
let store = createStore(mixReducers, [ 'Use Redux' ])

subscribe( … ) против connect(…)

По факту эти функции делают одно и то же в Redux, но официальная документация React НЕ советует использовать store.subscribe(), по той причине, что в connect() внесено множество оптимизаций, которые сложно сделать вручную, используя store.subscribe().

С помощью connect() создаётся «умный» компонент, подключаемый к Redux-стору.

«Умные» компоненты против «Глупых»

Подробнее о разделении на «умные» и «глупые» здесь

  • «Умные» компоненты предоставляют данные для «глупых» компонентов
  • «Глупые» компоненты: 1) Не имеют зависимостей от остального приложения 2) Определяют визуальную составляющую приложения.

Ссылки


Слушайте наш подкаст в iTunes и SoundCloud, читайте нас на Medium, контрибьютьте на GitHub, общайтесь в группе Telegram, следите в Twitter и канале Telegram, рекомендуйте в VK и Facebook.

Статья на Medium