SCAM: A better way to share components in Angular
SCAM is alternative approach for sharing components between your Angular feature modules. Learn how to apply it and what the benefits are compared to the usual SharedModule approach.
- Reading time
- 3 min
What is the SharedModule?
SharedModule, as recommended by the Angular Coding Style Guide, is a single Angular module with generic components, directives and pipes that are shared between feature modules in your Angular application.
Creating a project global place for all common things, like widgets or pipes to transform values, makes sense. You can share them between multiple modules and every developer knows where to put new common components.
The approach also has drawbacks. In general, we want to create small, encapsulated and reusable units. Creating a single shared module may get pretty large as the project grows.
I recommend another approach: SCAM.
What is SCAM?
Single Angular Component Module, or SCAM for short (not to be confused with scam), is the concept of creating Angular Modules with only one component (or directive / pipe). This brings a few benefits.
- Smaller modules: A SCAM is small and that is what we mostly want: small units of code, like small functions, classes - and also modules.
- Clear responsibility: You and every other developer in your team will know what that module is responsible for.
- Clear dependency: You can easily check where your component is used by checking where your module is imported.
You don't have to take "single component" literally, neither "single" nor "component". SCAM also applies to directives and pipes. And it's not about exactly one element. A SCAM may have additional components that are only used internally or it may even export multiple components that always belong together (like a component for an accordion and a component for an accordion entry). The pattern should bring you benefits and it's not meant to limit you.
SCAM in action
We can apply the SCAM pattern for our
SharedModule. We create a
shared folder and instead
of just one module we create multiple, small, shared modules there. It looks something like this:
src/ └── app/ └── shared/ ├── accordion/ │ ├── accordion.component.css|html|ts │ ├── accordion-group.component.css|html|ts │ └── accordion.module.ts ├── button/ │ ├── button.component.css|html|ts │ └── button.module.ts └── some-transformation/ ├── some-transformation.pipe.ts └── some-transformation.module.ts
This example has three shared modules: accordion, button and some-transformation.
What about ... ?
Tree-shaking and lazy loading
You may ask if the SCAM pattern provides any advantages regarding tree-shaking and lazy loading. The short answer is: no.
The Angular Ivy renderer, that replaces the now deprecated View Engine, has good support for tree-shaking and lazy loading components. It will not include unused components even if they are imported and exported in your
SharedModule. In addition, it will move components into lazy loaded chunks even if other components of the same module are used in your main bundle.
SCAM without modules
Angular is working on making NgModules optional, as mentioned on their roadmap. I don't know how this API will look like (and I don't expect this new concept to be released any time soon, see #37904 and #35646) but using shared SCAMs may make the switch easier, as you could remove the module of some shared SCAMs and still keep the module definition of other shared modules (either because refactoring them takes time or if they use features that still require modules).
Update: There is now a RFC about standalone components on GitHub.
Using shared SCAMs creates some overhead as you have more modules and more imports in your feature modules. On the other hand, you get smaller, better encapsulated modules that are easier to understand and hopefully easier to refactor when NgModules get optional.
That's it, that's the SCAM pattern. What do you think about it? Let me know on Twitter.