ngrx/store

AOT issue

Bretto opened this issue · 5 comments

I'm submitting a...


[X] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

Where I work we have developed a @Reducer decorator for are Apps.
Here is an example: http://plnkr.co/edit/BeeRiJ9eMmLyXnRGmUnW?p=preview
Its been working with the ngrx store 2.x for a while and in the plnkr it works with Ngrx4.
The thing is, with the cli and Ngrx4 we are getting this error:
Same project: https://github.com/Bretto/ngrx4Reducer
ERROR in Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function (position 20:10 in the original .ts file) ...

Don't be deceived if it works for you when you run the project, the error comes and goes "sporadically".

My Question to you guys, where do I go from there ? Is this an issue for Ngrx or Angular ?

Expected behavior

no error on compilation with AOT

Minimal reproduction of the problem with instructions

working example no AOT: http://plnkr.co/edit/BeeRiJ9eMmLyXnRGmUnW?p=preview
not working example with AOT: https://github.com/Bretto/ngrx4Reducer

What is the motivation / use case for changing the behavior?

We have a large number of application using our @Reducer decorator.

Environment

@angular/cli: 1.0.0
@angular/animations: 4.3.0
@angular/cdk: 2.0.0-beta.8
@angular/common: 4.3.0
@angular/compiler: 4.3.0
@angular/core: 4.3.0
@angular/flex-layout: 2.0.0-rc.1
@angular/forms: 4.3.0
@angular/http: 4.3.0
@angular/material: 2.0.0-beta.8
@angular/platform-browser: 4.3.0
@angular/platform-browser-dynamic: 4.3.0
@angular/router: 4.3.0
@angular/cli: 1.0.0
@angular/compiler-cli: 4.3.0

Browser:

  • Chrome (desktop) version XX
  • Chrome (Android) version XX
  • Chrome (iOS) version XX
  • Firefox version XX
  • Safari (desktop) version XX
  • Safari (iOS) version XX
  • IE version XX
  • Edge version XX

For Tooling issues:
node: 7.0.0
os: linux x64

Others:

Isnt the problem simply that you should export a function instead of a const?
There are already a lot issues with that AOT setup problem.
https://github.com/ngrx/store/search?q=Error+encountered+resolving+symbol+values+statically&type=Issues&utf8=%E2%9C%93

I did go through the AOT do and dont but I can't get the @Reducer to work. So I created the issue. If I missed a simple quick fix for this issue please show me.

I did not test this, but maybe its enough if you change it like this:

const reducers = {
  counter: fromCounter.registerReducer(fromCounter.MyReducers, 0)
};

const developmentReducer = compose(combineReducers)(reducers);

export function reducer(state: any, action: any) {
    return developmentReducer(state, action);
}

instead of

export const reducers = {
  counter: fromCounter.registerReducer(fromCounter.MyReducers, 0)
};

@Bretto @littleStudent This may be a CLI issue since its not consistently happening. With AOT, the metadata in the module has to be statically analyzable, so it needs to be able to read your code without executing it. In your map of reducers, you're calling a function to register the reducer. You can also register your root reducers with an InjectionToken, which would be AOT compatible.

reducers.ts

import { InjectionToken } from '@angular/core';
import { compose, combineReducers, ActionReducerMap } from '@ngrx/store';
import * as fromCounter from './counter';


export interface State {
  counter: fromCounter.State;
}

export const reducers = {
  counter: fromCounter.registerReducer(fromCounter.MyReducers, 0)
};

export const reducerToken = new InjectionToken<ActionReducerMap<State>>('Registered Reducers');

export const reducerProvider = [
  { provide: reducerToken, useValue: reducers }
];

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import {FormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';

import { StoreModule } from '@ngrx/store';
import * as fromRoot from './reducers';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    StoreModule.forRoot(fromRoot.reducerToken),
  ],
  providers: [fromRoot.reducerProvider],
  bootstrap: [AppComponent]
})
export class AppModule { }

Thank you @brandonroberts you saved us :) We were completely stuck. Good Job ! And congratulation on Ngrx4 !