An Angular module can be thought of as a declaration of all the things that would be used/needed in any section of our application. Let us have a look at what's there inside of the AppModule. AppModule is generated by the Angular CLI and it contains everything required for a working application shell:
1//app.module.ts
2import {NgModule} from '@angular/core';
3import {BrowserModule} from '@angular/platform-browser';
4import {AppComponent} from './app.component';
5
6@NgModule({
7 declarations: [AppComponent],
8 imports: [BrowserModule],
9 providers: [],
10 bootstrap: [AppComponent]
11})
12export class AppModule {}
Here, the use of @NgModule annotation actually defines our module.
Additionally, a module is essentially a declaration of all the things which will be used in a section of our app., AppModule is also the section where we are declaring the entire application.
Let us look into the details of what's inside the AppModule. Here we tell our entire app what it needs to use. To begin with, we are declaring our AppComponent. Every component in our app needs to be declared inside an Angular module for us to use it. We have also imported BrowserModule. The browser module is actually the ng module for our browser, as per Angular’s official documentation. So, we can think of that as the middleman between the browser and our application. We can list components, directives, and pipes, which are part of the module, in the "declarations" array. We can import other modules by adding them to the "imports" array. We can list down all the services which are part of our module in the "providers" array. The bootstrap property provides a list of components that should be used as entry points for our app. Most likely, it would have only one element in the array, which is the root component of our app. It tells the bootstrapping method as to which component it should bootstrap ( AppComponent in the above example).
So, now we can see that we have declared all the required things for our application using our AppModule. Over a period of time, as our app grows, we may require additional things to be declared. But, at a high-level, this is how a basic app would have its modules defined.
Well, Angular modules allow us to define a context for compiling our templates. Like when Angular parses HTML templates, it essentially looks up a particular list of components/directives/pipes. Each HTML tag is actually compared to this list to identify if any component should be applied and checks similarly for each attribute. Now, how does Angular know which components/directives/pipes it should look for while parsing the HTML?
This is where Angular modules come in. They are responsible for providing this information in a single place.
So, the following can be said about Angular modules: 1. These are necessary to parse templates, both in the case of Just-In-Time or Ahead-Of-Time Compilation. 2. They act as documentation for grouping together related functionality.
Angular Modules are very different from ES6 modules. An ES6 module is standardization of typical Javascript module which the JS community has been using for several years. They allow you to wrap private details inside a closure and only exposes the public API.
An Angular Module is mainly used to provide compilation context for the template, but it also defines a public API for a subset of functionality plus helps with dependency injection configuration of our app.
Each app will have only one root module. Also each component, directive, and pipe would be associated with only a single module.
Below is an example of an app's root module;
1import { BrowserModule } from '@angular/platform-browser';
2import { NgModule } from '@angular/core';
3import { AppComponent } from './app.component';
4
5@NgModule({
6 declarations: [AppComponent, MyCustomComponent, MyCustomDirective, MyCustomPipe],
7 imports: [BrowserModule],
8 providers: [MyUserService, MyOtherService],
9 bootstrap: [AppComponent]
10})
11export class AppModule {
12}
There are several things which identify the above as being a root module:
Let us try to demo this through a practical application. We'll set up our app such that we can use the Angular module structure which should make things clear. First, we'll generate the core module, core component, and then a shared module using the below commands: ng generate module core ng generate component core
If we set upthe module first, a folder will get created with our core module. Then, when the component is generated, it would get placed inside the same folder and will be declared in the module by our CLI.
ng g module shared We are not planning to do anything with our SharedModule yet, but we'll generate that for future usage.
Next, we have to inform our AppModule about the CoreModule. So, we'll import the CoreModule inside AppModule and then add it to the "imports" array. This is how AppModule should look like:
1import {BrowserModule} from '@angular/platform-browser';
2import {CoreModule} from './core/core.module';
3import {NgModule} from '@angular/core';
4import {AppComponent} from './app.component';
5
6@NgModule({
7 declarations: [AppComponent],
8 imports: [
9 BrowserModule,
10 CoreModule
11 ],
12 providers: [],
13 bootstrap: [AppComponent]
14})
15export class AppModule {}
Now we'll open app.component.html and replace the content with my-app-core. Also “my-app-core” is the selector for our core component. So, essentially, we are just asking our AppComponent to serve CoreComponent. If we run ng serve and hit localhost:4200, we will observe an error in the console saying my-app-core is not a known element and nothing gets displayed on the page. This implies that our application is not aware of any component with the selector “my-app-core”. Let us analyze why that is the case. We declared CoreComponent inside our CoreModule, but we did not expose that to our app. To do that, we'll need to add CoreComponent to the "exports" array inside our CoreModule. So, our CoreModule should look something like below:
1import {NgModule} from '@angular/core';
2import {CoreComponent} from './core.component';
3import {CommonModule} from '@angular/common';
4
5@NgModule({
6 imports: [CommonModule],
7 declarations: [CoreComponent],
8 exports: [CoreComponent]
9})
10export class CoreModule {}
Now, when we run ng serve again and verify in the browser, we would see “My core component is working!”, which represents the content/template of our CoreComponent.
Thus, we saw the use of Angular Modules which allow us to group the overall functionality of our app into logical parts. Modules can also be useful for enabling ahead of time compilation and for lazy-loading.