I am trying to inject the HttpClientModule
manually which runs outside independent(may be!) from app. Before static injector i was using reflective injector
StaticInjector
is supposed to be a replacement for ReflectiveInjector
that doesn't require Reflect
API. getAnnotations
is low-level hack and it likely won't work with StaticInjector
in its current state. Also, getAnnotations
is incompatible with AOT by design.
It's preferable to create an injector for a module the way it is supposed to be done by the framework, i.e. a module should be bootstrapped. Since there is no component to bootstrap, ngDoBootstrap
hook should be specified.
By default, bootstrap process is asynchronous. If this is not a problem, initialization promise can be chained to get module instance.
An example:
@NgModule({
imports: [BrowserModule, HttpClientModule]
})
export class MyHttpModule {
static httpClient?: HttpClient;
httpClient?: HttpClient;
constructor(private _injector: Injector) {}
ngDoBootstrap() {
MyHttpModule.httpClient = this.httpClient = this._injector.get(HttpClient);
}
}
platformBrowserDynamic().bootstrapModule(MyHttpModule)
.then((myHttpModule: NgModuleRef<MyHttpModule>) => {
// HttpClient instance is available here
const httpClient = myHttpModule.instance.httpClient;
httpClient.get('/foo', { responseType: 'text'}).subscribe();
})
.catch(err => console.error(err));
This approach is compatible with both JIT and AOT (which is good for using HttpClient
apart from Angular because this lowers the footprint significantly) out of the box.
Otherwise custom synchronous bootstrap routine can be performed instead. This is possible because HttpClient
doesn't require asynchronous initialization.
An example:
@NgModule({
imports: [BrowserModule, HttpClientModule]
})
export class MyHttpModule {
static httpClient?: HttpClient;
constructor(public _injector: Injector) {
MyHttpModule.httpClient = this._injector.get(HttpClient);
}
ngDoBootstrap() {}
}
const platform = platformBrowserDynamic();
const compiler = platform.injector.get(CompilerFactory).createCompiler();
const moduleFactory = compiler.compileModuleSync(MyHttpModule);
platform.bootstrapModuleFactory(moduleFactory)
.catch(err => console.error(err));
const httpClient = MyHttpModule.httpClient;
httpClient.get('/foo').subscribe();
This will work in JIT, but AOT can't be efficiently handled by Angular CLI in the code above. The code involves the compiler, which isn't needed in AOT compilation mode (that's its purpose). In order to use AOT, it should be compiled with ngc
compiler and a separate entry point that uses module factories should be created. Bootstrap routine becomes even simpler, because it doesn't involve compiler, something like:
...
import { platformBrowser } from '@angular/platform-browser-dynamic';
import { AppModuleNgFactory } from '<path to aot>/src/app/my-http-module.ngfactory';
const platform = platformBrowser();
platform.bootstrapModuleFactory(AppModuleNgFactory)
.catch(err => console.error(err));
const httpClient = MyHttpModule.httpClient;
httpClient.get('/foo').subscribe();