Angular has long been built around the concept of `NgModules` to organize an application’s structure, grouping components, services, pipes, and directives. However, Angular’s latest version introduces the `Standalone APIs`, which aim to reduce the overhead of modules by allowing developers to work directly with components and services. This change simplifies Angular applications by removing unnecessary `NgModule` classes and encouraging a more streamlined approach.
In this blog, we’ll discuss how to migrate an Angular project’s `CoreModule` to standalone APIs. We’ll focus on the following key concepts:
Standalone components
Standalone bootstrapping API
Converting directives and pipes to standalone
Lazy loading standalone components
Removing `NgModule` classes
Maintaining your project structure
The Angular team introduced Standalone APIs as a way to reduce the reliance on `NgModules` and provide a more flexible, modular architecture. The new `Standalone APIs` allow you to define components, directives, and pipes independently, eliminating the need for wrapping them in a module declaration. These APIs also offer a standalone-based bootstrapping method, which can simplify application initialization and streamline routing configuration.
When you migrate to standalone APIs, you’re essentially removing the dependency on `NgModules`. This requires you to shift your focus to direct dependencies for each component, making each element self-sufficient and portable. Angular’s `Standalone API` also introduces the ability to bootstrap an application without the need for a root `NgModule`.
Before beginning the migration, it’s important to:
Back up your project: Create a clean Git branch to ensure you can revert changes if necessary.
Update Angular: Ensure you’re using Angular 14 or later, as the standalone APIs were introduced in Angular 14.
Review your `CoreModule`: Identify which components, services, pipes, and directives need to be migrated.
Standalone components are at the heart of this migration. These components no longer need to be declared within a module; instead, they can be self-contained and define their own dependencies via the `imports` array.
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-header',
standalone: true, // Mark the component as standalone
imports: [CommonModule], // Import necessary modules directly
templateUrl: './header.component.html',
styleUrls: ['./header.component.css'],
})
export class HeaderComponent {}
In this example, the `standalone` flag is set to `true`, making the `HeaderComponent` independent. Instead of relying on a module’s `imports` array, the component declares its dependencies directly.
In addition to standalone components, Angular provides a new bootstrapping API—`bootstrapApplication`—that allows you to bootstrap your application without a root module. This is a key feature of the migration process, as it removes the need for a `root NgModule`.
Here’s how to switch from module-based bootstrapping to the standalone bootstrapping API:
Before:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
After:
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, {
providers: [
// Provide services and dependencies here
],
});
This replaces `bootstrapModule` with `bootstrapApplication`, allowing you to directly bootstrap your root component (`AppComponent`) without a root module.
Just like components, directives and pipes can now be declared as standalone. This helps reduce the complexity of the project by allowing them to be independent of `NgModules`.
import { Directive } from '@angular/core';
@Directive({
selector: '[appHighlight]',
standalone: true, // Standalone directive
})
export class HighlightDirective {}
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'customPipe',
standalone: true, // Standalone pipe
})
export class CustomPipe implements PipeTransform {
transform(value: any): any {
return value.toUpperCase();
}
}
The goal of migrating to standalone APIs is to remove unnecessary `NgModule` classes from your project. Once you have converted all components, directives, and pipes to standalone versions, you can safely delete the `CoreModule` and any other associated modules.
This involves the following steps:
Convert all components, directives, and pipes.
Ensure all services are provided using the `providedIn: 'root'` method in the `@Injectable` decorator.
Delete the `CoreModule` and remove its import references from other parts of the application.
Angular’s new standalone architecture supports lazy loading, but the way you configure it has changed slightly. Instead of lazy loading a module, you can now lazy load a standalone component directly.
Before:
{
path: 'about',
loadChildren: () => import('./about/about.module').then(m => m.AboutModule),
}
After:
{
path: 'about',
loadComponent: () => import('./about/about.component').then(c => c.AboutComponent),
}
This makes lazy loading more intuitive and reduces the need for `NgModules` to organize your routing configuration.
Migrating an existing Angular project to standalone APIs is a process that can be completed incrementally, allowing you to maintain functionality while converting one part of your project at a time.
Analyze Your Project: Identify the components, directives, pipes, and services in your `CoreModule` or other `NgModules`.
Convert Declarations: Convert each component, directive, and pipe to a standalone version by setting `standalone: true`.
Handle Services: Ensure all services are provided at the root level using `providedIn: 'root'` in the `@Injectable` decorator.
Migrate Bootstrapping: Switch from `bootstrapModule` to `bootstrapApplication` in `main.ts`.
Update Routing Configuration: Modify your lazy-loaded routes to use `loadComponent` instead of `loadChildren`.
Test and Fix: After each migration step, run your application and unit tests to ensure that everything still works as expected. Fix any compilation errors that arise.
Remove Modules: Once all components have been converted, remove unnecessary `NgModule` declarations.
It’s important to note that the migration to standalone APIs can be done incrementally. You don’t need to convert the entire project at once. Begin with smaller modules, like `CoreModule`, and move to more complex ones.
Angular’s static analysis can help recognize any missing imports and dependencies, ensuring that everything is accounted for during the migration.
When converting to standalone components, remember to update your unit tests to reflect the new standalone architecture. Make sure to import any necessary modules directly into the test file, as the component no longer belongs to a `NgModule`.
The Angular CLI includes a `migration schematic` that can assist with the conversion to standalone APIs. Running the schematic automates parts of the migration process, ensuring that as much code as possible is converted to the standalone style.
You can initiate the migration with the following command:
ng g @angular/core:convert-to-standalone
The schematic will handle some of the heavy lifting, such as recognizing custom wrappers and converting them to standalone APIs. However, a few manual fixes and follow-up steps may still be necessary to complete the migration.
Migrating your Angular project’s `CoreModule` to standalone APIs offers significant benefits, including reduced complexity and more flexible architecture. By eliminating unnecessary `NgModule` classes and switching to standalone components and lazy loading, you can streamline your codebase while retaining Angular’s powerful features.
With the help of the `bootstrapApplication` API, you can simplify the bootstrapping process and make your application more modular and maintainable. While the migration process may involve a few manual fixes, Angular’s new standalone style is designed to make future development more efficient and scalable.
So, if you’re looking to modernize your existing Angular project, migrating to standalone APIs is a step in the right direction. Start small, take it incrementally, and enjoy the benefits of Angular’s new, streamlined architecture.
This website uses cookies to analyze website traffic and optimize your website experience. By continuing, you agree to our use of cookies as described in our Privacy Policy.