In general, all services added to the providers array of any module are application-wide singletons - meaning they are added to the root injector automatically. There is no need to explicitly add them to the providers array of your AppModule.
That means that when you import a module (or another module imports a module) that has the providers array populated, the services they provide can be injected into any injectable constructor - regardless of where it is. Just import the service, and add it to an injectable constructor.
Now, I say "in general" because for the most part that's true. The only case where it is different is when the module is a lazy loaded module (i.e. loading lazy-loaded routes). Lazy-loaded modules have their own root scope. If you treat that as the exception, it all makes sense.
So to answer your question:
Prefer module.forRoot()
if it has such a method. This returns a module with services, which will get bootstrapped with the root injector.
@NgModule({
// forRoot ensures that services are added to root injector
imports: [ThirdPartyModule.forRoot()],
exports: [],
declarations: [...],
providers: [],
})
export class AppModule{ }
If there is no "forRoot" method, then just import the module into AppModule. Likely, the module has services intended to be registered with the root injector.
@NgModule({
imports: [ThirdPartyModule],
exports: [],
declarations: [...],
providers: [],
})
export class AppModule{ }
If you need to import the module from a FeatureModule (or a SharedModule) because you want to leverage the components, directives, and pipes contained within it, you should use the forChild()
method if it has one.
@NgModule({
// does not include any services. You still need to import
// .forRoot() in the AppModule
imports: [ThirdPartyModule.forChild()],
exports: [],
declarations: [...],
providers: [],
})
export class FeatureModule { }
If the author of the module has not provided a forRoot()
or forChild()
method, it may be it was never intended to be imported by any module other than the AppModule.
The author of the module may have decided to include services in the module, but by default chose not to add it to the providers array. In that case its up to you to add it to a providers array of a module (services will have root scope), or add it to a component's providers array (services will have component scope).