Introduction
Setting up application structure is one of the most important parts of application development. Because a well structured application allows you to scale/grow application with less effort, saves lot of effort in maintenance of the application, and allows you to locate files and resources easily.
No framework forces to follow how to structure application (how to arrange files in different parts of application), same goes for Angular 2 framework. It doesn’t force developers to structure application, like how to arrange components, directives, pipes, services etc. created by the developer. But the Angular team propose guidelines one must follow for structuring applications in style guide here: StyleGuide
Application Structure
The below diagram is a visual presentation of the structure of an Angular application, which is as per the guidelines from the Angular team.
Application Module — It’s the Start point of Angular application. This is the first module that gets called when the application gets loaded. This module automatically gets created when the application created with the help of Angular-cli. Point of note, all feature modules and core module are going to register themselves in this module.
Core Module — In Angular application, it’s module is going to have application level singleton services (for example, HttpInterceptor
used for intercepting http request, LoggerService
, LoggedInUserService
) or application level component (i.e. Navigation Bar).
Note: Application level component (i.e. Navigation Bar) can also be placed in Application Module.
Core Module have all singleton services, so only the root AppModule (Application Module) should import the CoreModule to make same instance of service in all modules of the application. If a lazy-loaded module imports it too, lazy module will create its own instance of core module services and use that newly created instance of services instead of application level singleton services. To avoid that problem make use of forRoot
method and guard clause, code for that given below. https://angular.io/guide/singleton-services
@NgModule({
imports: [CommonModule]
declarations: [XyzComponent],
exports: [XyzComponent]
})
export class CoreModule {
constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error(
'CoreModule is already loaded. Import it in the AppModule only');
}
}
static forRoot(): ModuleWithProviders {
return {
ngModule: CoreModule,
providers: [
LoggerService ,UserService
]
};
}
}
Shared Module — In angular application, its module going to have all dump Angular Pipes, Directives, Components, Function etc. For example, all who are dumb and receive input from, component which uses it like Extended Form Validation Component (Check Here), Confirmation Model Popup, Formatting Pipes, Validation & Common functions used throughout the application, Directive used by controls etc its like utilities used in application. Point of note, it should not have angular services.
Feature Modules — In angular application, Feature modules are going to have have features which is going to be provided by the application. (for example CustomerModule
, OrdersModule
, ProductsModule
, ShippingModule
).
This feature module is also going to have shared features modules in which is going to be shared between this features module only. For example, ProductDataService
module which is going to be shared between ProductModule
and OrderModule
.
Module Dependency (Flow of Services)
Below diagram shows dependency between modules (for example, it shows the flow of services) discussed above.
Hows modules dependent or Service flow
Feature Modules — these modules are going to consume singleton services form Core Module (via application module in which it is registered) and shared dumb pipes, component, directives, functions from shared module.
Which means Feature modules depends on Core Module and Shared module. For example, service flow from core & shared modules to feature modules. Important point to note here is, Service flows from top towards bottom, not from bottom to top. This means top level Core module, Application module and shared module must not consume service from feature modules.
Core Module — this module is going to consume service from shared module if needed. Mostly it doesn’t need service from shared module but sometimes it needs to access common function or formatting pipes for its component, that’s why diagram has a dotted line.
So service flows from shared module to core module if needed, otherwise this is independent module which provides application level singleton services and component.
Application Module — this module is simple module just going to to have one component to provide start point of application. It’s going to consume services from Core Module and, if needed, consume services from shared module.
Shared Module — It’s utility module. This module have all the dumb angular components, pipes, directives and utility functions. So this module provides its services to all the modules (Application Module, Core Module, Feature Modules) in applications.
But its not going to consume service from other modules.
Conclusion
Angular framework doesn’t force developers to follow discussed structure for developing application. But it is needed when applications are going to grow & developer wants to scale it up, and also helps in identifying different parts of the application in turns helps in maintaining the application. Putting component, service, pipe, directives in proper folder structure its not end of story. To make property structure, the developer must need to setup dependency properly between module (for example, flow of service as discussed).
Note
The above article is based on my reading on angular.io portal and structure applied in my application. Please comment if something is wrong.