It's been a while since Angular v14 was released - the version that introduced standalone components.
How many of you have already migrated to Angular v14 and to standalone components - raise your hand.
If you did, good for you!
If you didn't, I'd say "I understand".
I know from experience the struggles of the job. Sometimes so many things are going on - you're overwhelmed! Migrating to the latest version and catching up with updates just has to wait.
This article aims to answer questions like:
- how to create a standalone component in Angular?
- what changes did they bring to the Angular world?
- why should you care about them?
Hopefully, this will motivate you to put them higher on your priorities and to-do list.
Let's get started!
Creating standalone components, directives, or pipes is as simple as marking their class with standalone: true.
Standalone classes don't need to be declared in an NgModule. In fact, you'll get an error if you try to. Instead, you specify their dependencies directly in their
This means that NgModules are completely optional - which brings us to our next point.
Once you get to know standalone components, you'll realize that in many cases modules were just boilerplate code.
NgModule is a "context holder" for declarations and providers. This means that modules handle dependencies themselves.
The problem is when a module doesn't do anything like that. It's only exporting a declared component, directive, pipe, etc. Then we just deliver a useless class that provides no additional value.
We don't even need an
AppModule anymore - we can bootstrap the application directly with a component.
We just provide the required providers (as if this was a module). Think of
[importProvidersFrom](https://angular.io/api/core/importProvidersFrom) as a bridging function.
We will see this less often as libraries start to adapt and provide helper functions. For example, with Angular v14.2 we already got this (line 4):
However, to play the devil's advocate here - there's still work that needs to be done.
The list of imports can grow fast. It would be nice if we could somehow avoid this duplication.
The Angular team must already be aware of this. Hopefully, we'll see some mechanism that deals with this in an upcoming version.
Remember how we had to point to another module that then pointed to a routed component or route configuration?
That belongs to the past!
Now we can point directly to a routed component (line 10) or route configuration (line 14). Because of standalone components routing became more tree-shakable.
It goes without saying that if you can route to a component, then you can also lazy load a component.
No need to load an entire module when you only need to load a specific component.
Did you know?
Every time you lazy-loaded a module, you got a new scope. And when you eager-loaded a module, you didn't.
This is quite confusing. It's like trying to hit two birds with a stone, but instead shooting your own foot.
Luckily, route configuration now has a providers section (line 5). This is optional, but we can use it to provide some providers for that specific route and all its child routes.
These are the providers we would normally put in our lazy-loaded module.
This is more explicit. We put something there? We know we'll get a new scope, regardless of whether we use lazy loading.
Structuring the application without modules is not affected by any means. We can simply use folders to organize our project.
A better way to do this is to use barrels. It's like creating a public API. Whatever we export from our
index.ts means that is backward compatible and won't break by future changes.
As of Angular v15.2, there is an Angular schematic to automate the migration from NgModules to the standalone API.
Getting into the details goes way out of the scope of this article. But you can read how to use it here.
Standalone components certainly made an entrance. 😅
We talked about how to create them, the changes they brought to several features of Angular, and the benefits of using them.
Subscribe to my newsletter and stay tuned for more content like this.
Thank you for reading!