Check out myAngular article series with live demos and Facebook group Angular - Advanced Topics

Integrating NgRx with the Closure Compiler

Torgeir "Tor" Helgevold
- JavaScript Developer and Blogger
Published: Wed Jun 07 2017

In this post I will show how to integrate a simple ngrx sample with the Closure compiler.

I have heard a lot of people talk about ngrx, but I've never actually given it a try until today.

Since I am starting from scratch, I figured it made sense to start with the default ngrx demo application.

The idea behind the demo app is to use ngrx to manage the state of a simple counter.

I took the original code and modified it slightly as seen below:

app.module.ts
import { NgModule } from '@angular/core' import { BrowserModule } from '@angular/platform-browser'; import { StoreModule } from '@ngrx/store'; import { counterReducer } from './counter'; import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule, StoreModule.forRoot({counter: counterReducer}) ], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule {}

AppModule is where I configure the StoreModule and set up a simple “Store”.

app.component.ts
import { Store } from '@ngrx/store'; import { INCREMENT, DECREMENT } from './counter'; import { Observable } from 'rxjs/Observable'; import { Component } from '@angular/core'; interface AppState { counter: number; } @Component({ selector: 'my-app', template: ` <button id="increment" (click)="increment()">Increment</button> <div id="value">Current Count: {{ counter | async }}</div> <button id="decrement" (click)="decrement()">Decrement</button> ` }) export class AppComponent { counter: Observable<number>; constructor(private store: Store<AppState>){ this.counter = store.select(state => state.counter); } increment(){ this.store.dispatch({ type: INCREMENT }); } decrement(){ this.store.dispatch({ type: DECREMENT }); } }

In AppComponent I set up some basic user interactions to increment/decrement the counter. I also wire up the store API to keep track of counter state.

There is one very important point to make about the store.select api here.

The alternative store.select('counter') API is not compatible with Closure compiler property mangling.

Why not use the string based select API?

After Closure compilation the original “counter” property name has likely been renamed to a shorter name. As a result, “counter”, is no longer a valid name to reference the store.

Sticking to the object notation like I am doing in this sample is safe though since both counter references are renamed “together”.

counter.ts
import { ActionReducer, Action } from '@ngrx/store'; export const INCREMENT = 'INCREMENT'; export const DECREMENT = 'DECREMENT'; export function counterReducer(state: number = 0, action: Action) { switch (action.type) { case INCREMENT: return state + 1; case DECREMENT: return state - 1; default: return state; } }

I have put the code on Github in case you are interested in trying it out.

Build the project by running:

npm run build:ngrx && npm run serve

A few notes:

This sample is using the ngrx nightly build since the Angular 4 version is not yet available on npm.

If you liked this article, share it with your friends on social media:

We also have a new Facebook group about advanced Angular topics.

I invite you to follow me on twitter