In this tutorial, we learn how best to organize the folder structure of an Angular Application. Finding the right folder structure for your real-life Angular application is very important. As you add more and more features to your App locating a certain component or file becomes messy if you do not have the proper structure in place.
Table of Contents
Folder for each Angular Module
The Angular uses the concept of Angular Modules to group together the related features. This gives us a nice starting point to organize the folder structure. Each Module should get its own folder named after the Module Name.
The Angular does not make any distinction between the Modules. but based on how we make use of modules, we can classify our modules into the following four categories
- Root Module
- Feature Module
- Shared Module
- Core Module
Root Module
The Angular requires one module to be loaded as the application starts. We call this as root module. The root module loads the root component and all other modules
The root module is conventionally called as AppModule
and created under the /src/app
.folder
Feature Modules
The Features module implements a specific feature of the Application. All the components, pipes & directives which implement the feature become part of the module.
Further Reading on Angular Modules
All the components belonging to Feature Modules must be placed inside a directory named after the module. For Example /src/app/<ModuleName>
. By doing so, we make it easy to search a component belonging to the module
You can create subfolders for directives, pipes under the module folder
You can create a components folder and put all your components there. Or create a subfolder for each component under the components folder
Another option to create a pages
folder. Each route is a page. The folder is named after the route path. The route might contain more than one component. All of them placed under that page folder. The shared components can be placed under the separate components folder.
The idea of pages is borrowed from this article on Medium
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ├── src │ ├── app │ │ ├── admin │ │ │ ├── components │ │ │ │ ├── shared.component.ts │ │ │ ├── directives │ │ │ │ ├── first.directive.ts │ │ │ │ ├── another.directive.ts │ │ │ ├── pages │ │ │ │ ├── dashboard │ │ │ │ │ ├── dashboard.component.ts │ │ │ │ ├── rights │ │ │ │ │ ├── rights.component.ts │ │ │ │ ├── user │ │ │ │ │ ├── user.component.ts │ │ │ │ ├── admin.component.ts │ │ │ │ ├── admin.component.html │ │ │ │ ├── admin.component.css │ │ │ │ ├── index.ts │ │ │ ├── pipes │ │ │ │ ├── first.pipe.ts │ │ │ │ ├── another.pipe.ts │ │ │ ├── admin.module.ts │ │ │ ├── admin.routing.module.ts │ │ │ ├── index.ts |
There are many components, directives & pipes, which we may like to share across various modules. All these components should go into the shared module.
The shared module and must declare the components, pipes, and directives using the declarations
metadata and export it using the exports
metadata
Other Modules can import the shared modules and use the exported components, directives & pipes
The Services must not be defined here. Since the shared modules are imported everywhere, it may create a new instance of the service if it is imported in the lazy loaded modules.
The Shared module must be created under the folder /src/app/shared
folder.
The Shared module should not have any dependency on any of the other modules in the application.
The commonly required angular modules like ( CommonModule, FormsModule, etc) or third party modules can be imported here and re-exported. The other module importing the shared module does not have to import those modules.
You can follow the following folder structure, where each shared feature is created in its own own folder.
1 2 3 4 5 6 7 8 9 10 11 12 13 | ├── src │ ├── app │ │ ├── shared │ │ │ ├── layout │ │ │ │ ├── footer │ │ │ │ │ ├── footer.component.ts │ │ │ │ │ ├── footer.component.html │ │ │ │ ├── header │ │ │ │ │ ├── header.component.ts │ │ │ │ │ ├── header.component.html │ │ │ ├── index.ts |
Or you can create folders like components, pipes, directives as shown below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ├── src │ ├── app │ │ ├── shared │ │ │ ├── components │ │ │ │ ├── footer │ │ │ │ │ ├── footer.component.ts │ │ │ │ │ ├── footer.component.html │ │ │ │ ├── header │ │ │ │ │ ├── header.component.ts │ │ │ │ │ ├── header.component.html │ │ │ ├── pipes │ │ │ │ ├── pipe1 │ │ │ │ │ ├── pipe1.pipe.ts │ │ │ ├── index.ts |
Core Module
The Services shared across the application must become part of the CoreModule
. The user authentication services, services that fetch data are examples of such services.
The Services usually needs to be Singleton, Only one instance of the Service must exist. Providing it in CoreModule
ensures that the services remain singleton
The core module must be imported only in the root module. Other modules must not import the core modules. You can use the following code to stop the other modules from importing the core module.
1 2 3 4 5 6 7 8 9 10 11 | @NgModule({}) export class CoreModule { constructor(@Optional() @SkipSelf() core:CoreModule ){ if (core) { throw new Error("You should import core module only in the root module") } } } |
The CoreModule
must be created under the folder /src/app/core
folder.
Under the core folder, you can create subfolders for each service under the services folder.
Folder Structure Example
Let us build a simple with shared, core and feature module
Create a new application using ng new
1 2 3 | ng new --routing --style css ModuleDemo |
Feature Modules
Now let us create three feature modules AdminModule
, GthubModule
& HomeModule
Admin Module
Create the admin
folder under /src/app
folder
Under the /src/app/admin
folder create the admin.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import { NgModule } from '@angular/core'; import { AdminRoutingModule } from './admin.routing.module'; import { UserComponent,RightsComponent,DashboardComponent, AdminComponent } from './pages'; @NgModule({ declarations: [UserComponent,RightsComponent,DashboardComponent,AdminComponent], imports: [ AdminRoutingModule, ], providers: [], }) export class AdminModule { } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { UserComponent , RightsComponent ,DashboardComponent, AdminComponent } from './pages'; const routes: Routes = [ { path: 'admin', component: AdminComponent, children :[ { path: 'dashboard', component: DashboardComponent}, { path: 'user', component: UserComponent}, { path: 'rights', component: RightsComponent}, ] }, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class AdminRoutingModule { } |
AdminModule
has four pages. A admin
page is the root page. You can create it under the pages
folder.
1 2 3 4 5 6 7 8 9 10 11 | import { Component} from '@angular/core'; @Component({ selector: 'app-admin', templateUrl: './admin.component.html', styleUrls: ['./admin.component.css'] }) export class AdminComponent { } |
1 2 3 4 5 6 7 8 | <ul> <li><a routerLink="dashboard">dashboard</a></li> <li><a routerLink="user">User</a></li> <li><a routerLink="rights">Rights</a></li> </ul> <router-outlet></router-outlet> |
The admin page has three pages under it. dashboard, rights & user. Hence create a subfolder for all these under the pages
folder.
1 2 3 4 5 6 7 8 9 10 | import { Component } from '@angular/core'; @Component({ template: `<h1>Dashboard Component</h1>`, }) export class DashboardComponent { title = ''; } |
1 2 3 4 5 6 7 8 9 10 | import { Component } from '@angular/core'; @Component({ template: '<h1>Rights Component</h1>', }) export class RightsComponent { title = ''; } |
1 2 3 4 5 6 7 8 9 10 | import { Component } from '@angular/core'; @Component({ template: '<h1>User Component</h1>', }) export class UserComponent { title = ''; } |
1 2 3 4 5 6 | export * from './dashboard/dashboard.component'; export * from './rights/rights.component'; export * from './user/user.component'; export * from './admin.component'; |
1 2 3 4 | export * from './pages'; export * from './github.module'; |
Github Module
The GithubModule
retrieves the list of repos from the GitHub repository for a given user. The module is created under the folder github
. The components is created under the the pages
folder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { GitHubService } from '../../../core'; import { repos} from '../../../core'; @Component({ templateUrl: './repo-list.component.html', }) export class RepoListComponent { userName: string ="angular" repos: repos[]; loading: boolean=false; errorMessage; constructor(private githubService: GitHubService) { } public getRepos() { this.loading=true; this.errorMessage=""; this.githubService.getRepos(this.userName) .subscribe((response) => {this.repos=response;}, (error) => {this.errorMessage=error; this.loading=false; }, () => {this.loading=false;}) } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <h1 class="heading"><strong>HTTP </strong>Demo</h1> <div class="form-group"> <label for="userName">GitHub User Name</label> <input type="text" class="form-control" name="userName" [(ngModel)]="userName"> </div> <div class="form-group"> <button type="button" (click)="getRepos()">Get Repos</button> </div> <div *ngIf="loading">loading...</div> <div *ngIf="errorMessage" class="alert alert-warning"> <strong>Warning!</strong> {{errorMessage}} </div> <div class='table-responsive'> <table class='table'> <thead> <tr> <th>ID</th> <th>Name</th> <th>HTML Url</th> <th>description</th> </tr> </thead> <tbody> <tr *ngFor="let repo of repos;"> <td>{{repo.id}}</td> <td>{{repo.name}}</td> <td>{{repo.html_url}}</td> <td>{{repo.description}}</td> </tr> </tbody> </table> </div> |
1 2 3 | export * from './repolist/repo-list.component'; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { RepoListComponent } from './pages'; const routes: Routes = [ { path: 'github', component: RepoListComponent, children :[ { path: 'list', component: RepoListComponent}, ] } ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class GithubRoutingModule {} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import { NgModule } from '@angular/core'; import { GithubRoutingModule } from './github-routing.module'; import { RepoListComponent } from './pages'; import { SharedModule } from '../shared'; @NgModule({ imports: [ GithubRoutingModule,SharedModule ], providers: [ ], declarations: [RepoListComponent] }) export class GithubModule { } |
1 2 3 4 | export * from './pages'; export * from './github.module'; |
Home Module
This module contains three components, HomeComponent
, ContactUsComponent
and AboutUsComponent
1 2 3 4 5 6 7 8 9 10 | import { Component } from '@angular/core'; @Component({ template: `Anout Us`, }) export class AboutUsComponent { } |
1 2 3 4 5 6 7 8 9 10 | import { Component } from '@angular/core'; @Component({ template: `Contact Us`, }) export class ContactUsComponent { } |
1 2 3 4 5 6 7 8 9 10 | import { Component } from '@angular/core'; @Component({ template: `<h1> Welcome To Module Demo</h1>`, }) export class HomeComponent { } |
1 2 3 4 5 | export * from './aboutus/about-us.component'; export * from './contactus/contact-us.component'; export * from './home/home.component'; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { AboutUsComponent,ContactUsComponent,HomeComponent } from './pages'; const routes: Routes = [ { path: '', component: HomeComponent}, { path: 'contactus', component: ContactUsComponent}, { path: 'aboutus', component: AboutUsComponent}, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class HomeRoutingModule {} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import { NgModule } from '@angular/core'; import { HomeRoutingModule } from './home-routing.module'; import { AboutUsComponent,ContactUsComponent,HomeComponent } from './pages'; import { SharedModule } from '../shared'; @NgModule({ imports: [ HomeRoutingModule,SharedModule ], providers: [ ], declarations: [AboutUsComponent,ContactUsComponent,HomeComponent] }) export class HomeModule { } |
1 2 3 4 | export * from './pages'; export * from './home.module'; |
Core Module
The CoreModule
contains application-wide singleton services. In this example app, it contains a GitHubService
which retrieves the list of repositories of a given user.The CoreModule
is created under the folder src/app/core
.
All services are created under the src/app/core/services
folder. You may also create subfolder for each service.
1 2 3 4 5 6 7 8 | export class repos { id: string; name: string; html_url: string; description: string; } |
1 2 3 | export * from './repos'; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { repos} from '../models'; @Injectable() export class GitHubService { baseURL:string="https://api.github.com/"; constructor(private http:HttpClient){ } getRepos(userName:string): Observable<repos[]> { return this.http.get<repos[]>(this.baseURL + 'users/' + userName + '/repos') } } |
1 2 3 | export * from './github.service'; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import { NgModule, Optional, SkipSelf } from '@angular/core'; import { GitHubService } from './services/github.service'; @NgModule({ imports: [ ], providers: [ GitHubService ], declarations: [] }) export class CoreModule { constructor(@Optional() @SkipSelf() core:CoreModule ){ if (core) { throw new Error("You should import core module only in the root module") } } } |
1 2 3 4 5 | export * from './core.module'; export * from './services'; export * from './models'; |
Our Shared Module contains HeaderComponent
& FooterComponent
, which is used by the root module.
1 2 3 | <p>(c) All Rights Reserved</p> |
1 2 3 4 5 6 7 8 9 10 | import { Component } from '@angular/core'; @Component({ selector: 'app-footer', templateUrl: './footer.component.html' }) export class FooterComponent { } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <ul> <li> <a class="navbar-brand" routerLink="/">home</a> </li> <li> <a class="navbar-brand" routerLink="/github/list">GitHub</a> </li> <li> <a class="navbar-brand" routerLink="/admin">Admin</a> </li> <li> <a class="navbar-brand" routerLink="/aboutus">About</a> </li> <li> <a class="navbar-brand" routerLink="/contactus">Contact</a> </li> </ul> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ul { list-style-type: none; margin: 0; padding: 0; overflow: hidden; background-color: #333333; } li { float: left; } li a { display: block; color: white; text-align: center; padding: 16px; text-decoration: none; } li a:hover { background-color: #111111; } |
1 2 3 4 5 6 7 8 9 10 11 | import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.css'] }) export class HeaderComponent { } |
1 2 3 4 | export * from './footer/footer.component'; export * from './header/header.component'; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { RouterModule } from '@angular/router'; import { HeaderComponent, FooterComponent } from './layout'; @NgModule({ imports: [ CommonModule, FormsModule, ReactiveFormsModule, HttpClientModule, RouterModule ], declarations: [ HeaderComponent,FooterComponent ], exports: [ CommonModule, FormsModule, ReactiveFormsModule, HttpClientModule, RouterModule, HeaderComponent,FooterComponent ] }) export class SharedModule { } |
1 2 3 4 | export * from './shared.module'; export * from './layout'; |
Final Folder Structure
The following list shows the final structure of our application. You can change/fine-tune them as per the requirement of your project.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | ├── src │ ├── app │ │ ├── admin │ │ │ ├── directives │ │ │ ├── pages │ │ │ │ ├── dashboard │ │ │ │ │ ├── dashboard.component.ts │ │ │ │ ├── rights │ │ │ │ │ ├── rights.component.ts │ │ │ │ ├── user │ │ │ │ │ ├── user.component.ts │ │ │ │ ├── admin.component.ts │ │ │ │ ├── admin.component.html │ │ │ │ ├── admin.component.css │ │ │ │ ├── index.ts │ │ │ ├── pipes │ │ │ ├── admin.module.ts │ │ │ ├── admin.routing.module.ts │ │ │ ├── index.ts │ │ ├── core │ │ │ ├── models │ │ │ │ ├── index.ts │ │ │ │ ├── repos.ts │ │ │ ├── services │ │ │ │ ├── github.service.ts │ │ │ │ ├── index.ts │ │ │ ├── core.module.ts │ │ │ ├── index.ts │ │ ├── github │ │ │ ├── pages │ │ │ │ ├── repolist │ │ │ │ │ ├── repolist.component.ts │ │ │ │ │ ├── repolist.component.html │ │ │ ├── github.routing.module.ts │ │ │ ├── github.module.ts │ │ │ ├── index.ts │ │ ├── home │ │ │ ├── pages │ │ │ │ ├── aboutus │ │ │ │ │ ├── about-us.component.ts │ │ │ │ ├── contactus │ │ │ │ │ ├── contact-us.component.ts │ │ │ │ ├── home │ │ │ │ │ ├── home-us.component.ts │ │ │ │ ├── index.ts │ │ │ ├── home-routing.module.ts │ │ │ ├── home.module.ts │ │ │ ├── index.ts │ │ ├── shared │ │ │ ├── layout │ │ │ │ ├── footer │ │ │ │ │ ├── footer.component.ts │ │ │ │ │ ├── footer.component.html │ │ │ │ ├── header │ │ │ │ │ ├── header.component.ts │ │ │ │ │ ├── header.component.html │ │ │ ├── index.ts │ ├── app-routing.module.ts │ ├── app-wildcard-routing.module.ts │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── not-found.component.ts |
Please can you share the link to the repository with the source code?
Thanks a lot of
Thank you. it is helpful content.
Hello, there and thank you for this detailed article. My only challenge is that some of the files have an incorrect path and some components were imported before we had created them.
The incorrect path are:
Admin Module
/app/src/admin/admin.routing.module.ts
/app/src/admin/pages/admin.component.ts
/app/src/admin/pages/admin.component.html
/app/src/admin/pages/dashboard/dashboard.component.ts
/app/src/admin/pages/rights/rights.component.ts
/app/src/admin/pages/user/user.component.ts
/app/src/admin/pages/index.ts
/app/src/admin/index.ts
Github Module:
/app/src/github/pages/list/repo-list.component.ts
/app/src/github/pages/list/repo-list.component.html
/app/src/github/pages/index.ts
/app/src/github/github-routing.module.ts
/app/src/github/github.module.ts
/app/src/github/index.ts
Please can you share the link to the repository with the source code?
Thank you again.
Hi, I think you might have interchanged the folder structure for the below objects. Instead of using /app/src it should be /src/app
/app/src/admin/admin.routing.module.ts
/app/src/admin/pages/admin.component.ts
/app/src/admin/pages/admin.component.html
/app/src/admin/pages/dashboard/dashboard.component.ts
/app/src/admin/pages/rights/rights.component.ts
/app/src/admin/pages/user/user.component.ts
/app/src/admin/pages/index.ts
/app/src/admin/index.ts
/app/src/github/pages/list/repo-list.component.ts
/app/src/github/pages/list/repo-list.component.html
/app/src/github/pages/index.ts
/app/src/github/github-routing.module.ts
/app/src/github/github.module.ts
/app/src/github/index.ts
Thank you for sharing your knowledg!
I think here would be:
/src/app/shared/layout/header/header.component.html
Instead of:
/src/app/shared/layout/footer/header.component.html
How do you use “admin-routing.module.ts, home-routing.module.ts and github-routing.module” in app-routing module?
Cheers!
You put some files from core and services under “/modules” in core. The final structure shows it correctly, but the detailed explaination is not alwas correct.
Hi,
Nice article. It gives more knowledge on angular folder structure.
I have question.
In this same file structure if we have different header and footer for each module, how can we implement routing. Can you pls provide suggestion.
Remove footer & Header from the shared module.
Add them to each module.
In the top-level component of each module add them
Hi,
Thank you very much for sharing,
Maybe i’m wrong but I think there is a small mistake instead of:
/app/src/admin/pages/dashboard/rights.component.ts
put:
/app/src/admin/pages/rights/rights.component.ts
/app/src/admin/pages/dashboard/user.component.ts
put :
/app/src/admin/pages/user/user.component.ts
Thanks. Corrected the mistakes