Component-First Architecture with Angular and Standalone Components
Tags: angular, typescript, javascript, webdev
Published: 2021-12-23 15:51:43

[Angular](https://angular.io) recently had an [RFC](https://github.com/angular/angular/discussions/43784) (Request for Comments) on Standalone Components. It is an effort to make `NgModules` in Angular optional. We do not want to remove them completely as many Angular apps currently rely on the building blocks that are `NgModules`.

[Manfred Steyer](https://twitter.com/ManfredSteyer) explored what this will mean for the ecosystem moving forward and how we can begin to think about writing our Angular apps in his short blog series: https://www.angulararchitects.io/en/aktuelles/angulars-future-without-ngmodules-part-2-what-does-that-mean-for-our-architecture/

# Declarative Routing

I believe, however, that the best potential architecture we can achieve when Standalone Components are introduced, will be based around Declarative Routing. 

Declarative Routing is a concept that we have seen implemented by packages such as `react-router`. It involves declaring our routes as elements in our component’s template.

With Angular, we do not have an officially supported Declarative Routing solution, however, [Brandon Roberts](https://twitter.com/brandontroberts) has created a package that implements this concept, called the [Angular Component Router](https://github.com/angular-component/router).

It allows us to define the Routes through our application in our components, removing the need to configure the `RouterModule` at multiple layers of our application. 

As Standalone Components require us to specify their `imports` in their `@Component` decorator, this could get unwieldy. It also means that we’re still relying on `NgModules`, making it difficult to ever fully remove them from the framework.

![Large Standalone Component Imports](https://miro.medium.com/max/700/0*TfscPIP_KJpwbxI3)

# Component-First Architecture

However, what if we simply used our component’s template to define the Routes through our application? We could easily have a beautiful, declarative API for our application routing that supports redirects, fallbacks, lazy loading of components _(key!)_, and standard Route Guards!

![Declarative Routing](https://miro.medium.com/max/700/0*trPvwS3aG5WSwXFQ)

But, we should take this further. Right now, people could define Routes in _any_ component in their application, and figuring out the full routing setup for the application will become extremely painful.

With Standalone Components, we should still slice our application by dedicated features or domains. We’ll create a folder/workspace structure wherein each feature has it’s own dedicated folder/library. At the root of these, there will live a `route-entry`. This `route-entry` will contain the routes for this portion of the application. This creates a structure such as:

![Folder Structure](https://miro.medium.com/max/488/0*rczFxsGW4hsmlRNK)

We can expect to see a `route-entry` at the root of each domain/feature we have in our system which will define the routing for that area of the application. Now, every developer will know exactly where to look when they need to find, edit or add routes to the system.

From this, our top-level app routing should only ever point to `RouteEntryComonents`.

![Top Level Routing](https://miro.medium.com/max/700/0*A8KaIALsbv7nBb4M)


Following this pattern with Standalone Components means our components are the driving force of our applications, as they should be. 

**This is Component-First Architecture.**
Component-First Architecture is where our components define and drive the user experience of our application. Anything that impacts the user’s experience should be handled via our components, as it is our components that the user interacts with.

## Why should we care about Component-First?

Component-First aims to create an architectural pattern that places Components as the source of truth for your Angular application.  
Currently in the Angular ecosystem, `NgModules` act almost like orchestrators, wiring together your application. It's from the very existence of `NgModules` where we created the `AppModule` -> `FeatureModules` -> `SharedModules` -> `CoreModules` architecture.  
This architecture is fine. It works. It scales. But is it overkill? Possibly.

While it does introduce a great separation of concerns within your app's structure, `CoreModules` and `SharedModules` often become overpopulated and difficult to maintain. `SharedModules` in particular can become a dumping ground. This often leads to a situation where we need to import the `SharedModule` into all our `FeatureModules`, even if we one need 1 thing from it.

With Component-First, our Components decide themselves what they need to perform. They can take `Injectables` via their `constructor` and they can import any `component`, `directive` or `pipe` they need to function. This increased level of granularity allows our Components to be hyper-focused on their function, reducing any additional bloat that might end up compiled with the Component.

Components in a Component-First Architecture will be completely tree-shakeable. If they aren't imported or routed to, they won't be included in the final bundle for our applications. Currently, to achieve the same effect with `NgModules`, we need to follow a pattern known as the [SCAM (Single Component Angular Module) Pattern](https://dev.to/this-is-angular/emulating-tree-shakable-components-using-single-component-angular-modules-13do) which was popularized by [Lars Gyrup Brink Nielsen](https://twitter.com/LayZeeDK).

By following the Component-First Architecture Pattern, we also reduce the coupling between our Components and `NgModules` which paves the way to a truly `NgModule`-less Angular. We can still keep all the same composability that `NgModules` offered by simply following some best practices on code-organization; something Angular has us well trained to do already.

If components point to components, our mental mind map of our application becomes simpler. You can traverse the tree of components in your app and build out a pretty comprehensive map of your app, without having to worry about `NgModules` adding additional dependencies on your components that you may not be expecting. In Component-First, your components dictate their own dependencies. This massively reduces cognitive load, especially for newcomers to the codebase.

---

Colum Ferry’s Twitter: https://twitter.com/FerryColum