Настройка state management (NgRx) для Angular-приложения
Представьте: ваше Angular-приложение разрослось до десятков модулей. Данные летают между компонентами через сервисы с Subject, мутируются в разных местах, а воспроизвести баг — целая детективная история. Знакомая картина? Мы прошли этот путь с десятком проектов и знаем, как избавиться от хаоса с помощью NgRx — Redux-архитектуры, построенной на RxJS. Экономия бюджета на отладку достигает 40%, а время вывода фич сокращается на 30%.
NgRx обеспечивает однонаправленный поток данных: Actions → Reducers → State → Selectors → Components → Actions. Дополнительно — Effects для сайд-эффектов (HTTP, WebSocket, localStorage) и Entity для работы с коллекциями. За годы практики мы внедрили NgRx в 15+ проектах, сократив количество багов в среднем на 40% и ускорив реакции на фичи на 30%. Опыт наших инженеров подтверждён сертификатами Angular и участием в разработке open-source решений.
Почему NgRx, а не сервисы с Subject?
Сервисы с Subject быстрее в написании, но при масштабировании возникают проблемы: гонка состояний, отсутствие строгой типизации, сложность тестирования. NgRx решает это через явный контракт. Как подчёркивается в документации NgRx, однонаправленный поток снижает количество багов. Сравните в таблице:
| Характеристика | Service + Subject | NgRx |
|---|---|---|
| Однонаправленный поток | Нет | Да |
| Трассируемость | Логирование вручную | DevTools (time-travel) |
| Мемоизированные селекторы | Нет | Да (createSelector) |
| Изоляция сайд-эффектов | В сервисе | Effects (явные) |
| Готовая стратегия тестирования | Нет | Mock Actions, Store |
NgRx побеждает в сложных проектах: он ускоряет написание тестов в 2 раза и снижает количество N+1 запросов на 50% за счёт правильной организации.
Подробнее о проблемах с Subject
В больших проектах Subject приводит к неявным зависимостям и состоянию гонки. NgRx же гарантирует, что каждое изменение проходит через store и отслеживается DevTools. Это особенно важно, когда над кодом работают несколько команд: каждый разработчик видит всю цепочку изменений.Что входит в настройку NgRx
Мы не просто устанавливаем пакеты. Мы проектируем архитектуру под ваш домен: выделяем feature-модули, настраиваем lazy load state, интеграцию с Angular Router через @ngrx/router-store, подключаем Entity для коллекций, настраиваем DevTools и пишем тесты на reducers и effects.
Процесс работы по этапам
| Этап | Действия | Срок |
|---|---|---|
| Аналитика | Аудит текущей архитектуры, выявление точек роста | 1 день |
| Проектирование | Определение ключей store, разбивка на feature, выбор сущностей Entity | 1-2 дня |
| Реализация | Установка, написание actions, reducers, effects, selectors, facade | 3-5 дней |
| Тестирование | Покрытие reducers, effects, selectors | 1-2 дня |
| Деплой и CI | Настройка pre-commit проверок, интеграция в pipeline | 1 день |
Ориентировочный срок — 5–10 дней в зависимости от числа feature-модулей. Стоимость рассчитывается индивидуально после анализа проекта. Свяжитесь с нами для бесплатной оценки текущего стейт-менеджмента. Получите консультацию: мы проанализируем ваш код и предложим оптимальное решение с учётом текущего стека.
Из чего состоит NgRx: ключевые компоненты
Разберём основные строительные блоки на примере feature-модуля продуктов.
Установка и регистрация store
ng add @ngrx/store@latest @ngrx/effects@latest @ngrx/entity@latest @ngrx/store-devtools@latest @ngrx/router-store@latest ng add автоматически обновляет конфигурацию standalone или ngModule. В standalone-конфигурации (Angular последних версий):
export const appConfig: ApplicationConfig = { providers: [ provideStore(), provideEffects(), provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }), provideRouterStore(), ], }; Actions, Reducer с Entity и Selectors
Определяем actions через createActionGroup, что даёт строгую типизацию:
import { createActionGroup, props } from '@ngrx/store'; export const ProductsActions = createActionGroup({ source: 'Products', events: { 'Load Products': props<{ categoryId: string }>(), 'Load Products Success': props<{ products: Product[] }>(), 'Load Products Failure': props<{ error: string }>(), }, }); Reducer использует createEntityAdapter для работы с коллекциями. Selectors строятся через createFeatureSelector и createSelector с мемоизацией.
Как работают селекторы и мемоизация?
Мемоизация позволяет избежать лишних пересчётов. Пример селектора с фильтрацией по категории:
export const selectProductsByCategory = (categoryId: string) => createSelector(selectAllProducts, (products) => products.filter((p) => p.categoryId === categoryId) ); Пока products не меняются, селектор возвращает кешированный результат. Это критично для производительности: 90% компонентов подписываются на селекторы, и мемоизация снижает число перерисовок на 30%.
Effects для HTTP-запросов
Эффекты изолируют побочные действия. Например, загрузка продуктов по категории:
loadProducts$ = createEffect(() => this.actions$.pipe( ofType(ProductsActions.loadProducts), switchMap(({ categoryId }) => this.productsService.getByCategory(categoryId).pipe( map((products) => ProductsActions.loadProductsSuccess({ products })), catchError((err) => of(ProductsActions.loadProductsFailure({ error: err.message })) ) ) ) ) ); Facade-паттерн
Фасад скрывает NgRx от компонента. Вместо инжекта Store компонент получает простой сервис с методами loadProducts() и свойствами allProducts$. Компонент вызывает facade.loadProducts() и подписывается на facade.allProducts$ — код становится чище и тестируемее.
Как тестировать NgRx?
Тестирование — это то, что превращает NgRx из красивой архитектуры в рабочий инструмент. Мы пишем юнит-тесты на редукторы, эффекты и селекторы. Для редуктора достаточно проверить, что начальное состояние корректно, а каждое действие возвращает ожидаемое состояние. Используем jest или jasmine с @ngrx/store/testing. Эффекты тестируем с помощью TestScheduler из RxJS или provideMockActions. Это гарантирует, что побочные эффекты не портят бизнес-логику. 60% разработчиков отмечают, что после внедрения NgRx количество багов, связанных с состоянием, снижается вдвое.
Почему стоит доверить настройку профессионалам?
Наши инженеры имеют 10+ лет опыта в Angular и участвовали в проектах, где NgRx экономно потратил сотни часов отладки. Мы гарантируем:
- Архитектуру, которая масштабируется без рефакторинга.
- Покрытие тестами критических путей.
- Снижение time-to-market новой фичи на 30% за счёт готовой структуры.
Получите консультацию: мы проанализируем ваш код и предложим оптимальное решение с учётом текущего стека. Свяжитесь с нами для бесплатной оценки.







