Humans have a great history of constructing structures. The structure, which is considered to be a wonder in the 21st century is the folder structure in your project. The folder structure is equally important in the Angular realm. In this article, we will be exploring the best practices for Angular folder structuring.
Nicely written code and a well arrange folder structure in any project is a haven for the developers. This no different in Angular, the SPA framework Angular comes with its own coding guidelines Style Guide • Angular. The style guide is enough to show you a riotous path for following a coding standard, naming conventions and project structuring. We will touch base the style guide in this article, we will head in this direction for now:
It's crucial to understand the general philosophy to even have a defined folder structure in the first place. A well-defined folder structure enables developers to locate files as quickly as possible. So, basically, it's a raise against time, the poor the structure the more time it takes to locate files.
Now the arrangement of files can be broadly categorized in two ways,
In type based, you keep all the same type of files together, for example you clubbed all the components together, and services together. While in the feature based you club things based on their feature or domain, for example you clubbed components or services related to products in one folder and orders in another folder if we talk about any generic E-Commerce based app.
Both the approaches come with their own challenges if your app is big in size. If you consider only type based, then tons of components will be placed inside components folder without clearly distinguish between their features. While in the other approach you need to always logically define your feature boundaries, but with the changing nature of software development approach this becomes challenging later, as the sometime the feature name or context gets changed and then the structure becomes irrelevant over a period of time.
The best folder structure lies an approach that consume goodness of both the philosophy while being lean and clear. At high-level categorize everything based on feature/domain and at the low level organized by type.
Broadly in Angular, we have certain core things those serve as a basis for any app, certain things those are shared across the apps (some common components like button, grid, etc.) and many features. Lets go with this setup and create three base folders at high level as below:
app
|-- core
|-- features
|-- shared
|-- layout
|-- app.component.ts|html|spec
|-- app.config.ts
|-- app.routes.ts
Here, we have 3 base folders, this categorization is mostly domain based, further we will move into type based or in more specification.
Below highlights the role of these modules and the intent of having them:
We can have more folders along-side:
app
|-- core
|-- features
|-- shared
|-- layout
|-- states
|-- app.component.ts|html|spec
|-- app.config.ts
|-- app.routes.ts
Here, the states folder will be related to state management - like NgRx.
Lets get into these high-level folders and understand how we can categorize it. At low level we can segregate things based on their type instead of their domain. Note, we can even further categorize into sub-features, but finally we can categorize the sub-features too based on type based. This type-based categorization provides us a way to quickly identify the elemental things, instead of keeping everything inside one folder. First let us see what are the types we are talking about:
products
|-- pages
|-- components
|-- features
|-- constants
|-- directives
|-- mocks
|-- models
|-- pipes
|-- services
|-- utils
|-- products.config.ts
|-- products.routes.ts
Talking about each folders purpose below:
The sub-feature enables us to have more sub-feature within a feature maintaining a hierarchy. If a products feature has root level pages/components like list or detail and has further sub-features like product catalog or product history which has its own routing and pages/components, it's better to keep them one level down. This nesting helps us to quickly figure out whether they are on same level or nested.
The final folder structure will look something like this:
app
|-- core
| |-- constants
| |-- guards
| |-- interceptors
| |-- mocks
| |-- models
| |-- apis
| |-- services
| |-- core.config.ts
|-- features
| |-- products
| | |-- pages
| | |-- components
| | |-- apis
| | |-- constants
| | |-- guards
| | |-- mocks
| | |-- models
| | |-- modules
| | |-- services
| | |-- utils
| | |-- products.config.ts
| | |-- products.routes.ts
| |-- dashboard
| |-- account
| |-- orders
| |-- carts
|-- shared
| |-- components
| |-- constants
| |-- directives
| |-- pipes
| |-- models
| |-- utils
| |--shared.config.ts
|-- layout
| |-- components
| | |-- header.component.ts|html|spec
| | |-- footer.component.ts|html|spec
| | |-- shell.component.ts|html|spec
|-- states
| |-- actions
| |-- effects
| |-- reducers
| |-- selectors
| |-- app.state.ts
|-- app.component.ts|html|spec
|-- app.config.ts
|-- app.routes.ts
Keep the HTTP based API services file in Core or each Feature folders. These files can be generated from automated tool like NSwag. We can avoid using these services directly in the component instead we can plan to have a service layer for accessing the API methods.
app
|-- core
| |-- apis
| |-- auth.service.ts
| |-- account.service.ts
|-- features
| |-- products
| | |-- apis
| | | |-- products.service.ts
| | | |-- products-catalog.service.ts
| |-- orders
| | |-- apis
| | | |-- order.service.ts
| |-- carts
| | |-- apis
| | | |-- order.service.ts
Sometime the decision making difficult for the team, when they may be new or fairly having lesser understanding of folder structure followed, its better to have a decision-making graph that enables developers to resolve their generic queries those comes when creating any new module, service, component, utils etc.:
Consider using below prompts in ChatGPT to get aligned with the understanding of ideal folder structuring:
December 31, 2020
October 19, 2020
March 02, 2022