Angular (2+): Core vs Shared Modules
Angular: Core vs Shared Modules
If you're new to Angular, you might get confused between these two commonly used modules. So what do you put in either components?
What goes in CoreModule?
Your CoreModule contains code that will be used to instantiate your app and load some core functionality.
The clearest and most important use of the CoreModule is the place to put your global/HTTP services. The idea is to make sure only one instance of those services will be created across the entire app. The CoreModule, by convention, is only included in your entire app once in AppModule (only in the "import" property of the "@NgModule()" decorator inside your main app.module.ts, not in any other module's "import") and this will ensure services inside it will be only created once in the entire app. This is especially important if you intend to lazy-load your feature modules. Since lazy-loaded modules are loaded on demand (eg when you access the route using the lazy-loaded feature), you could end up creating new instances of supposedly singleton services if you don't put them in CoreModule.
Important single use components/classes can also go in the CoreModule. Good candidates are global components that go in your main AppComponent. For example, if your app has one global header component, you can add the code for HeaderComponent in CoreModule (and then put the HeaderComponent class in the "exports" property of CoreModule's "@NgModule()" decorator so AppModule which imports CoreModule can use it). This allows you to keep this global component in one spot and make sure there's only have one copy of it across the app.
The CoreModule should also be used to export any third party module that is required in the AppModule. The idea is to keep AppModule as lean as possible. Examples are BrowserAnimationsModule (as of time of this writing, this should only be imported once throughout the whole app), Angulartics2Module.
The CoreModule should also be used to export any third party module that is required in the AppModule. The idea is to keep AppModule as lean as possible. Examples are BrowserAnimationsModule (as of time of this writing, this should only be imported once throughout the whole app), Angulartics2Module.
What goes in SharedModule?
You SharedModule similarly contains code that will be used across your app and Feature Modules. But the difference is that you will import this SharedModule into the specific Feature Modules as needed. You DO NOT import the SharedModule into your main AppModule or CoreModule.
Common templates components should also go in the SharedModule. An example would be a global button component, eg ButtonComponent. These template components should be "dumb components" in that they should not expect or interact with any specific form of data. You should define a template, style, an "@Output()" event property, and maybe a "@Input()" string property for text inside the button so you can pass in whatever event you want to fire when a user clicks the button. Now all your buttons can look uniform across the app! Of course, this is an architectural decision left up to your discretion. It will make for easier unit testing and separation-of-concerns to follow the pattern though.
Commonly used pipes (ie filters) and directives should go in your SharedModule, too. Prime examples would be custom string/date filters.
In your SharedModule's main file (eg "shared.module.ts"), you might also export the commonly used Angular modules (eg "CommonModule" from "@angular/common" for the *ngIf structure directive or the "FormsModule" from "@angular/forms" for the [(ngModel)] directive) so they can be easily used across your app, without importing them in every Feature Module. Note, this might be introduce unnecessary loading speed if you don't use those modules/directives a lot; if that's the case, you might want to do it the old fashioned way and import these Angular modules only in the Feature Modules that use them.
Summary
To summarize, your CoreModule should definitely contain your singleton services, single-instance components, and export any third-party modules needed in AppModule. The SharedModule should contain common components/pipes/directives and also export commonly used Angular modules (like "CommonModule" from "@angular/common" for *ngIf directive). You should have "dumb components" in SharedModule.
For further clarification, reference Angular's tutorials on modules or their style guide.
This was very helpful! Thank you.
ReplyDeleteYou're welcome!
DeleteThanks for the good post.
ReplyDeleteYou're welcome!
Deletethanks)
ReplyDeleteYW!
DeleteHi Jing - thanks for the article! I have a question - in the Angular.io styleguide, they say:
ReplyDelete"Do import all modules required by the assets in the CoreModule (e.g. CommonModule and FormsModule)."
However, in other places (including your post), it seems as though the CommonModule, FormsModule, etc should be imported / exported in the SharedModule and imported into feature modules. I've found competing opinions / examples on this.
Is there a reason that the Angular documents directly contradicts this advice?
It depends on where and how you will use these modules. The point of SharedModule is a dumping grounds for all modules that will be used by all your FeatureModules. If you will make use of CommonModule (eg *ngIf directive) in all of your FeatureModules (which you likely will), then you should include it in SharedModule.
DeleteI think the styleguide for CoreModule didn't want to consider the existence of SharedModule due to separation of concerns (eg don't put SharedModule-related information into CoreModule documentation).
Another relevant point is instances of modules created with lazy-loading. Note, if you don't make sure of lazy-loading, this point can be ignored. Lazily-loaded FeatureModules will generate new instances of whatever modules they import (eg modules in SharedModule). So if you need one instance of a module in your whole app, you have to put it into CoreModule, which is only loaded once in your entire app. An example of this is the BrowserAnimationModule from Angular*, which will throw an exception if you try to import it multiple times. This concern doesn't matter for modules like CommonModule or FormModule because they provide directives/bindings/classes that don't affect use if the functionality comes from different instances of their respective containing-modules.
* This was true the last time I played with that module.
Hey - thanks for the quick reply! Great points, that makes more sense to me now. Thanks also for the heads up regarding lazy-loaded modules - that's something I've just started playing with and I'll make a note to consider how I intend to use a module before deciding whether to put it in Core or Shared.
DeleteCheers :)
Jake
Thanks admin, your blog gives lots of information to me. Continue sharing more like this.
ReplyDeleteAngularjs Training | Angular 2 Training in Chennai | Angularjs Training in Chennai
It is very nice post for learning Angular and web development. Thanks for sharing this useful blog.
ReplyDeleteAngularJS Training Institute in Chennai | Angular 2 Training in Chennai
Amazing Blog.The content is very useful. Pls update more.
ReplyDeleteAngularjs Training in Chennai
Angularjs course in Chennai
Angular 2 Training in Chennai
Angular 4 Training in Chennai
Angular Training in Chennai
This is really an good information with lot of valuable information.
ReplyDeleteAngularJS training in chennai | AngularJS training in anna nagar | AngularJS training in omr | AngularJS training in porur | AngularJS training in tambaram | AngularJS training in velachery
Hi admin, I created one module called dynamic form and try to use it in 2 modules called x and y module, When I'm importing dynamic form module into x module it's working fine and same dynamic module I'm try to use in y module it's showing blank page without throwing any error. Can you please help me out. Thanks in advance
ReplyDelete