NgRx — Best Practices for Enterprise Angular Applications
Tags: angular, ngrx, javascript, redux
Published: 2019-02-04 15:20:38

---
title: NgRx — Best Practices for Enterprise Angular Applications
published: true
description: The following represents a pattern that I’ve developed at my day job after building several enterprise Angular applications using the NgRx library. I have found that most online tutorials do a great job of helping you to get your store up and running, but often fall short of illustrating best practices for clean separation of concerns between your store feature slices, root store, and user interface.
tags: angular, ngrx, javascript, redux
canonical_url: https://wesleygrimes.com/angular/2018/05/30/ngrx-best-practices-for-enterprise-angular-applications.html
---

### Before We Get Started

This article is not intended to be a tutorial on **NgRx**. There are several great resources that currently exist, written by experts much smarter than me. I highly suggest that you take time and learn **NgRx** and the **redux** pattern before attempting to implement these concepts.

*   [Ultimate Angular — NgRx Store & Effects](https://ultimatecourses.com/courses/angular/ref/wes.grimes/)
*   [Pluralsight — Play by Play Angular NgRx](https://www.pluralsight.com/courses/play-by-play-angular-ngrx)
*   [NgRx Blog on Medium.com](https://medium.com/ngrx)
*   [NgRx.io Docs](https://ngrx.io/docs)
*   [NgRx.io Resources](https://ngrx.io/resources)

### Background

The following represents a pattern that I’ve developed at my day job after building several enterprise Angular applications using the **NgRx** library. I have found that most online tutorials do a great job of helping you to get your store up and running, but often fall short of illustrating best practices for clean separation of concerns between your store feature slices, root store, and user interface.

With the following pattern, your root application state, and each slice (property) of that root application state are separated into a _RootStoreModule_ and per feature _MyFeatureStoreModule_.

![](https://cdn-images-1.medium.com/max/1600/1*heR7Q5p_9a-v4kD1WKg1XQ.png)

### Prerequisites

This article assumes that you are building an [Angular v6 CLI](https://cli.angular.io/) generated application.

### Installing NgRx Dependencies

Before we get started with generating code, let’s make sure to install the necessary **NgRx** node modules from a prompt:

<pre name="b67b" id="b67b" class="graf graf--pre graf-after--p">npm install @ngrx/{store,store-devtools,entity,effects}</pre>

### Best Practice #1 — The Root Store Module

Create a Root Store Module as a proper Angular **NgModule’s** that bundles together NgRx store logic. Feature store modules will be imported into the Root Store Module allowing for a single root store module to be imported into your application’s main App Module.

#### Suggested Implementation

1.  Generate _RootStoreModule_ using the **Angular CLI:**

<pre name="fb1b" id="fb1b" class="graf graf--pre graf-after--li">ng g module root-store —-flat false —-module app.module.ts</pre>

2\. Generate _RootState_ interface to represent the entire state of your application using the **Angular CLI:**

<pre name="5ad4" id="5ad4" class="graf graf--pre graf-after--p">ng g interface root-store/root-state</pre>

This will create an interface named `RootState` but you will need to rename it to `State` inside the generated `.ts` file as we want to, later on, utilize this as `RootStoreState.State`

PLEASE NOTE: You will come back later on and add to this interface each feature module as a property.

### Best Practice #2 — Create Feature Store Module(s)

Create feature store modules as proper Angular NgModule’s that bundle together feature slices of your store, including _state_, _actions_, _reducer_, _selectors_, and _effects_. Feature modules are then imported into your _RootStoreModule_. This will keep your code cleanly organizing into sub-directories for each feature store. In addition, as illustrated later on in the article, public _actions_, _selectors_, and _state_ are name-spaced and exported with feature store prefixes.

#### Naming Your Feature Store

In the example implementation below we will use the feature name _MyFeature_, however, this will be different for each feature you generate and should closely mirror the _RootState_ property name. For example, if you are building a blog application, a feature name might be _Post_.

#### Entity Feature Modules or Standard Feature Modules?

Depending on the type of feature you are creating you may or may not benefit from implementing [NgRx Entity](https://medium.com/ngrx/introducing-ngrx-entity-598176456e15). If your store feature slice will be dealing with an array of type then I suggest following the _Entity Feature Module_ implementation below. If building a store feature slice that does not consist of a standard array of type, then I suggest following the _Standard Feature Module_ implementation below.

#### Suggested Implementation — Entity Feature Module

1.  Generate _MyFeatureStoreModule_ feature module using the **Angular CLI:**

<pre name="8add" id="8add" class="graf graf--pre graf-after--li">ng g module root-store/my-feature-store --flat false --module root-store/root-store.module.ts</pre>

2\. Actions — Create an _actions.ts_ file in the _app/root-store/my-feature-store_ directory:

{% gist https://gist.github.com/wesleygrimes/3f44710f040dd8c1f52a6b49b8135ecf %}

3\. State — Create a _state.ts_ file in the _app/root-store/my-feature-store_ directory:

{% gist https://gist.github.com/wesleygrimes/433a525d339c3cc1d13a4baf12036205 %}

4\. Reducer — Create a _reducer.ts_ file in the _app/root-store/my-feature-store_ directory:

{% gist https://gist.github.com/wesleygrimes/3cb221e1c0525bc09959327c3c2cb263 %}

5\. Selectors — Create a _selectors.ts_ file in the _app/root-store/my-feature-store_ directory:

{% gist https://gist.github.com/wesleygrimes/72a4bb87a4adb05ec57552d23d703024 %}

6\. Effects — Create an _effects.ts_ file in the _app/root-store/my-feature-store_ directory with the following:

{% gist https://gist.github.com/wesleygrimes/d31728ae8ebf99db7170bf896ea2c833 %}

#### Suggested Implementation — Standard Feature Module

1.  Generate _MyFeatureStoreModule_ feature module using the **Angular CLI:**

<pre name="c819" id="c819" class="graf graf--pre graf-after--li">ng g module root-store/my-feature-store --flat false --module root-store/root-store.module.ts</pre>

2\. Actions — Create an _actions.ts_ file in the _app/root-store/my-feature-store_ directory:

{% gist https://gist.github.com/wesleygrimes/d7b660caedb80a35213dd55e8c63a9d5 %}

3\. State — Create a _state.ts_ file in the _app/root-store/my-feature-store_ directory:

{% gist https://gist.github.com/wesleygrimes/51be65ebe6952234354a9f5c9329edae %}

4\. Reducer — Create a _reducer.ts_ file in the _app/root-store/my-feature-store_ directory:

{% gist https://gist.github.com/wesleygrimes/ff9cc03e43a46aae360f1c872d757193 %}

5\. Selectors — Create a _selectors.ts_ file in the _app/root-store/my-feature-store_ directory:

{% gist https://gist.github.com/wesleygrimes/330f6e42485598d406dbcfeb086d3d81 %}

6\. Effects — Create an _effects.ts_ file in the _app/root-store/my-feature-store_ directory with the following:

{% gist https://gist.github.com/wesleygrimes/f95dc16a1793bce388f1a32bfe1f1e24 %}

#### Suggested Implementation — Entity and Standard Feature Modules

Now that we have created our feature module, either Entity or Standard typed above, we need to import the parts (state, actions, reducer, effects, selectors) into the Angular NgModule for the feature. In addition, we will create a barrel export in order to make imports in our application components clean and orderly, with asserted name-spaces.

1.  Update the _app/root-store/my-feature-store/my-feature-store.module.ts_ with the following:

{% gist https://gist.github.com/wesleygrimes/c56034233725a6e067adf6e907aa55af %}

2\. Create an _app/root-store/my-feature-store/index.ts_ [barrel export](https://twitter.com/toddmotto/status/918818392680824832). You will notice that we import our store components and alias them before re-exporting them. This, in essence, is “name-spacing” our store components.

{% gist https://gist.github.com/wesleygrimes/84bcbe1ade8844c91b9232e6c38f6f0d %}

### Best Practice #1 — The Root Store Module (cont.)

Now that we have built our feature modules, let’s pick up where we left off in best practice #1 and finish building out our _RootStoreModule_ and _RootState._

#### Suggested Implementation (cont.)

3\. Update _app/root-store/root-state.ts_ and add a property for each feature that we have created previously:

{% gist https://gist.github.com/wesleygrimes/9d9bac862467038229f958b113f6fdf7 %}

4\. Update your _app/root-store/root-store.module.ts_ by importing all feature modules, and importing the following **NgRx** modules: _StoreModule.forRoot({})_ and _EffectsModule.forRoot([])_:

{% gist https://gist.github.com/wesleygrimes/a99ff7b248b4063e88dcb5acae77069d %}

5\. Create an _app/root-store/selectors.ts_ file. This will hold any root state level selectors, such as a Loading property, or even an aggregate Error property:

{% gist https://gist.github.com/wesleygrimes/c64c37c104d45d0b123ae49ac14117a3 %}

6\. Create an _app/root-store/index.ts_ barrel export for your store with the following:

{% gist https://gist.github.com/wesleygrimes/f272ad8cba5ba2a7880e757c999c195e %}

### Wiring up the Root Store Module to your Application

Now that we have built our Root Store Module, composed of Feature Store Modules, let’s add it to the main _app.module.ts_ and show just how neat and clean the wiring up process is.

1.  Add _RootStoreModule_ to your application’s _NgModule.imports_ array. Make sure that when you import the module to pull from the barrel export:

<pre name="32e2" id="32e2" class="graf graf--pre graf-after--li">import { RootStoreModule } from ‘./root-store’;</pre>

2\. Here’s an example _container_ component that is using the store:

{% gist https://gist.github.com/wesleygrimes/cf68217ea6d94feb6abbe5d717ddb715 %}

### Finished Application Structure

Once we have completed implementation of the above best practices our Angular application structure should look very similar to something like this:

<pre name="8942" id="8942" class="graf graf--pre graf-after--p">├── app
 │ ├── app-routing.module.ts
 │ ├── app.component.css
 │ ├── app.component.html
 │ ├── app.component.ts
 │ ├── app.module.ts
 │ ├── components
 │ ├── containers
 │ │    └── my-feature
 │ │         ├── my-feature.component.css
 │ │         ├── my-feature.component.html
 │ │         └── my-feature.component.ts
 │ ├── models
 │ │    ├── index.ts
 │ │    └── my-model.ts
 │ │    └── user.ts
 │ ├── root-store
 │ │    ├── index.ts
 │ │    ├── root-store.module.ts
 │ │    ├── selectors.ts
 │ │    ├── state.ts
 │ │    └── my-feature-store
 │ │    |    ├── actions.ts
 │ │    |    ├── effects.ts
 │ │    |    ├── index.ts
 │ │    |    ├── reducer.ts
 │ │    |    ├── selectors.ts
 │ │    |    ├── state.ts
 │ │    |    └── my-feature-store.module.ts
 │ │    └── my-other-feature-store
 │ │         ├── actions.ts
 │ │         ├── effects.ts
 │ │         ├── index.ts
 │ │         ├── reducer.ts
 │ │         ├── selectors.ts
 │ │         ├── state.ts
 │ │         └── my-other-feature-store.module.ts
 │ └── services
 │      └── data.service.ts
 ├── assets
 ├── browserslist
 ├── environments
 │ ├── environment.prod.ts
 │ └── environment.ts
 ├── index.html
 ├── main.ts
 ├── polyfills.ts
 ├── styles.css
 ├── test.ts
 ├── tsconfig.app.json
 ├── tsconfig.spec.json
 └── tslint.json</pre>

### Fully Working Example — Chuck Norris Joke Generator

I have put together a fully working example of the above best practices. It’s a simple Chuck Norris Joke Generator that has uses _@angular/material_ and the [http://www.icndb.com/](http://www.icndb.com/) api for data.

#### Github

{% github ngHighCountry/angular-ngrx-chuck-norris %}


#### Stackblitz

You can see the live demo at [https://angular-ngrx-chuck-norris.stackblitz.io](https://angular-ngrx-chuck-norris.stackblitz.io) and here is the [Stackblitz](https://stackblitz.com) editor:

[**angular-ngrx-chuck-norris - StackBlitz**
_NgRx _Best_Practices_Chuck_Norris_Example_stackblitz.com](https://stackblitz.com/edit/angular-ngrx-chuck-norris?embed=1&file=src/app/containers/jokes/jokes.component.ts "https://stackblitz.com/edit/angular-ngrx-chuck-norris?embed=1&file=src/app/containers/jokes/jokes.component.ts")[](https://stackblitz.com/edit/angular-ngrx-chuck-norris?embed=1&file=src/app/containers/jokes/jokes.component.ts)

### Conclusion

It’s important to remember that I have implemented these best practices in several “real world” applications. While I have found these best practices helpful, and maintainable, I do not believe they are an end-all-be-all solution to organizing NgRx projects; it’s just what has worked for me. I am curious as to what you all think? Please feel free to offer any suggestions, tips, or best practices you’ve learned when building enterprise Angular applications with NgRx and I will update the article to reflect as such. Happy Coding!

* * *

### Additional Resources

I would highly recommend enrolling in the Ultimate Angular courses, especially the NgRx course. It is well worth the money and I have used it as a training tool for new Angular developers. Follow the link below to signup.

[**Ultimate Courses: Expert online courses in JavaScript, Angular, NGRX and TypeScript**
_Expert online courses in JavaScript, Angular, NGRX and TypeScript. Join 50,000 others mastering new technologies with…_ultimatecourses.com](https://ultimatecourses.com/?ref=76683_ttll_neb "https://ultimatecourses.com/?ref=76683_ttll_neb")[](https://ultimatecourses.com/?ref=76683_ttll_neb)