Angular 4 and ApolloModule.forRoot() result not being seen as correctly annotated as an NgModule
See original GitHub issueI am in the process of migrating my App over to Angular 4 as well as upgrading Apollo from the Angular2Apollo days, and I am almost complete in my progress except for the fact that Angular seems to now choke on the Apollo importation. I get the following error:
Error: Unexpected value '[object Object]' imported by the module 'AppModule'. Please add a @NgModule annotation.
I am using the following setup in my module for imports:
imports: [
ServerModule,
AppModule,
ApolloModule.forRoot(() => client)
],
My client looks like this:
import 'isomorphic-fetch';
import ApolloClient, { createNetworkInterface } from 'apollo-client';
import { Config } from './config.node';
export const client = new ApolloClient({
networkInterface: createNetworkInterface({
uri: Config.apiHost
}),
ssrMode: true
});
The result, when printed, of ApolloModule.forRoot(() => client)
looks fine (it resembles the shape of any other imported module it seems).
I spent a lot of time stepping through the Angular2 compiler and core files, printing out debugging log, but it get very complicated, very quickly.
In Angular core, ReflectionCapabilities.prototype.annotations
function finds all the decorator stuff (preferring the tsickle method of class decoration apparently). This is called from Angular compiler, function NgModuleResolver.prototype.resolve
. Inside that function is the following call findLast(this._reflector.annotations(type), _isNgModuleMetadata)
. This basically reaches in, gets the decorators, etc, etc, and then calls _isNgModuleMetadata
. That function is the following:
function _isNgModuleMetadata(obj) {
return obj instanceof NgModule;
}
Well, obj
(the annotations pulled from the class) is not an instance of NgModule
and so at this point NgModuleResolver.prototype.resolve
returns null
, and this goes all the way up the chain until it’s handled by some code which claims the object being imported is not correctly annotated with NgModule
(the original error at the top of the stack).
I am really unsure of how to proceed here. Perhaps I am missing something? Also, I should note that I am attempting to port my Angular Universal stuff to the new built-in server side rendering so these failures are happening on the Node level as the app attempts to render on the server. I haven’t yet ripped out that code to try and just load this browser-level. This stuff did used to work with Angular Universal however. Also, I am on Angular 4.0.0 which was just released 3 days ago or so.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:2
- Comments:5 (1 by maintainers)
Top GitHub Comments
Hey so this is just yet another issue regarding the fragile ecosystem of web dev. Angular 4 pulled Angular Universal (which was always sort of beta) into it’s main codebase and the documentation is still very sparse. There appears to be a bug where the decorators used for server-side rendering are just different (in terms of JS reference) and this causes the server-side renderer to choke when it sees third party libraries using Angular. I do not believe that the difference is anything but reference based. However if I’m wrong this fix may introduce more bugs, but so far it hasn’t for me (I’m still dealing with other things now though). It is not an issue with Angular version references in third party libs versus the main application as many Stackoverflow/Github answers might indicate, that is another issue that manifests the same way.
Here is the hacky workaround.
Put that in your server-side
app.module
above theNgModule
declaration and after your imports. Obviously you will need to haveNgModule
andPipe
imported for the above code to work.Also, if you are not using Typescript then you can use
.decorators
rather than['decorators']
as the verbose accessor is just to get the TS compiler to shut up.Fixed in v1.0