Angular Enterprise
Bad practices to avoid in Angular
- Courses
- 13 practices
- 4 min read
Here we have gathered a list of bad practices to avoid when you are developing an Angular application. Before starting a new project it's highly recommended to make a similar list based on your previous experience: it will help you learn from past lessons and avoid making the same mistakes again and again.
- deeply nested logic structures (
if/elseblocks, nestedsubscribecalls, nested templates) make the code hard to read, test and maintain. Prefer early returns, small functions, RxJS operators orcomputedsignals. - lack of a clear design pattern such as container/presentational components results in a codebase that is hard to read, debug, test and maintain. Also called smart/dumb components, this pattern should be used everywhere in the app.
- lack of application monitoring and error tracking at the beginning of the project such as
Sentry. It results in tons of bugs the day you install it and then you have to work for months in order to rid the app of all those bugs. - lack of
purefunctions: developers are used to writingimpurefunctions which change the state of the component variables inside the function, this results in side effects and functions that are not testable. It's harder to writepurefunctions but it results in code that is easier to maintain. - lack of simple
typingsfor objects, functions, inputs and outputs: developers sometimes useanyinstead. If in addition you don't have unit tests then your code is very vulnerable to errors. - lack of
readonlyandDeepReadonlytypings results in unsafe code and possible mutation of any attribute in the codebase, functions will potentially have side effects. - lack of a clear pattern for overriding the existing theme. A clear convention should be used, for instance if you want to customize
Angular Materialthere are many different cases to know (theme variables, overlay components, regular components...). Recent versions of Angular Material expose design tokens andoverridesSass mixins for this purpose: prefer them to overriding internal CSS classes. - lack of splitting into lazy-loaded features (lazy routes with
loadComponent/loadChildren, orlazy modulesin older applications) results in a big main bundle, but it also makes the app more and more coupled and later it becomes almost impossible to split the codebase. - wrong usage of
NgRx: the global store should be used only for certain types of entities which are shared, hydrated, available, retrieved or impacted (the SHARI principle). That's also why new solutions emerged (ComponentStore, thenSignalStoreand plain Angular signals) in order to give developers the ability to store data in a local state instead of the globalNgRxstore. - usage of
::ng-deepwithout:hostaffects the CSS of the other components and breaks the style isolation principle. The way to avoid that is to use:host ::ng-deepor, even better, CSS variables to override the style as explained in our best practices guide. Those errors are also due to the fact that Angular Material renders part of some components outside of them, in a detached overlay panel which pops on top of the view, for instance when amat-selectis open. - accumulation of circular dependencies warnings will make your app less and less maintainable. Each time you detect a circular dependency it's recommended to take the time to fix it.
- using
combineLatestin an NgRx effect to read the store triggers unexpected actions each time one of the sources emits. It is strongly advised to useconcatLatestFrom(from@ngrx/operators) orwithLatestFromin order to be sure that you are not going to listen to future events. - usage of the deprecated Sass
@importrule in each component produces a lot of duplicated code, use@useand@forwardinstead.