|
| 1 | +--- |
| 2 | +title: "Angular standalone components" |
| 3 | +excerpt: "A simplified way to build Angular applications" |
| 4 | +tags: Web Angular standalone |
| 5 | +authors: |
| 6 | +- Ankit Pant |
| 7 | +header: |
| 8 | + teaser: /assets/images/post/angular-standalone-components.png |
| 9 | + teaser_alt: Angular standalone components |
| 10 | +category: Frontend |
| 11 | +--- |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +# Introduction |
| 16 | + |
| 17 | +Until now, developers have been using NgModules to specify the components, directives, pipes, etc that are available for use in templates, however, after the release of Angular [standalone components](https://angular.io/guide/standalone-components "https://angular.io/guide/standalone-components"), you don't need to do this anymore in the NgModules. |
| 18 | +Angular standalone feature was fully released with Angular v15. Angular [standalone components](https://angular.io/guide/standalone-components "https://angular.io/guide/standalone-components") are independent and self-contained building blocks in an Angular app which can be used to independently import the dependencies required for its functionality. |
| 19 | +Although the standalone components are not mandatory, and there are no strict rules for using them, Angular architects recommend using the Standalone feature for the newly created Angular components. |
| 20 | + |
| 21 | +To designate a component, directive, or a pipe as a standalone component, you must mark it as `standalone: true`. The component does not have to be declared or imported in `NgModule`, and you can import all the dependencies directly in the component itself, thus eliminating the use of `NgModule` entirely. |
| 22 | + |
| 23 | + ```typescript |
| 24 | + @Component({ |
| 25 | + selector: '...', |
| 26 | + templateUrl: '...', |
| 27 | + styleUrls: ['...'], |
| 28 | + standalone: true, |
| 29 | + imports: [ |
| 30 | + NgIf, |
| 31 | + NgFor, |
| 32 | + AsyncPipe, |
| 33 | + ... |
| 34 | + ], |
| 35 | + }) |
| 36 | + export class FooBarComponent { |
| 37 | +``` |
| 38 | +
|
| 39 | +
|
| 40 | +# Generate a standalone component via the Angular CLI |
| 41 | +
|
| 42 | + ``` |
| 43 | + ng generate component --standalone account-statements |
| 44 | +``` |
| 45 | +
|
| 46 | +A component generated with `--standalone` flag is not added to `NgModule` and contains default imports such as `CommonModule` to get started with the component right away. |
| 47 | +
|
| 48 | +# Adopt standalone components incrementally |
| 49 | +
|
| 50 | +Standalone components can be seamlessly combined with existing modules. They are easy to implement, and can be adopted incrementally into an app. A `standalone` component, pipe or directive can also be imported into an existing `NgModule` configuration, applied incrementally for complex apps, so that you can ensure that there are no breaking changes. |
| 51 | +
|
| 52 | + ```typescript |
| 53 | + @NgModule({ |
| 54 | + declarations: [...], |
| 55 | + exports: [...] |
| 56 | + imports: [ |
| 57 | + AccountDetailsComponent, // This is a standalone component |
| 58 | + CommonModule, |
| 59 | + RouterModule.forChild(routes), |
| 60 | + ..... |
| 61 | + ], |
| 62 | + }) |
| 63 | +``` |
| 64 | +
|
| 65 | +# Migrate a component to a Standalone |
| 66 | +
|
| 67 | +You can convert a component in one of the following ways: |
| 68 | +
|
| 69 | +* Using the [schematics](https://angular.io/guide/standalone-migration#migrate-an-existing-angular-project-to-standalone "https://angular.io/guide/standalone-migration#migrate-an-existing-angular-project-to-standalone") |
| 70 | +
|
| 71 | +* Manually |
| 72 | +
|
| 73 | +## Migrate to Standalone via schematics |
| 74 | +
|
| 75 | +To migrate standalone components, you must satisfy the [prerequisites from Angular](https://angular.io/guide/standalone-migration#prerequisites). |
| 76 | +Angular provides a [schematic to migrate](https://angular.io/guide/standalone-migration#migrate-an-existing-angular-project-to-standalone "https://angular.io/guide/standalone-migration#migrate-an-existing-angular-project-to-standalone") existing Angular apps that use Angular `v15` or later, to use the standalone features. |
| 77 | +
|
| 78 | +
|
| 79 | +``` |
| 80 | +ng generate @angular/core:standalone |
| 81 | +``` |
| 82 | +
|
| 83 | +`ng generate @angular/core:standalone` should be executed at the root of the project. |
| 84 | +
|
| 85 | +Use this as follows: |
| 86 | +
|
| 87 | +1. Run `ng generate @angular/core:standalone` to convert all components, directives and pipes to standalone. This will try to convert and migrate all the files to use standalone features. |
| 88 | +
|
| 89 | +2. Run `ng generate @angular/core:standalone` again to remove unnecessary NgModule classes. Empty `NgModules` are searched for removed them from the app. |
| 90 | +
|
| 91 | +3. Run `ng generate @angular/core:standalone` a third time to bootstrap the project using standalone APIs. The schematics change how the app is bootstrapped in the `main.ts` file. |
| 92 | +
|
| 93 | +_**Note:**_ |
| 94 | +
|
| 95 | +* To avoid any breaking changes to an app with the standalone feature, in Angular, most of the `NgModule` or other files, so you might have to remove and migrated some of the files manually. |
| 96 | +
|
| 97 | +## Migrate a component manually |
| 98 | +The steps below shows how to migrate an existing component to a standalone component |
| 99 | +
|
| 100 | +1. Mark the component as standalone by adding `standalone: true` as the meta data in the `@Component` directive. |
| 101 | +
|
| 102 | + ```typescript |
| 103 | + @Component({ |
| 104 | + ... |
| 105 | + + standalone: true, |
| 106 | + ``` |
| 107 | +
|
| 108 | +2. Import all the `dependencies` in the standalone component from `ngModules` |
| 109 | +
|
| 110 | + ```typescript |
| 111 | + @Component({ |
| 112 | + ... |
| 113 | + standalone: true, |
| 114 | + + imports: [ |
| 115 | + + TransactionsAccountSelectComponent, //another standalone component |
| 116 | + + HeaderModule, // non-standalone component can be imported like this |
| 117 | + + NgIf, |
| 118 | + + NgFor, |
| 119 | + + AsyncPipe, |
| 120 | + + JsonPipe, |
| 121 | + + ] |
| 122 | + }) |
| 123 | + ``` |
| 124 | +
|
| 125 | +3. If the component has [child routes](https://angular.io/guide/standalone-components#providing-services-to-a-subset-of-routes "https://angular.io/guide/standalone-components#providing-services-to-a-subset-of-routes"), create and export `routing.ts`. |
| 126 | +
|
| 127 | +4. Delete the `NgModule` and the routing configurations. |
| 128 | +
|
| 129 | +{% include |
| 130 | +components/figure.html |
| 131 | +url="/assets/images/post/angular-standalone-components-3.png" |
| 132 | +description="Migrate a component to a Standalone" |
| 133 | +%} |
| 134 | +
|
| 135 | +# Differences between using NgModules and Standalone feature |
| 136 | +
|
| 137 | +## Bootstrapping an app |
| 138 | +
|
| 139 | +Once the `AppComponent` is standalone you can get rid of the `AppModules` completely and use |
| 140 | +[bootstrapApplication](https://angular.io/api/platform-browser/bootstrapApplication "https://angular.io/api/platform-browser/bootstrapApplication") API to bootstrap the application in `src/main.ts` file and import the dependencies directly in the `AppComponent`, for more information see [here](https://angular.io/guide/standalone-components#bootstrapping-an-application-using-a-standalone-component "https://angular.io/guide/standalone-components#bootstrapping-an-application-using-a-standalone-component"). |
| 141 | +
|
| 142 | +{% include |
| 143 | +components/figure.html |
| 144 | +url="/assets/images/post/angular-standalone-components-1.png" |
| 145 | +description="Bootstrapping an Application" |
| 146 | +%} |
| 147 | +
|
| 148 | +## Changes in the Routing configuration |
| 149 | +
|
| 150 | +With standalone feature in place, `NgModule` is no long required for many lazy loading scenarios. |
| 151 | +You can simply lazy load a standalone component by exporting the routes and using `loadComponent` instead of `loadChildren` and include them in `src/main.ts` files using `provideRouter()` from `@angular/router` as follows. |
| 152 | + |
| 153 | +{% include |
| 154 | +components/figure.html |
| 155 | +url="/assets/images/post/angular-standalone-components-2.png" |
| 156 | +description="Changes in the Routing configuration" |
| 157 | +%} |
| 158 | + |
| 159 | +## Specs for Standalone components |
| 160 | + |
| 161 | +The TestBed configuration now doesn't needs to import all the dependencies used by the component |
| 162 | +you are testing and hence reduces the boilerplate code in the spec file. |
| 163 | + |
| 164 | +{% include |
| 165 | +components/figure.html |
| 166 | +url="/assets/images/post/angular-standalone-components-4.png" |
| 167 | +description="Specs for Standalone component" |
| 168 | +%} |
| 169 | + |
| 170 | +_**NOTE:**_ After the migration the specs might be broken and might need manual fixes |
| 171 | + |
| 172 | +# Improvements on performance using standalone feature |
| 173 | + |
| 174 | +Here are a few ways in which Angular standalone components can contribute to performance improvements: |
| 175 | + |
| 176 | +* **Reduced bundle size:** You can reduce the overall bundle size of your app by using Angular's standalone feature and eliminating NgModules and the boilerplate code that comes with it. |
| 177 | + |
| 178 | +* **Isolation and lazy loading:** You can enhance the performance by encapsulating functionality within standalone components which helps to load all the resource only when it is lazy loaded. |
| 179 | + |
| 180 | +* **Reusability:** Angular standalone components are self-contained, independent, and can be re-utilized across the app. |
| 181 | + |
| 182 | +# Bundle size |
| 183 | + |
| 184 | +The actual impact on bundle size will depend on the complexity and size of your Angular component as well as the specific dependencies it requires. The difference in bundle size was not that huge (about 8.5 kb) for a small app which is also mentioned in the table below, but it might make a big difference with the large apps. While using Angular standalone components can reduce bundle size, other factors such as code optimization, tree shaking, and lazy loading can also play a role in optimizing bundle size. |
| 185 | + |
| 186 | +| App type | Bundle size | |
| 187 | +| ------------------- | ------------- | |
| 188 | +| Non Standalone app | 7648528 bytes | |
| 189 | +| Standalone app | 7640882 bytes | |
0 commit comments