Standalone Components and Bootstrapping
Since Angular 14 introduced them and Angular 17+ made them the default, standalone components let a component declare its own dependencies—other components, directives, and pipes—directly in an imports array on the @Component decorator, without needing to belong to an NgModule. This removes an entire layer of ceremony that historically confused newcomers: no more deciding which NgModule a component belongs to, no more declarations arrays, and no more forgetting to export a component so another module can use it. A standalone component is self-contained and can be imported wherever it's needed, much like importing a component in React or Vue.
Cricket analogy: It's like a franchise player who brings their own kit and support staff to any tournament they join, rather than needing to be permanently registered with one specific league body, just as a standalone component declares its own imports without belonging to an NgModule.
Bootstrapping Without a Root Module
Traditional Angular applications bootstrapped via platformBrowserDynamic().bootstrapModule(AppModule), where AppModule declared the root component and imported feature modules. Standalone applications instead call bootstrapApplication(AppComponent, appConfig) from @angular/platform-browser, passing the root standalone component directly along with an ApplicationConfig object that supplies application-wide providers—router configuration, HTTP client setup, and any global services.
Cricket analogy: The old bootstrapModule approach is like a board selecting the whole squad through one central selection committee meeting, while bootstrapApplication(AppComponent, appConfig) is like directly naming the captain and handing them a settings sheet covering fielding rules and umpiring setup.
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { routes } from './app.routes';
import { authInterceptor } from './auth.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(withInterceptors([authInterceptor])),
],
};
// app.component.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
template: `<router-outlet />`,
})
export class AppComponent {}The provideX() Pattern
Standalone bootstrapping favors function-based provider configuration—provideRouter(), provideHttpClient(), provideAnimations(), provideStore() in NgRx—over NgModule imports. Each provideX() function returns an array of providers configured for a specific concern, composable via the providers array in ApplicationConfig. This tree-shakable, functional style means unused features (like HTTP interceptors you never opt into) don't bloat the bundle, and it mirrors patterns familiar from other modern frameworks' composable setup functions.
Cricket analogy: provideRouter() and provideHttpClient() are like a franchise separately hiring a fielding coach and a data analyst as needed, rather than being forced to take a whole bundled support-staff package, keeping the payroll (bundle size) lean by only paying for roles actually used.
Since Angular 19, standalone: true is the implicit default for components generated by the CLI—you no longer need to write it explicitly. NgModules still exist and remain fully supported for legacy codebases, but new Angular projects and the official style guide now steer entirely toward standalone components as the default mental model.
A standalone component must explicitly import everything it uses in its template—including CommonModule directives like NgIf/NgFor if you're not using the newer @if/@for control-flow syntax. Forgetting to add a used component or directive to the imports array produces a template error at compile time (or a silently unrendered element in some cases), unlike NgModule-declared components which inherited the whole module's declarations implicitly.
- Standalone components declare their own dependencies via an
importsarray on @Component, removing the need for NgModules. - bootstrapApplication(AppComponent, appConfig) replaces bootstrapModule(AppModule) as the entry point for standalone apps.
- ApplicationConfig's
providersarray configures app-wide services using composable provideX() functions like provideRouter() and provideHttpClient(). - Since Angular 19,
standalone: trueis the implicit default and no longer needs to be written explicitly. - Each standalone component must explicitly import everything its template references — there is no implicit inheritance from a shared module.
- NgModules remain supported for legacy code but are no longer the recommended default architecture.
Practice what you learned
1. What replaces bootstrapModule(AppModule) in a standalone Angular application?
2. How does a standalone component declare which other components or directives it uses in its template?
3. What is the purpose of functions like provideRouter() and provideHttpClient()?
4. As of Angular 19, what is true about the `standalone: true` flag on CLI-generated components?
5. What happens if a standalone component's template uses a directive that isn't included in its `imports` array?
Was this page helpful?
You May Also Like
What Is Angular?
An overview of Angular as a full-featured, opinionated TypeScript framework for building web applications, and how it compares to lighter-weight libraries.
The inject() Function
Learn how the inject() function offers a flexible alternative to constructor injection, and how it enables DI in functional contexts like guards, resolvers, and interceptors.
Angular Router Basics
Learn how Angular's built-in router maps URL paths to components, enabling single-page applications to feel like multi-page sites without full page reloads.
Anatomy of a Component
A close look at the parts that make up an Angular component — the decorator metadata, class body, template, and styles — and how they fit together.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics