Автор оригинала: FreeCodeCamp Community Member.
Кевин мосты
Эта статья является введением в Функция-u – библиотека, которую облегчает Организация проекта на основе функций В вашем реагировать проект. Эта утилита помогает в организации вашего проекта по индивидуальным особенностям.
Большинство разработчиков согласится с тем, что организация вашего проекта по функциям является очень предпочтительным над типовыми шаблонами. Потому что Домены приложений растут В реальном мире проект Организация по типу Просто не масштабируется, это просто становится неуправляемым!
Есть много хороших статей по этой теме с Insights на основе функций дизайна и структуры (см. Ссылки ниже).
В данной статье говорится моя экскурсия в композицию на основе функций. Работаю по деталям, я понял, что библиотека была возможность помочь управлять и оптимизировать некоторые препятствия, понесенные в этом процессе. Результат: Функция-u (Проверьте Full Docs Full Docs , Источник GitHub и Пакет NPM ).
С одного взгляда
Фон – почему функция – u создана
ОСНОВНЫЕ ОСНОВНЫЕ ОСНОВЫ – Введите концепции высокого уровня
приложение для елки-кивки – приложение приложения, используемое для демонстрации функции-U
До и после – закусочная кивка Структура проекта до и после функций
Функция-u в действии – исследовать аспекты функций и бетонных примеров
Функция-u Преимущества – в резюме
Ссылки – Статьи на основе функций
Фон
Давайте начнем с покоя моего путешествия в этом процессе
Из начальных ворот …
SOOO … Я решил реструктурировать мой проект по функциям Отказ С точки зрения дизайна, было несколько соображений в определении границ объектов. Я прочитал все статьи и применил свой дизайн на Новая структура каталога на основе функций.
В общем, я чувствовал себя хорошо о моем прогрессе. Я начинал видеть конкретные преимущества … Сегрегация функций была приведет к приведению кода, который гораздо более управляемый!
препятствия …
Тем не менее, было несколько препятствий, чтобы еще не было решено …
Как я могу инкапсулировать и изолировать мои особенности, пока до сих пор позволяют им сотрудничать друг с другом?
Как выбранные функции вводят инициализацию запуска (даже утилита для инъекций в корневом DOM), не полагаясь на некоторые внешний процесс запуска?
Как я могу продвигать компоненты на основе функций в изолированный и автономный путь?
Как я могу настроить мои выбранные рамки теперь, когда мой код так распространен?
Как я могу включить/отключить выбранные функции, которые либо являются необязательными, либо требуют обновления лицензии?
Короче говоря, как я могу потянуть все это вместе, чтобы мои индивидуальные функции работали как одно приложение?
Цель (что сейчас?)
Верховная цель из функций-u два раза:
- Разрешить функции Подключи и играй! Это охватывает много вещей, таких как: инкапсуляция, перекрестная связь, включение, инициализация и так далее. Мы будем строить эти концепции на протяжении всей этой статьи.
- Автоматизировать запуск вашего приложения !! У вас есть функции. Позвольте им продвигать свои характеристики, поэтому центральная утилита может автоматически Настройте фреймворки, используемые в вашем приложении, тем самым запускаем ваше приложение. Эта задача должна быть достигнута устойчивым способом, потому что не каждый использует тот же набор рамок.
Основные основы
Основной процесс Функция-u это то, что каждая функция способствует Особенность Объект, который содержит различные аспекты этой функции – такие вещи, как имя функции, его общедоступное API, включена ли она, включена, инициализационные конструкции, а ресурсы, используемые для настройки его ломтика в использовании каркасов.
В свою очередь, эти объекты объекта поставляются на launchapp () , который настраивает и начинает работу вашего приложения. Кроме того, возвращенные Приложение Объект экспортируется, чтобы продвигать публичные API каждой функции.
аспекты
В особенности-u, «аспект» является обобщенным термином, используемым для ссылки на различные ингредиенты, которые (при совместившемся) составляют ваше приложение.
Аспекты могут взять на себя много разных форм:
- Компоненты и маршруты пользовательского интерфейса
- Управление государством (действия, редукторы, селекторы)
- Бизнес-логика
- Код инициализации запуска
- И так далее…
Не все аспекты представляют интерес к функциям-u – только те, которые необходимы для настройки и запуска приложения – все остальные считаются внутренней деталью реализации функции.
В качестве примера рассмотрите менеджер государства Redux. Хотя он использует действия, редукторы и селекторы … Для настройки и настройки Redux необходимы только редукторы.
Рамочная интеграция
Фундаментальная цель функции – у вас Автоматически настраивать каркас (ы), используемые в вашем режиме прохождения (накапливая необходимые ресурсы во всех ваших функциях). Потому что не все используют те же рамки, особенность – вы выполняете это через Расширяющиеся аспекты (Вы можете найти их во внешних пакетах NPM, или вы можете создать свой собственный).
Важно понимать, что интерфейс к выбранным вами каркасам не изменяется никак. Вы используете их так же, как у вас всегда (только в пределах вашей функции).
Особенностью – U просто предоставляет четко определенный организационный слой, где каркасы автоматически настраиваются и настроены, накапливая необходимые ресурсы во всех ваших функциях.
приложение
закусочная кивка это приложение, где функция – U задумана. Это Реагистративно Экспо Mobile App, и является одним из моих приложений Sandbox, которые я использую для тестирования Frameworks. Мне нравится разрабатывать приложения, которые я могу использовать, но иметь достаточно реальных требований, чтобы сделать его интересным.
SateRy-Nov случайно выбирает ресторан «Date Night» от бассейна избранного. Моя жена, и у меня устойчивая «дата вечера», и мы всегда нерешительны, на каком из наших любимых ресторанов частых:-) Так что съесть-киваки обеспечивает прядильное колесо!
Посмотрите на закусочную киву Readme чтобы почувствовать заявку. Доступны экранные потоки, поэтому это действительно помогает в вашей ориентации к проекту.
Кроме того, Файлы readme найдены в каждой функции, описывая, что выполняет каждую функцию. Займите некоторое время и убейте через эти ресурсы:
- устройство – Инициализирует устройство для использования приложением и способствует абстракции API устройства
- auth – Продвигает полную аутентификацию пользователя
- левойнав – Продвигает приложение-специфичный ящик/боковой панель на левой стороне приложения
- CurrentView – поддерживает текущее представление с GET/SET CROSS-функциональной связи
- закусочные – Управляет и способствует взгляду закусочных
- Открытие – Управляет и способствует открытию открытия
- Firebase – Инициализирует сервис FireBase Google
- объекты – Журналы всех отправленных действий и полученного состояния
- песочница – Продвигает различные интерактивные тесты, используемые в разработке, которые могут легко отключить
До после
Любой, кто знает меня, скажет вам, что у меня будет признательность за хорошее до/после анализа. Будь то домашняя реконструкция или рефактором программного обеспечения, оно помогает хроникам, где вы были, чтобы оценить конкретные достижения, и дает вам чувство выполнения.
Давайте посмотрим на структуру каталогов Neeery-Nod (до/после).
Для иллюстрации я только расширил несколько каталогов, но я думаю, что вы получите идею.
До : вот мой проект до функций …
eatery-nod src BEFORE featuressrc/├──actions/ ... redux actions│ auth.js│ discovery.js│ eateries.js│ ... snip snip├──api/ ... various abstract APIs│ device.js│ discovery.js│ ... snip snip├──app/ ... mainline startup **1**│ │ ScreenRouter.js│ │ SideBar.js│ │ index.js│ └──startup/│ │ createAppStore.js│ │ platformSetup.android.js│ │ platformSetup.ios.js│ └──firebase/│ firebaseAppConfig.js│ initFireBase.js├──appState/ ... redux reducers│ auth.js│ discovery.js│ eateries.js│ ... snip snip├──comp/ ... UI Component Screens│ DiscoveryListScreen.js│ EateriesListScreen.js│ ... snip snip├──logic/ ... redux-logic modules│ auth.js│ discovery.js│ eateries.js│ ... snip snip└──util/ ... common utilities
После : А вот тот же проект После функций …
eatery-nod src AFTER featuressrc/│ app.js ... launches app via launchApp() **2**├──feature/│ │ index.js ... accumulate/promote all app Feature objects│ ├──auth/ ... the app's authorization feature│ │ │ actions.js│ │ │ featureName.js│ │ │ index.js│ │ │ logic.js│ │ │ publicFace.js│ │ │ route.js│ │ │ signInFormMeta.js│ │ │ state.js│ │ └──comp/│ │ SignInScreen.js│ │ SignInVerifyScreen.js│ ├──currentView/ ... other features│ ├──device/ ... feature to initialize the device│ │ │ actions.js│ │ │ api.js│ │ │ appDidStart.js│ │ │ appWillStart.js│ │ │ featureName.js│ │ │ index.js│ │ │ logic.js│ │ │ publicFace.js│ │ │ route.js│ │ │ state.js│ │ └──init/│ │ platformSetup.android.js│ │ platformSetup.ios.js│ ├──discovery/ ... more features│ ├──eateries/│ ├──firebase/│ ├──leftNav/│ ├──logActions/│ └──sandbox/└──util/ ... common utilities used across all features
Как и ожидалось, разница в организации проекта драматическая!
- До функций – Вы найдете конструкции для данной функции, распространяемой на многочисленные напечатанные каталоги.
- После функций : Все аспекты данной функции содержатся в его собственном изолированном каталоге.
- Примечательно разница в том, что Драматическое снижение сложности процесса запуска приложения! «До функций» содержится целый
приложение \
каталог запуска кода (см.** 1 **
выше), в то время как «после функций» просто содержит одинapp.js
Запуск файл (см.** 2 **
выше). Куда идут всю сложность? … Следите за обновлениями!
Особенностью в действии
Чтобы лучше понять особенность – u, давайте приблизимся к некоторым примерам Neatery-Noke в действии.
Каждое из следующих разделов кратко введет новую тему функции-U, коррелируйте образец кода от Natery-Nod. Дополнительная информация предоставляется через ссылки, как для документов, как DOCS, так и для исходного кода Neatery-Nov. В некоторых случаях встроенный пример код был упрощен (чтобы подчеркнуть фокусную точку), однако ссылка на подписи приведет вас к фактическому коду (размещенному на Github).
Вот наши темы …
- Упрощенное запуск приложения
- React Platforms
- Объект объекта
- Инициализация функций
- Функция сотрудничества
- Рамочная интеграция
- Функция включения
- Управляемое расширение кода
- Ui Компонент Продвижение
- Один источник правды
1. Упрощенное запуск приложения
После разрыва вашего приложения на куски (как с функциями), как вы их потяните вместе, и на самом деле запустите свое приложение? На первый взгляд, это может показаться пугающей задачей. Однако, как получается, однако из-за структуры, продвигаемой функцией-u, это на самом деле является очень простым процессом.
Чтобы решить это, функция-u обеспечивает launchapp () Функция (см.: Запуск вашего приложения ).
Вот главная линия затравки …
Первое, что следует отметить, что просто насколько простым и универсальным процессом запуска магистрали. В нем нет настоящего кода конкретного приложения … даже некая глобальная инициализация!
Это связано с тем, что функция-u обеспечивает различные крючки, которые позволяют вашим функциям вводить свои собственные специфические конструкции.
Основная линия просто накапливает аспекты и особенности и запускает приложение, вызывая launchapp ()
Отказ
Вот несколько важных интересных точек (соответствуют номерам * N *
в коде выше):
(
* 1 *
)
Прилагаемые аспекты (вытащенные из отдельных пакетов NPM) отражают рамки нашего стека во время работы (в нашем примере redux , redux-logic и Функциональный маршрутизатор ) и продлить приемлемый Особенности свойств –Функция .eduducer
,Особенность .Logic
иThumps.Route
соответственно. (См. Расширяемые аспекты ).(
* 2 *
)
Все функции приложений накапливаются с нашихФункция/
каталог(
* 3 *
)
как предварительный просмотр Особенность совместной работы экспортируемая возвратная стоимостьlaunchapp ()
этоПриложение
Объект, который способствует накоплению общедоступных API всех функций.
2. Реагистрационные платформы
В приведенном выше примере (см. * 4 *
), вы видите, что launchapp ()
использует RecisterraterPAppelm () Обратный вызов Крюк для регистрации поставляемых RootAppelm
на конкретную реактивную платформу в использовании. Поскольку эта регистрация осуществляется по конкретному приложению код, функция – U может работать в любой из платформ RACT React (см. Регистрация React ).
Вот некоторые RecisterraterPAppelm () Вариации:
Экспо :
3. Особенность объекта
Каждая функция находится в своем каталоге и способствует аспекту контента через Особенность
Объект (используя Createfeature () ).
Вот пример от закусочных кивок устройство характерная черта.
Как вы можете видеть, Особенность
Объект – это просто контейнер, который удерживает аспектное содержание, представляющее интерес к функции. Единственная цель Особенность
Объект состоит в том, чтобы сообщить эту информацию о аспекте launchapp ()
Отказ
Мы будем заполнять более подробно чуть позже, но теперь обратите внимание, что эта функция передает редукторы, логические модули, маршруты и имеют некоторые тип инициализации ( Appwillstart
/ appdidstart
). Это также способствует Publicface
которые могут быть использованы другими функциями (например, общедоступная функция API).
Для получения дополнительной информации, пожалуйста, обратитесь к Особенности и аспект контента Отказ
4. Инициализация функции
Любая заданная функция не должна не полагаться на внешний процесс запуска, чтобы выполнить инициализацию, которую необходимо. Скорее, эта функция должна иметь возможность вырезать инициализацию, на которой она зависит.
Это может быть любое количество вещей, таких как:
- Инициализировать некоторые сервисные API
- Включить коммунальную реактивный компонент в корневом приложении
- отправить действие, которое начинает процесс запуска
- И больше…
Чтобы решить это, функция – вы представляете два Крючки жизненного цикла приложений , вводится через следующие аспекты функций:
- Feature.appwillstart ({app, currotappelm}): rootappelm Falsy
Привязан один раз, пока приложение запускается. Это может сделать любой тип инициализации, включая дополнение корневого элемента верхнего уровня приложения (например, React
компонент - экземпляр). Feature.appdidstart ({app, appstate, dispatch}): void
Привязан один раз сразу после начала приложения. Типичное использование для этого крюка - отправить какой-то тип
Действие Bootstrap
Вот несколько примеров из елочной кивки:
Инициализация Firebase:
Действие Bootstrap:
Введите root тьм домо
5. Функция сотрудничества
Несмотря на то, что реализация функции инкапсулирована, она все еще должна взаимодействовать с его окружением. Чтобы усложнить вопросы, одна особенность никогда не должна импортировать ресурсы из другой функции, потому что она должна стремиться быть подключаемым и воспроизведением. В результате нам нужна четко определенная общественная API на основе функций.
Чтобы решить это, особенность – вы продвигаете Cross Feature Communication Отказ Это достигается через Функция. Publicface
Встроенный аспект имущество. Функция может разоблачить все, что его считают необходимыми через его Publicface
Отказ На этом ресурсе нет реальных ограничений. Это действительно открыто.
Как правило, это включает в себя содействие выбранному:
- Действия
- селекторы
- Апис
- И так далее
Publicface
Из всех функций накапливаются и выставлены через Приложение
Объект (испускаемый из LaunchApp ()
).
Содержит названные узлы функций следующим образом:
App.{featureName}.{publicFace}
Вот пример от закусочных кивок auth характерная черта.
Из всех предметов, найденных в auth
Особенность, только два действия и один селектор являются публичными.
Вот что Приложение
Объект будет выглядеть для этого примера:
app: { auth: { actions: { userProfileChanged(userProfile), signOut(), }, sel: { getUserPool(appState), }, }, currentView: { // other features ... snip snip },}
В результате auth
Общественный API функции можно получить следующим образом:
app.auth.actions.userProfileChanged(userProfile)app.auth.actions.signOut()app.auth.sel.getUserPool(appState)
6. Рамочная интеграция
Скорее всего, ваша приложение использует одну или несколько фреймворков (таких как redux
или redux-logic ). Как ресурсы, необходимые по этим каркасам, накопленными и настроены по всему множеству ваших функций вашего приложения?
Чтобы решить это, функция – U вводит Расширяющиеся аспекты Отказ Функция-u это Расширяемый Отказ Он обеспечивает точки интеграции между вашими функциями и выбранными рамками.
Расширяющиеся аспекты упаковываются отдельно от функций-u, чтобы не вводить нежелательные зависимости (потому что не все используют те же рамки). Вы выбираете их, основываясь на рамочных рамках, используемых в вашем проекте (сопоставление стека выполнения вашего проекта). Они созданы с помощью расширяемой API функции-u, используя CreateaseSpect () Отказ Вы можете определить свой собственный аспект, если вам нужно уже не существует.
Давайте посмотрим на пример Redux от Neatery-Noad.
устройство
Функция поддерживает свой собственный ломтик дерева штата.
Это способствует его редуктору через Функция .eduducer
Аспект:
Потому что Функция .eduducer
Это расширенный аспект (стихи встроенный аспект), он только доступен, потому что мы зарегистрировали Особенность-redux Редустерасфект
к launchapp ()
(Пожалуйста, обратитесь к Упрощенное приложение Startup выше).
Ключевая вещь, которую нужно понять, заключается в том, что функция u (через расширение функции-redux) автоматически настроит Redux, накопив все редукторы функций в одну общую appstate.
Вот код редуктора …
Редуктор на основе функций – это просто обычный редуктор, который управляет ломтиком функции общего appstate. Единственное отличие в том, что она должна быть украшена Порезы () , который предоставляет инструкции, где вставлять его в общий первоначальный AppState.
В результате устройство
Редуктор поддерживает только государство, относящееся к устройство
Функция (как и его маленький кусочек мира) – статус, индикатор FontSloaded и расположение устройства.
Боковая панель : Мы используем ASTX-Redux-util Утилита редуктор () Функция, чтобы кратко реализовать редуктор функции (предоставляя альтернативу общему оператору выключателя). Я обнаружил, что в использовании такой утилиты, поскольку большинство случаев можно осуществимо реализовать все редукторы функции в одном файле (из-за того, что из-за меньшей границы функции). ASTX-Redux-Util также способствует другому Редуктор высшего порядка с. Вы можете проверить это.
7. Функция включения
Некоторые из ваших функций могут быть динамически включены или отключены. В качестве примера определенные функции могут быть включены только с обновлением лицензии, или другие функции могут быть использованы только для диагностических целей.
Чтобы решить это, функция – U вводит Функция включения Отказ Используя Функция Встроенный аспект (логическое свойство), вы можете включить или отключить вашу функцию.
Вот пример от закусочных кивок песочница характерная черта:
Функция Sandbox способствует различным интерактивным тестам, используемым в разработке, которые можно легко отключить.
Обычно этот индикатор основан на динамическом выражении, но в этом случае он просто жестко закодируется (для установки разработчиком).
Боковая панель : Когда другие функции взаимодействуют с функцией, которую можно отключить, вы можете использовать Приложение
Объект, чтобы определить, присутствует ли функция или нет (см.: Включение функции для получения дополнительной информации).
8. Управляемое расширение кода
В общем, доступ к Импортированные ресурсы Во время встроенного кода расширение может быть проблематичным, из-за порядка, в котором эти ресурсы расширяются. Особенность – u Приложение
Объект – это такой критический ресурс (потому что он способствует общедоступному API всех функций), Это должно быть доступно даже во время расширения кода Отказ Другими словами, мы не можем полагаться на «импортированное приложение», которое будет разрешено во время расширения кода.
Чтобы решить это, функция – U вводит Управляемый код расширения Отказ
Когда определения контента аспекта требуют Приложение
Объект по времени расширения кода, вы просто оберните определение в ManagedExpansion () функция. Другими словами, ваш аспект может быть либо фактическим самим содержимым (таким как редуктор), либо функция, которая возвращает содержимое.
Когда это сделано, функция – U расширит его, вызывая его контролируемым способом, передавая полностью разрешенную Приложение
объект как параметр.
Вот логический модуль от закусочных кивок auth характерная черта:
Вы можете увидеть, что функция auth использует действие от устройство Функция, требующая доступа к приложение
Объект (см. * 2 *
). Потому что приложение
Объект необходим во время расширения кода, мы используем ManagedExpansion ()
Функция (см. * 1 *
), позволяя функцию – вы расширить его контролируемым способом, передавая полностью разрешенную приложение
объект как параметр.
9. Компонент UI Продвижение
Особенности, которые поддерживают свои собственные компоненты пользовательского интерфейса, нуждаются в способе продвижения их в общем GUI приложения. Поскольку функции инкапсулированы, как это достигается автономным способом?
Чтобы решить это, функция – вы рекомендуете, учитывая На основе функций маршруты через Функциональный маршрутизатор Расширяющийся аспект (упакован отдельно). Этот подход может даже использоваться в сочетании с другими навигационными решениями.
Функциональные маршруты основаны на очень простой концепции: позвольте состоянию приложения водить маршруты! Он работает через серию функций маршрутизации на основе функций, которая причинами к AppState и либо возвращает оказанный компонент, либо NULL, чтобы разрешить нисходящие маршруты ту же возможность.
Вот простой пример из устройство характерная черта.
Этот маршрут анализирует текущее appstate и отображает всплеск, пока система не будет готов:
В маршрутизации на основе функций вы не найдете типичный каталог «Путь маршрута к компоненту», где (например) некоторых псевдо Маршрут («устройство»)
Директива приводит к отображению экрана устройства, что, в свою очередь, вызывает систему для приспособления запроса, регулируя его состояние соответствующим образом.
Скорее, AppState проанализирован, и если устройство не готово, никакие другие экраны не дают возможности даже рендеринга … Простое кресть!
В зависимости от вашей точки зрения, этот подход может быть более естественным, но, что более важно, оно позволяет своим функциям продвигать свои собственные экраны в инкапсулированном и автономном пути.
10. Один источник правды
Функциональные реализации (например, все кодирующие конструкции) должны стремиться следовать за Одностоищенная правда принцип. При этом единственная линия модификации может распространяться со многими областями вашей реализации.
Что такое некоторые Лучшие практики Для односторонней истины, поскольку оно относится к функциям и как можно сделать – вы помогаете?
Лучшие практики Секция подчеркивает ряд объектов, основанных на особенностях, представляющих интерес одного источника. Это руководящие принципы, поскольку вы должны реализовать их в вашем приложении (функция – u не контролирует это).
Вот пример из закусочные характерная черта:
FeigureName
Используется для указания состояния верхнего уровня этой функции (см. * 1 *
). Особенности – U гарантирует, что имя функции уникально. В результате его можно использовать для квалификации идентичности нескольких аспектов признаков.
Например:
- Префикс типов действий с feignename, гарантируя их уникальность в приложении (см.: Функция-redux Документы)
- Префикс логические имена модулей с featurename, выявление того, где этот модуль жизни (см.: Функция-redux-logic Документы)
- В зависимости от контекста, файл featureName можно использовать в качестве корня формы состояния вашей функции (см.: Функция-redux Документы)
Потому что функция – ты полагается на Порезы () (В пакете функции-redux) наилучшая практика заключается в использовании украшенного селектора редуктора для квалификации корень состояния функции во всех ваших определениях селектора. В результате определение среза поддерживается в одном месте (см. * 2 *
).
Преимущества
Таким образом, преимущества использования функций-u включают:
- Функциональная инкапсуляция – ИЗОБРАЖЕНИЕ ОСОБЕННОСТИ ОСОБЕННОСТИ Улучшает управляемость кода
- Cross Feature Communication – Общественный API функции продвигается через четко определенный стандарт
- Функция включения – Включить/отключить функции через выходной выключатель
- Крючки жизненного цикла приложений – Особенности могут инициализировать себя, не полагаясь на внешний процесс
- Один источник правды – облегчается несколькими способами в реализации функции
- Рамочная интеграция – Настройте рамки (ы) по вашему выбору (сопоставление вашего времени запуска) с использованием расширяемой API API-u
- UI Компонент Продвижение – через объекты маршрутов
- Минимизируйте вопросы зависимости заказа функций – даже в коде, который расширен в режиме онлайн
- Plug-and-Play – Особенности могут быть добавлены/удалены легко
- Упрощенная главная линия –
Launcapp ()
Запускает приложение, запущенное, настроив использование фреймворков, все приводимые в действие простым набором функций. - Работает на любой React Platform (в том числе React Web, реагировать на родной и экспо)
Надеюсь, эта статья дает вам почувствовать, как функция – вы можете улучшить ваш проект. Пожалуйста, обратитесь к Полная документация Больше подробностей.
Функция-u позволяет вам сосредоточить свое внимание на «деловом конце» ваших функций! Иди и вычислить !!
Рекомендации
- Подход на основе функций для развития реагирования … Райан Ланчая
- Как лучше организовать ваши приложения React? … Алексис Мангин
- Как использовать Redux на высокомасштабных приложениях JavaScript? … Алексис Мангин
- 100% правильный способ структурирования приложения RACT (или почему нет такой вещи) … Дэвид Гилбернтсон
- Redux для государственного управления в крупных веб-приложениях … Дэвид Кларк