The problem we are trying to solve
A bad structure is a big problem when it comes to scaling up a project, where it becomes a nightmare for developers.
If a project is not well structured and organized developers are losing a lot of time and focus to find some parts of the code, or components, especially if a big team is running a project.
A solution that works for me
I have created this as a universal seed project, which I reuse when creating new Angular apps, with the following modules structure:
- Core
- Public
- Private
- Shared
Core Module
This module, as the name says, is a core module for the app and it holds all core functionalities such as Authentication, Guards, Interceptors, Handlers…
Auth folder
In the auth folder I put auth service, which does authentication stuff for the application.
Guards folder
Here I store all types of guards, for example:
- Auth Guard
- Role Guard
- Login Guard…
These guards are preventing users to acces certain routes using angular’s router.
Handlers folder
Here I have handlers for the app. It depends what are you going to achieve, but I have created a handler for loading different modules for the same route as per user role. I will make another article about this approach and explain what I do.
Interceptors folder
In this folder I put different types of interceptors, such as error interceptor, to intercept all error responses from the server and show the message as a toast to an end user.
Services folder
A few different services for the core functionalities, for example:
- Login service (handle login requests)
- Token service (stores token, does refreshing of token, etc.)
- User service (keeps all information about the logged in user, such as id, email, roles, or anything you need)
You can add anything that fits your application needs in the core folder, this is just an example of the most common usage.
Public Module
Public module I use for storing all components/pages that are visible to non-registered users, such as 404 page, login page, register page, web presentation…
As you can see in the attached image, I have also created a “public” component within the public module. That component is going to handle routing, actually to have the router outlet inside the public.component.html.
<router-outlet></router-outlet>
You can also see the scss and routing files here as well.
Components folder
Here I have all public components / pages, I don’t have to explain this in details 🙂
Http folder
Http folder, some people don’t use this folder and keep their API services in the services folder, but what I like to do is to separate http (API calls), and services.
Models folder
Models (Interfaces), all kind of… Everything I will need in the public module.
Pipes folder
Pipes and filters…
Services folder
As I mentioned in the http folder, I have separated services from API calls. So the services here are just for communicating and sharing the data between components.
So that is all in the public folder, but you can add more folders as per your needs.
Private Module
Think about it as opposed to the public module. So, everything has to be visible just for logged-in users. Example: back-offices, hidden panels, role-based things…
In this module I am using the same structure as in the public module, so you can just copy/paste the structure.
Shared Module
The shared module is a bit different than the previous modules. In this module, I am not creating a component in the root (flat) since there is no need for it. This module has no routing module and is going to be imported into the Public and Private modules.
Why is this module important
As Angular is a component-based framework that allows us to make reusable components we should make them in every possible situation. (If we are the same logic more than 2 times) We will use this module a lot.
Examples of reusable components across the application: navbars, sidebars, footers, loaders, spinners, specific cards…
Also, when including a library that has to be used in both modules such as Angular Material Design and components, or any others. We will import them into the shared module and add them to the module exports and that’s it, we will have the libraries accessible by both shared and public modules.
Assets folder
Structuring of assets folder is also important. Here is an example of the assets folder structure.
Here I have scss folder for my default-theme.scss and scss partials. As you can see in the partials folder I have _colors.scss. You can add more partials here but this is just for example.
The default theme is especially important if you are using the Angular Material theme. In this theme file, I am also styling Angular material core components, such as buttons, input fields, etc.
Example of imports:
/* _colors.scss */
$black: #000;
$white: #FFF;
$red: #FF0000;
/* default-theme.scss */
@use 'partials/colors' as *;
.some-element{
background: $black;
}
/* -----------or------------- */
@use 'partials/colors' as c;
.some-element{
background: c.$black;
}
Conclusion
In the end, the best structure is the one that fits your needs and with which you can work without any disruption. This structure works very well for me and fits my team’s needs.
Also, the structure is scalable and there will be more folders during the development process as well.
If you have any kind suggestions, questions, or corrections, feel free to comment and reach me.
I hope you found this article helpful.
Thank you for reading the article.
GitHub link to the project: adnan-halilovic/angular-folder-structure: Angular Project Architecture (github.com)