For nearly a decade, Angular developers have lived in a world dominated by NgModules. We spent countless hours managing declarations, imports, and exports just to get a single component to show up on a screen. It was a complex system that often felt like solving a puzzle before you could even start coding.
But the landscape of Angular has shifted. With the introduction of standalone components, the framework has moved toward a simpler, more streamlined architecture. This modern approach removes the need for bulky modules, making your code easier to read, faster to test, and significantly more maintainable.
If you are maintaining a legacy Angular application, migrating to standalone components is the single most impactful way to modernize your codebase in 2026. This guide provides a clear, risk-reduced roadmap to help you make the switch.
Why Move to Standalone Components?
Before we dive into the "how," let’s talk about the "why." Why should your team invest time in this migration?
- Reduced Boilerplate: You no longer need to manage app.module.ts or dozens of feature modules. Each component stands on its own.
- Better Tree Shaking: Because dependencies are explicit at the component level, build tools can remove unused code more effectively, leading to smaller bundle sizes.
- Easier Testing: You don’t have to import entire modules into your unit tests. You only import the specific component you are testing.
- Improved Developer Experience: New developers can understand the dependency graph of a component just by looking at its decorator, rather than hunting through module files.
The Pre-Migration Checklist
Migrating an enterprise-level app isn't something you do in a single afternoon. To ensure a smooth transition, follow these preliminary steps:
1. Update to the Latest Version
Your application must be on at least Angular 15.2, though it is highly recommended to update to Angular 18 or 19 first. The migration schematics (the automated tools we will use) are much more robust in the newer versions.
2. Clean Git Branch
Never run migration scripts on your main branch. Create a dedicated feature/standalone-migration branch. Ensure your current project builds without any errors and that all unit tests pass.
3. Identify Complex Dependencies
Check if your third-party libraries (like UI kits or state management tools) support standalone APIs. Most modern libraries do, but legacy ones might require a manual workaround or an update.
Step 1: Automated Conversion of Declarations
Angular provides a powerful command-line tool called a "schematic" to handle the heavy lifting. The first step is to mark every component, directive, and pipe as "standalone."
Run this command in your terminal:
1ng generate @angular/core:standaloneWhen prompted, select the first option: "Convert all components, directives and pipes to standalone".
What happens in this step?
The tool will scan your project and add standalone: true to the @Component decorator of every file. It also looks at the module where that component was originally declared, identifies its dependencies, and adds those dependencies to a new imports array inside the component itself.
Pro Tip: After this step, run npm start. Your app should still work exactly as before because the original modules still exist and now simply import the standalone components.
Step 2: Pruning Unnecessary NgModules
Now that your components are standalone, those old NgModule files are mostly empty shells. It’s time to clean them up.
Run the schematic again:
1ng generate @angular/core:standaloneThis time, select: "Remove unnecessary NgModule classes".
What happens in this step?
The schematic will delete most of your feature modules. If a module was only serving as a "bucket" for declarations, it is no longer needed. The tool will also update any other parts of your app that were importing those deleted modules, pointing them directly to the components instead.
Warning: Some modules might remain if they contain "providers" (services) that the tool couldn't safely move. You may need to handle these manually later.
Step 3: Modernizing the Bootstrap Process
The final automated step is the most significant. It changes how your entire application starts. In legacy Angular, we use platformBrowser().bootstrapModule(AppModule). In the modern world, we bootstrap the root component directly.
Run the schematic one last time:
1ng generate @angular/core:standaloneSelect: "Bootstrap the project using standalone APIs".
What happens in this step?
- It deletes your app.module.ts.
- It updates your main.ts to use bootstrapApplication(AppComponent).
- It moves global providers (like those for Routing or HTTP) into a new configuration object.
Step 4: Manual Cleanup and Routing Refactor
While the automated tools are excellent, they aren't perfect. For a truly "production-grade" migration, you need to do a manual pass.
Refactor your Routes
In legacy apps, we often use RouterModule.forChild(). In a standalone app, you can use a simpler syntax. Change your routing files to export a simple Routes array:
1// old way
2@NgModule({
3 imports: [RouterModule.forChild(routes)],
4 exports: [RouterModule]
5})
6export class FeatureRoutingModule {}
7
8// new way (routes.ts)
9export const featureRoutes: Routes = [
10 { path: '', component: FeatureComponent }
11];Then, in your main app routes, you can lazy-load the routes directly without a module:
1{
2 path: 'admin',
3 loadChildren: () => import('./admin/routes').then(m => m.adminRoutes)
4}Use Functional Interceptors
If your app uses HTTP Interceptors, consider moving from class-based interceptors to functional interceptors. They are much easier to write and integrate perfectly with the new provideHttpClient() API.
Real-World Tips for Large Teams
If you are working with a large team on a massive codebase, don't try to migrate everything at once.
- The Path-Based Migration: The ng generate @angular/core:standalone command accepts a --path argument. You can migrate one folder at a time to keep pull requests small and manageable.
- Enforce the New Standard: Update your linting rules to require standalone: true for any new components. This prevents "code regression" where developers accidentally create new legacy-style modules.
- Monitor Bundle Size: Use a tool like webpack-bundle-analyzer to see the impact. You should see a noticeable drop in the "main" bundle size as you move to a fully standalone, lazy-loaded architecture.
Common Pitfalls to Avoid
- Circular Dependencies: Standalone components import each other directly. If Component A imports Component B, and Component B imports Component A, you will create a circular dependency. Use services or shared components to break these loops.
- Hidden Providers: Sometimes services are provided in a module that you just deleted. If your app crashes with a "No provider for X" error, you need to add that service to the providers array in your bootstrapApplication call or use { providedIn: 'root' }.
- CommonModule Bloat: The automated tool often adds CommonModule (which contains *ngIf, *ngFor, etc.) to every component. To optimize further, you can eventually replace CommonModule with the modern Angular Control Flow (@if, @for).
FAQ: Frequently Asked Questions
Can I mix standalone components and NgModules?
Yes! Angular is designed for "incremental adoption." You can have a standalone component inside an NgModule, or you can import an NgModule into a standalone component. You don't have to finish the whole migration in one day.
Is standalone: true the default now?
As of Angular 19, standalone is the default. If you generate a new component using the CLI (ng g c my-component), it will be standalone by default unless you explicitly tell it otherwise.
Does this improve performance?
Yes. By eliminating the module layer, Angular's compiler can better optimize the code. You will likely see faster build times and smaller initial load times for your users.
What happens to my SharedModule?
In the standalone world, the "SharedModule" pattern is replaced by "Shared Components." Instead of importing one giant module with 50 components, you simply import the 2 or 3 specific components you actually need.
Conclusion
The shift to standalone components is more than just a syntax change; it is a fundamental improvement to the Angular ecosystem. By following this step-by-step plan, you can take a complex, module-heavy legacy application and transform it into a lean, modern system that is ready for the future of web development.
Start today by updating your version and running the first schematic. Your future self—and your development team—will thank you for the cleaner, faster, and more manageable codebase.
About the Author

Suraj - Writer Dock
Passionate writer and developer sharing insights on the latest tech trends. loves building clean, accessible web applications.
