Если вы еще не читали часть 1, нажмите здесь

Что мы будем использовать в этой части

  • Redux (3. *)
  • Инструменты разработчика Redux
  • ReactJS

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

Введение

Часть 2 будет посвящена настройке библиотеки Redux в вашем изоморфном стеке. То, что мы сделали сейчас, довольно простое: мы можем создать веб-сайт, но как нам управлять нашей бизнес-логикой? Нам нужна библиотека для обработки нашего потока данных.

Для этого мы будем использовать Redux, контейнер состояния для вашего приложения. Исходя из традиционного фона Java, я часто сравнивал его с наблюдаемым паттерном, но это не покрывает всей картины.

Если вы занимались программированием на React, вы знаете о Flux и архитектуре, которую он подразумевает. Процитирую Дэна Абрамова (создателя Redux):

Redux развивает идеи Flux, но избегает его сложности, беря реплики Elm.

Эта статья не объяснит вам, как работает Redux, есть много отличных статей и даже бесплатных видео-сериалов, которые преподает сам Дэн.

Посмотреть весь код можно здесь:



Давайте нырнем!

1) Библиотека

Исходя из предположения, что вы (теперь) знаете, что такое Redux и для чего он предназначен, вы должны почувствовать необходимость отделить его от своей архитектуры React.

Почему? Redux - это контейнер состояний, который полностью отделен от какой-либо структуры. Это означает, что его можно использовать повторно, и он не привязан к правилам / парадигмам /…

Возможность многократного использования вашей базовой логики в нескольких приложениях - одно из величайших преимуществ Redux.

Чтобы привести пример, в настоящее время мы создаем наш пользовательский интерфейс на ReactJS, но Angular 2 не за горами, и вы можете захотеть отказаться от парадигмы пользовательского интерфейса в какой-то момент. Redux имеет предопределенные привязки для Angular 2 и React, но вы можете создавать привязки для любой библиотеки представлений. Это то, что делает redux таким мощным, низкое сцепление и высокое сцепление.

Итак, давайте начнем с настройки нашей библиотеки. Структура нашей папки «lib» будет выглядеть следующим образом:

Примечание. Эта папка lib также может быть модулем npm или подмодулем git. Для этой настройки я решил оставить библиотеку внутри проекта, поскольку это небольшая архитектура. Имейте в виду, что если ваша установка будет расти, вы захотите разделить основную логику.

Итак, давайте быстро рассмотрим эту структуру каталогов:

  • index.js - наша точка входа, он предоставит все важные методы для настройки Redux.
  • Мы также будем писать настраиваемые промежуточное ПО для поддержки настраиваемых действий, обещаний и т. Д.
  • Папка modules - это архитектурное решение, в основном мы будем сопоставлять модуль с маршрутом. Например, созданный нами компонент Feed будет отображаться в модуль feed, который будет содержать действия, редукторы и т. Д. Для этого маршрута.
  • Папка store будет содержать логику для создания и поддержки нашего магазина.
  • Утилиты - это просто утилиты или легкодоступные функции многоразового использования.

1.1) Настройка библиотеки

У нас есть 3 важных аспекта, которые отражают то, что делает наша библиотека: она создает магазин, предоставляет модули и предоставляет промежуточное ПО. Почему он предоставляет модули и промежуточное ПО? Задолго до того, как мы ответим на эти вопросы, мы должны сначала построить базовый пример, чтобы пролить свет на общие проблемы, с которыми мы можем столкнуться. Затем мы сосредоточимся на том, как их решить. Во-первых, давайте создадим основу нашей библиотеки. (Большинство оптимизаций, которые мы сейчас внедряем, будут объяснены в части 3.)

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

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

Чтобы объединить все воедино, необходимо предоставить определенные модули. Я считаю, что сборщик модулей - лучший способ связать все модули вместе:

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

Задача довольно проста: когда вы создаете экземпляр moduleCollector и добавляете к нему модуль, он собирает редукторы и действия для этого модуля в соответствующие массивы.

Он также откроет модули через функцию get. Таким образом можно получить доступ к каждому отдельному модулю, а также ко всем редюсерам / действиям для всех модулей.

Конфигурация передается каждому добавленному модулю, сейчас это не имеет значения. (предварительная оптимизация)

1.2) Определение модуля

Модуль связан с маршрутом, поэтому каждый модуль будет содержать 3 вещи:

  • Действия
  • Редукторы
  • Константы

Константы определяют, какие возможные состояния может принимать действие (если оно асинхронное).

В предыдущей части этой серии мы определили маршрут Feed. Если бы мы сопоставили это с модулем vanilla redux, это выглядело бы примерно так:

В модулях создайте папку «feed», в этой папке определите следующие файлы:

Примечание
При рассмотрении редукторов следует обратить внимание на то, что инициализация объекта состояния должна напрямую отражать тип объекта, который вы пытаетесь вернуть. Если это не так, react-redux не обновит состояние правильно.

1.3) Собираем все вместе

Пришло время заставить все снова работать. Что нам нужно сделать? Наша библиотека в основном настроена, но наше приложение ее еще не использует. Итак, давайте попробуем соединить все вместе.

1.3.1) React-Redux

Нам нужно иметь возможность подключиться к React, чтобы получать обновления в магазине redux. Здесь в игру вступает react-redux. Это дает нам компонент ‹Provider /›, который обертывает нашу маршрутизацию и предоставляет доступ к хранилищу всем дочерним элементам.

Как вы можете видеть выше, мы также открываем хранилище, если плагин определения WebPack содержит переменную с именем «process.env.feature.DEV» (или серверная часть узла для SSR), это признак функции. При сборке WebPack пропустит этот код, поскольку uglify удаляет мертвый код.

По умолчанию ваш узел не понимает эту переменную «feature», поэтому вы должны установить ее по умолчанию.

1.3.2) Инструменты разработчика Redux

В app.js мы также представили магазин, чтобы мы могли реализовать инструменты разработчика redux. Эти инструменты разработчика позволяют нам просматривать изменения состояния нашего хранилища. Фактически позволяет вам путешествовать во времени по состоянию вашего приложения, а также по действиям пользователя, вызвавшим изменение.

Все возможные инструменты можно найти здесь.

Как нам его запустить и запустить? Нам нужно добавить «devtools.js» в нашу папку «utils» в библиотеке, это выглядит так:

По сути, это создает ваш компонент «DevTools», который вам нужно создать в функции Redux «compose».

Нам также необходимо добавить строку ввода в нашу конфигурацию WebPack для наших инструментов разработки. Вы также можете обернуть его внутри своего приложения, но я считаю, что, поскольку это отдельный инструмент, вы должны загружать его отдельно и отображать на другом узле DOM:

Примечание.
Это также важно для рендеринга на стороне сервера, потому что ваши инструменты разработчика не должны отображаться на вашем сервере.

Теперь все, что нам нужно сделать, это отрендерить его в узел DOM:

Вуаля, если бы вы запустили код, вы бы увидели следующее:
(нажмите ctrl-h):

1.3.3) Заставляем ваш компонент взаимодействовать с Redux

Теперь, когда наше приложение имеет представление о Redux благодаря ‹Provider /›, и у нас есть соответствующие инструменты разработчика для управления состоянием.
Нам нужно связать нашу «Ленту» с обновлениями.

Помните React-redux? В основном он может делать следующее: при изменении состояния вы можете сопоставить определенные значения хранилища своим свойствам. Да, response-redux обновляет свойства вашего компонента, чтобы ваш компонент мог повторно отрисоваться.

Этот код очень важен, это уровень связи между React и Redux. (В частности, «connect» и «mapStateToProps»)

Обычно ваш компонент не должен иметь понятия о мутации состояния, он должен просто подписываться на / получать обновления. Это то, что выполняет метод connect, он подключает наш компонент к store-updates.

Когда магазин обновляет, каждый компонент, связанный с состоянием, будет вызывать его «mapToProps» или метод. Вот изящная часть, поскольку React настолько умен, что если ничего не изменилось, он не будет повторно отображаться.

Здесь проводится важное различие между «умными» и «глупыми» компонентами. Вышеупомянутый компонент «Лента» имеет представление о магазине и его обновлениях, поэтому является интеллектуальным компонентом. Компонент ‹Item /› - это тупой компонент, поскольку он не имеет понятия о хранилище и показывает только данные.

1.3.4) Рендеринг на стороне сервера

Мы скорректировали нашу кодовую базу для реализации Redux. Однако рендеринг на стороне сервера не учитывается. Это все еще работает?

Да, он, вероятно, по-прежнему будет работать, однако он не будет делать ничего полезного на сервере, поскольку клиент переопределит все, что он обслуживал. Это связано с тем, что то, что возвращается с сервера, и то, что на самом деле отображает клиент, отличается. Итак, React выполнит повторный рендеринг.

В итоге наша структура каталогов выглядит так:

Время для обзора

Итак, давайте подведем итоги того, что у нас есть прямо сейчас:

  • Настройка ReactJS
  • Отрисовка на стороне сервера: которую можно проверить, проверив «response-контрольная сумма-id» на ваших обработанных узлах.
  • Библиотека Redux
  • Инструменты разработчика Redux
  • Конфигурация разработки WebPack
  • Front-end Node-сервер, который будет обслуживать наше приложение
  • Вавилонская транспиляция (ES6 / ES7)
  • Внешняя / серверная маршрутизация

К чему мы все еще стремимся:

  • Оптимизация рендеринга на стороне сервера: Мы не должны создавать магазин каждый раз, а создавать его на основе выполненных действий. У нас также должны быть данные в хранилище от асинхронных действий до рендеринга.
  • Набор тестов Mocha
  • Оптимизация библиотеки Redux:
    URL-адреса API и конфигурация / ресурсы на основе среды должны загружаться динамически
  • Обобщение конфигурации WebPack для нескольких сред сборки (сборка, готовая к производству)
  • Создатели / помощники Redux Action: подключите наш канал к асинхронному потоку данных (канал Twitter).

Все вышеперечисленное будет рассмотрено в Части 3.

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