Standalone Angular & Nx

tldr;

Standalone components, directives, and pipes are the future of Angular. Luckily, Nx works great with the new paradigm. However, if you’re like me, you may be a little overwhelmed with how to organize your project with standalone and Nx. I have been using Nx for years, and Angular for even longer, and wasn’t exactly sure what to do to get started. Once I got started, though, I found out it wasn’t all that bad.

Quick Nx Recap

The point of this article is not to go into too much depth on what Nx is or how projects are organized. There is a lot of content out there that covers this topic. But to better understand how to introduce standalone components in your Nx project, I think a review will help.

Nx projects are made up of apps and libraries. The apps are what they sound like, and are made up of one or more libraries. The libraries contain components, services, pipes, etc. Until standalone pieces were introduced to Angular, all components, pipes, and directives needed to be included in modules. Those modules were then imported in other libraries or in apps to build out the functionality needed. Your layout might look something like this:

Simplified demo layout of an Nx app

The demo-app would include the UiLayoutModule exported from ./libs/ui/layout and the FeatureDashboardModule from ./libs/feature/dashboard. There’s nothing wrong with this per se, but let’s imagine that the layout module has 10 components in it. 3 are actually used in the demo-app’s AppComponent file, but the other 7 are used in the FeatureDashboard module. In this situation, All of the exported code from the UiLayoutModule is imported into both of the other modules, regardless of whether or not the components are used there. It’s also unclear what components you are actually importing into a given module. That’s not great, right?

Now, as for all the extra imported code, we probably don’t need to worry about that, as tree shaking should remove any unused code in our application. But it is still a little unclear where and what we’re using when everything is imported and exported via modules.

Converting to (or Using) Standalone

Using standalone pieces does simplify some of this. Remember, standalone components, pipes and directives, can not be included as part of a module. They need to be imported into the component where they’re used (or if the component where they’re used is not yet standalone, then its parent module). In this way, it’s very obvious what components and pipes are being used and where.

So, how do you create a standalone component in an Nx library and use it in another? This was my hangup initially. I didn’t understand how to organize my library. Let’s look at the following (simplified) library structure:

Simplified demo layout of an Nx UI lib

In this UiLayoutModule we have a MainNav component. it’s a standalone component, and we want to use it in our app. To do so, it needs to be exported from the index.ts file. That may look like this:

export * from ‘./lib/main-nav/main-nav.component.ts’;

If you export the component like this, you will be able to import the component from your library in the same way that you would have imported a module from a library previously.

// Previous import:
import { UiLayoutModule } from ‘@my-nx-workspace/ui/layout’;

// New import:
import { MainNavComponent } from ‘@my-nx-workspace/ui/layout’;

This exported component can then be imported where necessary. If your AppComponent is also standalone, you’ll import it in the imports array in the decorator of the component. If the AppComponent is not standalone, you’ll add the component to the AppModule’s imports array. The component will then be available to use as needed.

This may seem obvious to you, but the import/export pattern here confused me, so although I started my current project after standalone was generally available, I didn’t initially use it. I was unsure how I would import standalone components from my libraries in other parts of the app. I couldn’t find anything explicit out there, so I just shied away from implementing standalone components. But once I just took a stab at it, I realized it worked basically the same way as importing/exporting a module.

Why Should You Convert to Standalone?

Before wrapping up this article, I wanted to list a few reasons why you might want to convert to standalone components, pipes, and directives. I asked the Angular Twitterverse, and here are some of the responses I got:

Testing is significantly easier, in part because it is clear what is needed as far as imports for the component. In Cypress component testing, it virtually eliminates extra setup for mounting and testing the component.More efficient developers. Specifically, it simplifies the developer’s ability to reason about, review, and manage components and other parts of the app. In small apps the difference might be negligible. But as apps grow, the effect is magnified.Implementing other tools is simpler. Cypress, Storybook, etc are examples of tools that are so much simpler.Less mental overhead in trying to connect and remember how components and modules are interconnected, and knowing if you already have the parent module imported into the current module you’re working on.Your app will be caught up with the latest versions of Angular, ensuring you don’t get left behind with old best practices.

Other answers were given, and more may come in, but these were the top answers given when I asked today. And I’ll say, after converting most of my app to standalone components recently, I agree with what everyone told me. My Cypress component tests were simplified, it’s clear what components are being used and where, and I can see where it will be easier in the future as well.

Conclusion

In the end, it took a long time for me to convert my app, and I only converted UI and util libraries to begin with. I still need to convert my feature library components to be standalone. It will take some time, though, as I have many of them. I decided I’d do that as I touch them in the future. But after a day of conversion, I did get rid of more lines of code than I added, and I think I have a simpler, more easy-to-reason-about app. I believe it will be better in the future as standalone becomes more and more accepted and used.

Standalone Angular & Nx was originally published in ngconf on Medium, where people are continuing the conversation by highlighting and responding to this story.

Leave a Comment

Your email address will not be published. Required fields are marked *