Should I create a module per component in Angular 4+ app?

Angular

Angular Problem Overview


We have a medium sized Angular 4 application (+-150 components).

Many of these components require the injection of service classes and require the declaration of other components in the app.

An approach we have been experimenting with, and have found to be much more developer friendly, is to create a module per component. The module imports the child component modules and provides (or imports) all the services needed by the component. It also exports the component itself so that other components can reference it through the module.

It makes the composition of components a breeze and the setup of the test fixture of a component very simple (this is where there was previously a lot of repetition of dependencies and child component tree dependencies).
This approach seems to match the component based architecture and allows for a form of encapsulation around what a components dependencies are.
It feels just too good to be true ;)

My question is, what is the performance (or other) impact of having so many modules?

Angular Solutions


Solution 1 - Angular

I consider one module per component the best way to design your Angular apps.

If it depends on other components, you can include only the component modules related to each component that is a direct dependency and don't need to care about indirect dependencies.

It may seem more work at first, but it will pay you back will less maintenace problems.

If ComponentA depends on ComponentB that depends on ComponentC create a:

ModuleC related to ComponentC

ModuleB related to ComponentB that imports ModuleC

ModuleA related to ComponentA that imports ModuleB (it doesn't need to import directly ModuleC)

If ComponentB now depends on ComponentD (like including <my-component-d> in the template) and stops depending on ComponentC you just change ModuleB and all components that depend on ComponentB will work fine, if you are using this approach.

Think now about hundreds of components. How many components will depend on ComponentB?

I consider this problem similar with the old way (or not too old) of including js files in script tags:

<script src="build/a.js"></script>
<script src="build/b.js"></script>
<script src="build/c.js"></script>

And if you change b to stop depending on c and starts depending on d, all pages that import b have now to import d, and so on, leading to a maintenance nightmare. You may also forget to remove (the now unneeded) c.js and import it needlessly in some pages, increasing your boot time (or worse, you remove it from all files that import b.js, but some page imports e.js that depends on c.js and you break some functionality of that page).

Instead I consider it much better to import:

<script src="build/bundle.js"></script>

or

<script src="build/vendor.js"></script>
<script src="build/main.js"></script>

and the dependencies are handled by a module bundler, like webpack.

There is the approach of making a module with lots of components and just import it, but you end up importing several components that you don't use and if you use lazy loading, your modules may become huge, unless you import that module in AppModule, making your boot time increase.

You can still use the approach of one component per module with feature modules. Just import the component module into the feature module (instead of the component itself):

feature.module.ts:

imports: [
    ComponentAModule,
    ComponentBModule,
    ComponentCModule,
]

(You may want to export them too).

I also consider this approach the best way when creating libraries, otherwise you would force the consumers of the library to import all the components, even if they only use 1 or 2 components in the library.

I'm experiencing this issue with ionic3: the minified ionic-angular library has 437KB of which 292KB are the components (hopefully it will change with ionic4). I use just a few ionic components, there was no need to import all of them, but I have no choice (unless I fork the repo or stop using it).

I have an app with 176 components and this was the best approach in my opinion. Before, I included several components in a feature module and it gave me some headaches later on. Also, it was harder when changing a component from a feature module to another (What about its dependencies? They were all mixed together).

I haven't found a satisfactory approach with services (@Injectable()) tough.

In the end it's up to you the decision. This is my opinion based on my experience.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMark WhitfeldView Question on Stackoverflow
Solution 1 - AngularLucas BasquerottoView Answer on Stackoverflow