A Scalable Angular Project Structure

Younes
Marmicode
Published in
3 min readMar 13, 2019

--

A beautiful but yet fragile project structure

The ideal project structure is something that keeps moving.

So, a good project structure is something easy to refactor.

Few hours ago, I published this article about SCAM modules:

And this Angular schematic called @wishtack/schematics:scam:

… then the annoying side of my brain was like:

The annoying side of my brain

OK! … and now, how do you regroup related components? And how do you handle routing?

Proxy Modules

In order to regroup related components & modules, I use what I call “proxy” modules.

A proxy module is a module that doesn’t declare anything, it just exports other modules in order to regroup & expose them.

Here’s an example of a proxy module.

@NgModule({
exports: [
MatButtonModule,
ReactiveFormsModule,
MyFunkyInputModule
]
})
export class SharedFormsModule {
}

DRY

A proxy module exports all the modules it imports, so let’s not repeat ourselves.

It’s still better to avoid them though.

Rule of Thumb

  1. Let your team vote and choose a number (named X) between 3 and 7.
  2. Now, you can’t have more than X components or X imports per module.
  3. You can vote again…

View Modules

One of the most confusing things I noticed when meeting new Angular apps is that it’s hard to tell which modules are Routed Modules and which are not.

To avoid this issue, I recommend dedicating a directory called views to Routed Modules which we will call View Modules and view components following the rules below:

  • Outside from View Modules (modules inside the views directory), no other module is defining any routes.
  • View components (components inside the views directory) are the only components allowed to read params & query params from the activated route.
  • View Modules shouldn’t export anything.

Example

  • views/app-routing.module.ts :
  • views/sandwich/sandwich-views.module.ts :

You should end up with a project structure that should look something like this.

app/
sandwich/
sandwich-catalog/
sandwich-catalog.component.ts|html
sandwich-form/
sandwich-form.component.ts|html
sandwich-picture/
sandwich-picture.component.ts|html
sandwich-preview/
sandwich-preview.component.ts|html
user/
...
views/
landing-view/
landing-view.component.ts
sandwich-views/
sandwich-views.module.ts
sandwich-catalog-view/
sandwich-catalog-view.component.ts
sandwich-detail-view/
sandwich-detail-view.component.ts
sandwich-editor-view/
sandwich-editor-view.component.ts

Note that app/sandwich is not an Angular module but just a directory that regroups SCAM modules.

You can also note that LandingViewComponent which is in app/views/landing-view/landing-view.component.ts is free to use a component from a SCAM module in app/sandwich without having to refactor or load a SandwichModule that would contain all these components (and which doesn’t exist with this kind of project structure).

Key Takeaways

This project structure has three kinds of modules:

  • SCAM modules with one component per module.
  • Proxy Modules to regroup stuff. These modules don’t declare anything.
  • View Modules that handle the routing.

… and should following the rules below:

  • Avoid having more than 7 imports per module.
  • Separate view modules from the rest.
  • Outside from View Modules (modules inside the views directory), no other module is defining any routes.
  • View components (components inside the views directory) are the only components allowed to read params & query params from the activated route.
  • View Modules shouldn’t export anything.

If you want to learn more about Angular and if you can read French (or if you don’t mind using google translate meanwhile I translate the content), you can have a look at our FREE Angular Guide https://guide-angular.wishtack.io/.

--

--

Younes
Marmicode

Google Developer Expert for Angular & Web Technologies | eXtreme Programming Coach | Tech Advisor