Angular has evolved significantly over the years, and one of the most impactful improvements is the introduction of Standalone Components. This feature simplifies application architecture by reducing boilerplate and making components more self-contained and reusable.
In this article, I’ll explain what standalone components are, how they differ from regular (module-based) components, and when not to use them, using a real-time store application demo that I built locally.
What is a Standalone Component?
A Standalone Component is an Angular component that does not need to be declared inside an NgModule.
Instead of relying on modules for declarations and imports, a standalone component directly manages its own dependencies.
In traditional Angular applications:
Every component must be declared in an NgModule
Routing, directives, and pipes are imported via modules
With standalone components:
Components are self-contained
Dependencies like CommonModule, RouterLink, or other components are imported directly in the component decorator
Applications become simpler, more readable, and easier to maintain
Angular now recommends standalone components for new applications, making them the future-proof approach.
Real-Time Scenario: Store Application Using Standalone Components
To understand standalone components in practice, I created a simple store application with the following pages:
Landing Page
Products Page
Product Details Page
Services Page
About Us Page
Contact Us Page
Almost all components in this application are standalone, including routing and navigation.
Routing Without Modules (app.routes.ts)
Instead of defining routes inside a routing module, routes are configured directly using standalone components:
export const routes: Routes = [
{ path: '', component: LandingComponent },
{ path: 'about', component: AboutComponent },
{ path: 'products', component: ProductListComponent },
{ path: 'products/:id', component: ProductDetailComponent },
{ path: 'services', component: ServicesComponent },
{
path: 'contact',
loadComponent: () =>
import('./contact/contact.component').then(m => m.ContactComponent)
},
];
Why this matters
No routing module required
Supports lazy loading at component level
Cleaner and more readable route definitions
Root Component as a Standalone Component
The root component (AppComponent) itself is standalone and imports only what it needs:
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, NavbarComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
title = 'Standalone_Component_POC';
}
Key Takeaways
RouterOutlet and NavbarComponent are imported directly
No AppModule is required
The root component controls its own dependencies
Navbar as a Reusable Standalone Component
The navigation bar is a perfect example of a reusable standalone component:
@Component({
selector: 'app-navbar',
standalone: true,
imports: [RouterLink, RouterLinkActive],
templateUrl: './navbar.component.html',
})
export class NavbarComponent {}
Benefits
Product Listing Page Using Standalone Component
The products page displays a list of products and uses routing for navigation:
@Component({
selector: 'app-product-list',
standalone: true,
imports: [CommonModule, RouterLink],
templateUrl: './product-list.component.html'
})
export class ProductListComponent {
products = [
{ id: 1, name: 'Red T-Shirt', price: 19.99 },
{ id: 2, name: 'Blue Jeans', price: 49.99 },
{ id: 3, name: 'Sneakers', price: 89.99 },
];
}
What this demonstrates
CommonModule is imported directly for structural directives
RouterLink is imported at component level
The component is fully independent and reusable
Lazy-Loaded Contact Page
The Contact page is lazy-loaded using loadComponent, which avoids loading it upfront:
@Component({
selector: 'app-contact',
standalone: true,
imports: [CommonModule],
templateUrl: './contact.component.html',
})
export class ContactComponent {}
Why this is powerful
Reduces initial bundle size
Improves application performance
No feature module required for lazy loading
UI Screenshots of the Store Application Built Using Standalone Components
Landing Page – Standalone Component Entry Point
![1_Landing_Page]()
Key Highlights:
Products Page – Standalone Component with Routing
![2_Products_Page]()
Key Highlights:
Uses *ngFor from CommonModule
Navigates using RouterLink
Demonstrates data display in a standalone component
Contact Us Page – Lazy Loaded Standalone Component
![3_ContactUs_Page]()
Key Highlights:
Lazy-loaded at component level
No feature module required
Improves performance and scalability
Regular Component vs Standalone Component
| Feature | Regular Component | Standalone Component |
|---|
| Requires NgModule | Yes | No |
| Boilerplate code | High | Minimal |
| Lazy loading | Module-based | Component-based |
| Dependency handling | Via modules | Inside component |
| Reusability | Limited | High |
| Recommended for new apps | No | Yes |
When NOT to Use Standalone Components
Although standalone components are highly recommended, there are a few scenarios where they might not be ideal:
Large legacy applications heavily dependent on modules
Applications running on older Angular versions
Complex shared module patterns that are expensive to refactor
Teams not ready to migrate existing module-based architecture
For new projects and modern Angular versions, standalone components should be the default choice.
Conclusion
Standalone components simplify Angular development by:
Removing unnecessary modules
Improving readability and maintainability
Making components self-contained and reusable
Enabling easier lazy loading and routing
In this store application demo, standalone components helped create a clean, modern, and scalable architecture without sacrificing functionality.
Source Code
You can find the complete working demo here:
GitHub Repository: Standalone_Component_POC