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:

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”.

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 = => state.counter); } increment(){{ type: INCREMENT }); } decrement(){{ 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 api here.

The alternative'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”.

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.