Despite the default application structure we get from the Angular CLI, we can follow other structures with the dominant being the "Core - Shared - Feature modules". In this article we will see what the Core-Shared-Features pattern is all about, we will face the issues it has, we will scratch the surface of the SCAM pattern, and last but not least we will see how to use the Standalone Components.
Core - Shared - Feature modules
Let's start by explaining what this structure is all about.
The Core Module is loaded with the application and should load just once! No module other than the AppModule should import the Core module and it contains:
The usage of the Shared module is to stop repeating ourselves by importing the same modules again and again. The Shared module contains:
Despite the Core (core.module.ts) and Shared (shared.module.ts) modules where a specific file module exists, the feature modules are multiple and should follow each product's structure. Some examples are Products, Users, Dashboard, etc.
The feature modules import the shared.module.ts and should never import the core.module.ts
The following image depicts the association between the modules.
This is a dominant structure and helps achieving a clean application structure, and we can even say a clean separation between the borders of each module. Since we often need to have something in common, we use the Shared module. And last but not least, instead of bloating the App Module we use the Core Module. This sounds like a great structure. Yet, it has some drawbacks.
When we import the Shared Module into a Feature Module, we also import all the modules it contains. Unfortunately though, not every imported module is required by all the Feature Modules and this leads to bigger chunks. Follow this article to read more about the performance issues.
The applications have many user flows and the users decide which to follow, based on their needs. Think that we have in our application the user flows:
A solution to this problem would be to lazy load the "List" and "Charts & Reports" components. It is definitely possible to achieve this using the Core - Shared - Feature modules, but it is harder to do so.
Since we now know what the problems are, we can be cautious on the Shared Module usage and start importing the required modules into each Feature Module.
Angular SCAM Module
A possible "band aid" to the problems the Core - Shared - Feature module have, is to use the SCAM pattern. SCAM = Single Component Angular Module.
So what is this all about? Essentially every component uses its own module and looks like the following:
So, in the same file we have the Component and NgModule as well.
This pattern opens the door to a more flexible and scalable application structure, and we can be cautious about the modules we import or the declarations we use in that SCAM module. For example, we do not need to import the charts modules in a component which will never gonna use them.
Alternatively, we can implement a more fine grained lazy load modules!
This and this are very good reads that worth spending some time.
Angular Standalone Components
In Angular 14 (the next version), a new feature will be released and is the Standalone Components.
The term Standalone means that the Components, Directives and Pipes can have their own module. Independently from NgModule. Like SCAM, but without the biolerplate code and it looks like the code below:
Since every component has it's own module, we can apply a lazy load modules (err, components). Let's have a look at an example.
We have already created a Standalone List Component (above) and let's see how to apply the routing.
We then import the UserRoutingModule in the AppRoutingModule. But wait, this isn't new. Right? Yes correct, we can implement the routing with the way we already know. For reference, let's have a look at the code of the AppRoutingModule:
Earlier in this article, we addressed a problem with two user flows.
Note that instead of loadChildren, we use loadComponent to lazy load the ReportsComponent.
Having the Standalone Components feature in place, doesn't mean that we have to have them fully in our application. It's a great feature and we can use it as we wish.
Thanks for reading my article!