0

This is my SharedModule

import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { IconModule } from "@my-app/components/icon/icon.module";
import { RequiredActionDirective } from "@my-app/directives/required-action.directive";

@NgModule({
    imports: [
        CommonModule,
        IconModule
    ],
    declarations: [
        RequiredActionDirective
    ],
    exports: [
        CommonModule,
        IconModule,
        FormsModule,
        ReactiveFormsModule,
        RequiredActionDirective
    ]
})
export class SharedModule { }

Please note that I added to Imports only CommonModule and IconModule. I did it because I'm using those modules in my RequiredActionDirective. But Exports has more Modules because will be used by other modules that will import SharedModule.

Question: am I thinking correctly that I don't need to add Modules to Imports unless I want to use them directly in SharedModule? Or in future there might be some problems of which I am currently not aware because now everything is working properly?

DiPix
  • 5,755
  • 15
  • 61
  • 108

3 Answers3

0

You shouldn't re-export modules without a reason, and only import modules that the current module depends upon. There is no harm to import, but exporting creates a branch in the dependency tree for providers.

Once a module re-exports a module the parent module importing it can not override that import. So this can be a problem in some edge cases.

For example;

NgModule({
     imports: [HttpClientModule],
     provide: { provide: HTTP_INTERCEPTORS, useClass: ExampleInterceptor, multi: true },
     exports: [HttpClientModule]
})
export class SharedModule {}

Now the AppModule can not provide another interceptor.

NgModule({
     imports: [SharedModule],
     provide: { provide: HTTP_INTERCEPTORS, useClass: AppInterceptor, multi: true }
     // ^^ interceptor is ignored
})
export class AppModule {}

The reason is that the HttpClientModule becomes declared in the provider tree at the SharedModule level and resolves all HTTP_INTERCEPTORS from that point down.

The requirement is that the AppModule should import the HttpClientModule first, and then the SharedModule.

NgModule({
     imports: [HttpClientModule, SharedModule],
     provide: { provide: HTTP_INTERCEPTORS, useClass: AppInterceptor, multi: true }
})
export class AppModule {}

Now the HttpClientModule is declared at the AppModule level and resolves all providers downwards including the SharedModule. The order in the imports: [] array isn't important.

Reactgular
  • 52,335
  • 19
  • 158
  • 208
  • I agree but your case takes into account providers which is a different kettle of fish. The assumption of SharedModule is to aggregate most common modules that I want to use almost in each module. And I was asking whether need to import before I'll export them further, but it seems that I don't need to. :) – DiPix Jan 14 '20 at 20:24
0

An NgModule can export a combination of its own declarations, selected imported classes, and imported NgModules.

Don't bother re-exporting pure service modules. Pure service modules don't export declarable classes that another NgModule could use. For example, there's no point in re-exporting HttpClientModule because it doesn't export anything. Its only purpose is to add http service providers to the application as a whole.

0

Yes, you are correct. You could even technically get rid of CommonModule from imports in SharedModule, but there is a high chance that some of the stuff may need it now or later, so I would not recommend it.

Also in terms of CommonModule: Notice that CommonModule is automatically added to imports when generating new module using CLI. It means that it is available right away, however it can be safely deleted since we already export it in SharedModule. It can be useful when optimizing redundant imports, but it's really up to you.