Angular has been around for some time now but a lot of us still struggle with scaling our applications to match the demands of the requirements. Drawing from the past several years of working with Angular apps for clients, I’ve made a list of nine major ideas that are often overlooked. These are patterns of implementation that can help accelerate the quality of your final product.
1. Figure Out Your Domains and Be Clear With Your Boundaries
One of the biggest mistakes new Angular developers make is that they jump right in, coding first and fixing later. We’ve all been guilty of this at some point in our careers — even if it’s not with Angular.
However, as we gain more experience, we quickly discover that good architecture and planning can cut down your development time by a good amount.
But how can we achieve this? Through the clarity of domains and boundaries.
There are different domains that you can structure your Angular app around, such as logical domains, theoretical domains, and functional domains.
But what’s a domain?
A domain is a collection of ideas that are similar in nature and fit into a particular category. The boundaries of these domains help us determine if a particular feature or functionality fits within a particular categorization.
Don’t just code your Angular app as-is. Put some structure on it by figuring out how things should be grouped and therefore determine how your components, flow of data and directives ultimately relate to one another.
2. Custom Directives Are Not Evil
Custom directives in Angular are not talked about enough.
The common perception is that components are modularized parts that come together to form the application. However, if we modify this thinking into directives as one of the major building blocks and components as the glue that stick them all together, the concept of true reusability increases two-fold.
This is because starting with custom directives is not the usual flow tutorials follow when it comes to creating a quick Angular application. However, for large scale applications where there needs to be a clear separation of functionality from custom features, custom directives are super handy.
The purpose of your component is to bring everything together anyway. Processing and manipulation of data are supposed to sit on the services layer (which isn’t just limited to http calls to your APIs).
The thing about custom directives is that they’re sharable across the codebase, they reduce duplicate code, and they can help you create a deconstructed app that is able to adapt to changes quickly. If you need to create a new view, all you need to do is to put the parts together rather than having to code everything all over again.
3. Centralized Data Storage Can Keep You Sane
RxJS is a big deal and for good reason. While it’s nice to have your state’s accessibility at your fingertips, when there are more than just your fingertips involved, things can get messy quickly.
As applications grow, the number of states that you have to be aware of grows with it. While smaller apps may do fine with localized state management, a centralized methodology keeps everything in one place and prevents weird backflows.
Yes. Backflows do happen — because it seems logical at first until parts of the application start to get confused about what to do with themselves because your states’ hierarchy is now slightly messed up. When child components start overriding parent components, it’s the beginning of a logical tangle.
A centralized flow of data means that your states and changes are kept flat — with no side branches to detract from the main flow. Any changes go through a cycle that has no deviations — making it highly predictable for your application development process, resulting in a particular expectation from the code produced by your peers as well.
Centralized flow through RxJs enforces standardization. When things are standard, it means everyone is on the same page with their coding output.
4. How You Structure Your CSS Matters
CSS is the last thing on most people’s mind when it comes to Angular development. However, it’s deeply intertwined with the presentation layer of your application. It often determines the final experience of your users and how they interact with your app.
While it’s easy to slap some CSS into the associated file that’s generated by the CLI, this can cause issues further down the road when it comes to maintainability. The next thing you know, you and your teammates are chucking
!important declarations everywhere just to make things look right.
Except you can never quite achieve it and if you do it’s bound to fall apart in the next iteration.
The way you structure CSS is as important as working out how to architecture your Angular application. If you approach your CSS in the same manner — working out which components are reusable and what classes are expected to sit where within the code, then dealing with your presentation layer allows you to properly create custom solutions that are the first things on the agenda and not an afterthought.
When you separate out the process of creating CSS from the process of creating your Angular code, you’re able to see how the two properly fit together and the repeated elements rather than creating everything constantly on the fly.
5. Ways to Organize Your Domains
As mentioned, there are three common ways to organize your domains — logical, theoretical and functional. While they may all feel like variations of the same thing, they’re not due to the way they make you think about your application.
Let’s take logical as the first example.
When you group parts of your Angular application based on logical domains, you are grouping everything based on the business logic. Your boss may have a particular way of displaying the pricing table and so you group everything that’s to do with pricing under one tree structure.
However, if you were to take a theoretical approach, you are targeting your application’s organization based on expected behavior. So rather than grouping your boss’ pricing methodology into one domain, you split it up based on where that pricing is expected to be used the most.
For a functional approach, you are looking at a particular set of features and determining if they fit together on a feature-based grouping. A functional approach is a balance between logical and theoretical — the final deployed structure will probably change as more features are added to the application.
6. With Great Flexibility Comes Great Power
Angular is a lot more flexible than many outsiders realize. While the framework does come with a predetermined way of writing things, you’re mostly free to structure your application however you like.
In theory, you could just put all your logic, external data calls, and processes in your component. But just because you can does not mean that you should. You could perhaps lay it all out in a single service and import it into every component possible.
These are often just signs of inexperienced programming and understanding of how Angular works. Yes, the code may work but it won’t scale in the long run — not because of the framework itself but because of how it’s been utilized.
Learning common patterns in Angular — like central state storage, clear domains of separation and how to use component directives — are all techniques that can be leveraged against bad code.
7. It’s OK to Make Component Libraries
Turning your components or directives into libraries is not something you think about every day — nor is it talked about enough in the general ecosystem — but you should consider it for your next application.
There are certain things that crop up again and again in the world of application development. It may be a signup form, a login modal, or a cart system. Whatever it is, if you’ve encountered it in daily life, then there’s a high chance that you’ll end up coding it at some point.
When you turn your components into libraries, you are contributing to an ecosystem of reusable parts that are isolated from change and can speed up the overall workflow of your team.
This is because component libraries are code assets that can be shared across projects and have a centralized methodology of maintaining updates and changes.
For example, you may have a cart components library that’s used across your web application, your Angular/Ionic implementation and your backend portal for customer service. Rather than having to go and individually update the set of components manually, you can just code an updated version of the library and push out the distribution.
8. Shake That Tree for Production Deployments
Have you ever found your Angular app to be loading ridiculously slowly in a live environment, despite being minified?
budgets in Angular lets you set a maximum size for your final compiled code. Angular, by design, is very fast in the development environment but everything will appear to be working at a breakneck pace because it’s all running on your machine.
However, a barebones Angular app, uncompiled, already runs in at around 3.9mb. It’s being even bigger once you start adding more code to it…
The main reason for its size is the number of libraries it employs to make things work. When you run
--stats-json flag with your build command, you can see how your final application size came to be.
9. Micro-Front Ends Can Save Your Sanity for Large Projects
Micro-front ends may feel like a child of Frankenstein, but it can save you a great deal of time when there are multiple legacy units to deal with.
Sometimes a clean slate transition isn’t possible and the only way to move out of the old is to implement a micro-front end approach, where there are multiple applications running inside a container page.
When you go for a micro-front end approach, you’re able to clearly separate out the massive project into small executable parts that are independent of one another. The backend becomes the central focal point where data is stored and shared across different parts of the application. You may have to implement event listeners — but it will certainly centralize your data storage and processing, taking a traditionally backend task back to its original space.
There’s a new habit amongst application developers to do as little in the backend as possible, leaving it for the front end to sort out. However, this can result in security vulnerabilities. The front end should be limited to the visual and implementation of data, rather than actual data processing, which is different from the first screening of validation.
Angular is good and robust — but only as good and robust your thinking and the act of translating that thinking into code is. These 9 points are just some of a few things to get you thinking about how to better improve your Angular code for the long haul. They are techniques I’ve used for refactoring Angular code (both my own and those given to me).
When things fall apart, you need to step back and look at the way you organized your code rather than hit on the framework. The chances are it’s because of inefficiencies and patterns that made sense in the beginning but proved to be ineffective when more parts were added. The more we work on a particular project, the more we understand how it works — we begin to see where there the bad parts are.
It’s not a sin to refactor. Rather, you should get into the habit of doing so. Refactoring isn’t just about deleting code or looking at what you’ve written a few months back and shaking your head in horror. It’s about taking stock of your current situation, figuring out what can be done better and implementing it.