Building scalable, enterprise Angular apps comes with some challenges, one of which is to organize project in a way, that something maintained by two-three developers will be good to be developed by several teams like this.
So the organisation of the project is really important. Especially because an enterprise app can consist of anything between 100 and 500 components and same amount of services.
By the way, my name is Tom Smykowski, I’m an expert in building scalable, enterprise applications and in this series I’ll be teaching you how to do it!
Before standalone components were introduced, you had to put every component, directive and pipe into a module. Here’s an example of a module:
@NgModule({
declarations: [AppComponent, HeaderComponent],
imports: [CommonModule, FormsModule],
providers: [SomeService],
bootstrap: [AppComponent]
})
export class AppModule {}
There were several problems with this approach. First of all, modules aren’t always necessary. Other libraries like React doesn’t require this construct. For a reason, it increases complexity, increases risk of circular dependencies, makes the codebase harder to understand (you have to figure out what module exports your component, especially difficult when working with 3rd party libraries), lazy loading was a bit complex, and well… there was really a nice pattern to use them.
If you put too much in a module, it gets bloated and your app suffers on performance, because Angular is unable to tree-shake them properly. If you create a module for every component… what is the best option… what’s the point of modules at all?
These issues led to creation of standalone elements in Angular. Now you import a component, service, or a pipe directly where you use it, from where it’s defined:
`import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MeasurementCardComponent } from './measurement-card.component';
import { UnitConverterPipe } from './unit-converter.pipe';
import { StatusDirective } from './status.directive';
@Component({
selector: 'app-factory-dashboard',
...
imports: [
// HERE
CommonModule,
MeasurementCardComponent,
UnitConverterPipe,
StatusDirective
]
})
export class FactoryDashboardComponent {
...
}`
As you can see, it’s easier to figure out and find dependencies of the component using standalone entities.
When you are not there yet with your codebase to use standalone entities, you have to know that in Angular 19 components are standalone by default. You don’t have to add standalone: true to the decorator:
@Component({
selector: 'app-factory-dashboard',
standalone: true,
...
})
You can also use the schematic to automatically switch to standalone:
ng generate @angular/core:standalone
It will also change other elements like bootstrapping and routing. So a lot of things will be taken care of automatically.
In my experience the schematics works quite good. If you use some special things in your application, you may need to do some manual adjustments. But as long as you sticked to Angular standards, it should go smoothly.
To summarize by updating and switching to standalone components, your app complexity will drop, maintainability increase, build size will drop and initial load time drop. All of these contribute strongly to building scalable Angular app.
In my experience of working on Angular apps serving millions of users, standalone components are mature, and serving purpose they were designed for. So, I encourage you to switch to standalone entities.
I’ve prepared a free checklist how to make your Angular app scalable and ready for enterprise demand. If you’re interested, you can get this checklist for free here.
If you have any questions, ask these in the comment section!
Top comments (0)