Angular is evolving. Standalone components provide a simplified way to build applications by removing the need for NgModules.
1The Death of Boilerplate
For years, every Angular component had to belong to an NgModule. This often led to 'Shared Modules' that became bloated over time. Standalone components fix this by making the component itself the unit of modularity. By setting standalone: true, you tell Angular that this component will manage its own dependencies. This leads to a 'tree-shakeable' architecture where only the code you actually use is included in the final bundle.
2Direct Dependencies
In a standalone world, dependencies are explicit. If a component needs the DatePipe or another component, it imports them directly in its @Component metadata. This makes the code much easier to trace. You no longer have to hunt through various module files to understand why a specific directive is available. This locality of reference improves both developer productivity and the performance of Angular's compilation process.
3Step-by-Step Breakdown
While NgModules are powerful, they add boilerplate. Modern Angular (v14+) introduces 'Standalone Components' to simplify your code.
A standalone component doesn't need an NgModule. It manages its own dependencies using the 'standalone: true' flag.
Instead of importing other components into a module, you import them directly into the component that needs them.
Checkpoint: In a standalone component, where do you list the other components or modules that it depends on?
- →declarations
- →imports (inside @Component)
Bootstrapping is also simpler. We use 'bootstrapApplication' instead of 'platformBrowserDynamic().bootstrapModule()'.
Standalone is the future of Angular. It makes components more reusable, easier to test, and reduces the learning curve.
Checkpoint: Which property must be set to 'true' in the @Component decorator to make it standalone?
- →independent
- →standalone
Modern architecture mastered! Your code is now leaner, cleaner, and ready for the future.
Next, we'll dive deeper into the engine that powers everything: Advanced Dependency Injection.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Removing NgModules Changes Nothing About Accessibility Requirements
Standalone components simplify how a component declares its dependencies (`imports` directly on the `@Component` decorator instead of an enclosing `NgModule`) — the template itself still needs the exact same semantic HTML, labels, and ARIA attention regardless of this architectural change.
2Simpler Bootstrapping Can Reduce Setup Mistakes That Indirectly Affect Accessibility Tooling
Standalone's simplified `bootstrapApplication` setup reduces the surface area for module-wiring mistakes — indirectly helpful since a correctly bootstrapped app is a prerequisite for accessibility auditing tools to even analyze it correctly in the first place.
SEO Implications
- 1
Standalone Components Still Require the Same SSR Setup for Crawlable Content
Switching from NgModules to standalone components is an internal architecture change with zero effect on whether content is crawlable — Angular Universal (or prerendering) is still required for search engines to see real rendered HTML, regardless of which component model is used underneath.
- 2
Simplified Bootstrapping Can Reduce Bundle Size, Modestly Helping Load Performance
Standalone APIs can make tree-shaking more granular since components declare their exact dependencies directly rather than through a module's aggregate imports — a smaller bundle modestly helps Time to Interactive, an indirect Core Web Vitals benefit.
Best Practices
Import Only What a Standalone Component Actually Uses in Its `imports` Array
Since standalone components declare dependencies directly rather than inheriting a module's broader import list, take the opportunity to be precise — importing only `CommonModule` directives actually used (or specific standalone pipes/directives) rather than habitually importing broad, unused modules.
Use `bootstrapApplication` With Explicit Providers for App-Wide Configuration
In a standalone app, `bootstrapApplication(AppComponent, { providers: [...] })` replaces what used to be root `NgModule` providers — centralize genuinely app-wide providers (like `provideHttpClient()`, `provideRouter()`) there rather than scattering them across components.
Frequent Bugs
A standalone component's template fails to recognize a directive or pipe that 'should just work'.
Standalone components must explicitly list every directive, pipe, and component they use directly in their own `imports` array — unlike an NgModule-declared component, there's no ambient module scope providing it implicitly. Add the specific standalone dependency (or `CommonModule` for structural directives like `*ngIf`) to the component's `imports`.
Mixing standalone components with legacy NgModule-based components causes confusing import errors.
A standalone component can be imported directly into an NgModule's `imports` array (not `declarations`), and an NgModule-declared component can be used inside a standalone component's `imports` only if that NgModule is imported — the two systems interoperate, but the specific 'imports vs declarations' rules differ depending on which direction you're bridging, and mixing them up is a common source of this error.
Real-World Examples
Standalone Component With Explicit Dependencies
A standalone component explicitly imports only the specific Angular features its own template actually uses, avoiding both the implicit module-scope confusion and unused dependency bloat of the older NgModule pattern.
@Component({
selector: 'app-user-card',
standalone: true,
imports: [CommonModule, RouterLink],
templateUrl: './user-card.component.html'
})
export class UserCardComponent {}