ngx-eager-provider-loader
v4.0.2
Published
Eager provider / service loader for Angular 2+
Downloads
16
Maintainers
Readme
IMPORTANT: this package has been merged into
ngx-inject
. Consequently, thengx-eager-provider-loader
package is deprecated: it will not receive any updates! It is therefore recommended to upgrade tongx-inject
. That package offers an improved API for eager loading and has better support for Angular's AoT compiler.
Eager provider / service loader for Angular 4+
This module for Angular 4+ enables your application to eager load providers if necessary. By default Angular loads all providers in a lazy manner, i.e. only whenever they are used by other components or services that are instantiated. While this is actually a good thing and is desirable for the majority of the cases, sometimes you might have a valid reason to have your provider(s) loaded directly. This is the case in particular for providers that play an active role in your application, but are never referenced by other components or providers. For more information when this is useful and the rationale for this package see the following article: Eager loading in Angular 2
Installation
To use this module in your application, you first have to install the NPM package, which can be done using the following command:
npm install ngx-eager-provider-loader --save
When installed, this package provides an UMD bundle (bundles/ngx-eager-provider-loader.umd.js
), that can be
referenced from the module loader used by your application.
For example when using SystemJS, add the following entries to the config file:
To the map
option:
'ngx-eager-provider-loader': 'node_modules/ngx-eager-provider-loader/bundles/'
To the packages
option:
'ngx-eager-provider-loader': {
main: 'ngx-eager-provider-loader.umd.js',
defaultExtension: 'js'
}
In addition to the UMD bundle, the package is also provided in ESM module format.
This format is more convenient to use when you want to make use of tree shaking.
The ESM bundle is provided in both ES5 (bundles/ngx-eager-provider-loader.es5.js
) and ES6
(bundles/ngx-eager-provider-loader.js
).
Usage
After having installed the NPM package and updated the configuring of the module loader, you can use module within your
Angular application.
To enable eager loading for your provider(s), first find the @NgModule
class in which the provider should be loaded.
Usually this is the same module in which the provider is defined, however it could be different module if you want to
eagerly load a provider that is defined in another module which you cannot modify.
Once you've found the module in which the provider should be loaded, import the EagerProviderLoaderModule
:
import { EagerProviderLoaderModule } from 'ngx-eager-provider-loader';
@NgModule({
imports: [ EagerProviderLoaderModule ]
})
export class AppModule { /* ... */ }
By importing the EagerProviderLoaderModule
your application will load all providers on startup that have been
registered as eagerly loaded providers.
Although not strictly necessary, it is best to import this module in every module in which you mark providers for eager
loading.
This improves the reusability of those modules, since they don't depend on other modules to import the
EagerProviderLoaderModule
.
After having imported the EagerProviderLoaderModule
, you need to define which providers you want to have loaded
eagerly.
This can be done using the following functions:
eagerProviderRegistration(token: any): Provider
- Registers a previously defined provider (usually defined in another module) for eager loading. The result is aProvider
which you have to add theproviders
property of theNgModule
decorator.eagerProvider(provider: Provider): Provider[]
- Registers the specified provider and marks it for eager loading. The result is an array consisting of two providers which need to be added to theproviders
property of theNgModule
decorator. Use this function if you simultaneously wish to define a new provider and have it loaded eagerly.eagerProviders(...providers: Provider[]): Provider[]
- Accepts an arbitrary number of providers which will be returned as an array of providers that are marked for eager loading.
An example usage for each of these functions is shown in the code example below:
import { OtherModule, providerFromOtherModule } from './modules/other-module/index';
import { RouteLogger, MyService, AwesomeMyServiceImpl, AnotherCoolService, BadAssService } from './index';
import {
EagerProviderLoaderModule,
eagerProviderRegistration,
eagerProvider,
eagerProviders,
} from 'ngx-eager-provider-loader';
@NgModule({
imports: [
OtherModule,
EagerProviderLoaderModule
],
providers: [
// Mark the provider identified by the token `providerFromOtherModule` for eager loading.
// Note that the provider is listed in the providers of the `OtherModule`, so we only have
// to mark it for eager loading.
eagerProviderRegistration(providerFromOtherModule),
// Defines the provider `RouteLogger` and marks it for eager loading. Note that the expression
// below is equivalent to: ...[RouteLogger, eagerProviderRegistration(RouteLogger)]
...eagerProvider(RouteLogger),
// Defines three providers and marks them for eager loading.
...eagerProviders(
{ provide: MyService, useClass: AwesomeMyServiceImpl },
AnotherCoolService,
BadAssService
)
]
})
export class AppModule { /* ... */ }
Ahead-of-Time (AoT) compilation support
Unfortunately when using AoT you cannot use function calls for the @NgModule
metadata, hence it is not possible to use
the eagerProvider*
functions to generate the eager provider registrations.
This means you'll have to define these registration entries manually in the providers list of your module.
To do so, first import the EAGER_PROVIDER
token.
With this token you can register a provider for eager loading.
This is illustrated for the UserService
in the following example:
import { EagerProviderLoaderModule, EAGER_PROVIDER } from 'ngx-eager-provider-loader';
import { UserService } from './shared/user.service';
@NgModule({
imports: [ EagerProviderLoaderModule ],
providers: [
UserService,
{ provide: EAGER_PROVIDER, useValue: UserService, multi: true }
]
})
export class AppModule { /* ... */ }
Note that you have to define the provider twice: once as you would normally define it and once as the value of multi
provider for the EAGER_PROVIDER
token.
If you omit the normal provider definition, then Angular will complain about not having a provider for whatever value
you specified in the useValue
property.
It is important to use the useValue
property and not the useClass
property, since this will result in a runtime DI
error, which the eager provider loader cannot prevent.
Also make sure to always set the multi
property to true
.
Lazy module loading support
The eager provider loader package has support for lazy loaded modules. However, before using eager provider loading for lazy loaded modules ask yourself whether it actually makes sense that the provider should only be loaded when the module itself is loaded. In most cases I expect that the provider must be loaded on application startup anyway. If so, you can simply move the eager loading registration to the module that is being used to bootstrap the application (or to another imported module).
If you still feel that you need eager provider loading for a lazy loaded module, then you can use it in the same way as
you would for modules that get loaded on application startup.
Just don't forget to import the EagerProviderLoaderModule
within these lazy loaded modules.
Note that there is a small difference for eager loaded providers compared to normal providers which are defined in lazy loaded modules. Normal providers for lazy loaded modules might be instantiated multiple times by Angular itself, e.g. when changing routes back and forth to lazy loaded routes. The eager provider loader, however, makes sure that providers marked for eager loading within these lazy loaded modules will only be instantiated once.
Troubleshooting
In case your service does not get loaded on application startup, check the following:
- You have marked the provider for eager loading with one of the following functions:
eagerProviderRegistration
,eagerProvider
, oreagerProviders
. When using AoT, instead of these functions, add a multi provider for theEAGER_PROVIDER
token. - If you manually mark a provider for eager loading, either using the
eagerProviderRegistration
function or theEAGER_PROVIDER
token, make sure that provider itself is also added to the providers list of the module (or imported modules). - The provider is marked for eager loading in a lazy loaded module that simply hasn't been loaded yet.
- At least one of the modules that gets loaded on application startup adds
EagerProviderLoaderModule
to the import list. If you use lazy loaded modules, then those also need to importEagerProviderLoaderModule
.