In my previous post, I talked about how to build large-scale enterprise Angular applications. Now you know why TypeScript is a must-have for larger applications, how you can optimize Angular, and which third-party libraries are recommended.
In case you missed that post, you can check it out here.
In this post, I will talk about the tricks and tips I learned during building and maintaining our enterprise Angular applications. These tips will guide you to properly design your app, use the proper git-flow and libraries, and also how to update a complex enterprise Angular application and do the refactoring.
- 1. Design the structure well
- 2. Learn from other projects
- 3. Use proper git-flow and CI
- 4. Use well-maintained libraries
- 5. Upgrade carefully
- 6. Best practices and code syntax may change over time
- 7. Refactor only if beneficial
- 8. Do code review before merging
- +1 Start a new project if the old one is escalated
👉 Pssst! Since you're here, don't forget to download the State of Software Development 2019 report here.
Everything starts with a good design. You need to plan your projects with proper tools and configs as these are hard to change later when your team has implemented modules based on the initial rules.
Consider using strict Tsconfig rules including noImplicitAny, noUnusedLocals, noUnusedParameters and all strict typing rules.
Starting a new project is a good chance to review your setup and to implement best practices. As I mentioned, it’s hard to change the base configs later (e.g., require the explicit return type after hundreds of functions have been implemented without it). I recommend reviewing your previous projects or finding good examples on the internet. You can check out and install our ESlint config here.
Large-Scale Enterprise Applications require a large developer team. Using proper git-flow is necessary to maintain your codebase on an everyday basis.
I recommend setting up your git as you consider the following:
- Keep the master branch stable and ready for release.
- Create a develop branch as the center of your work.
- Set the develop branch default.
- Create a staging branch as a bridge between the develop and master. You may test the latest version on this branch before you release.
- Make the main branches (master, develop, staging) protected. Don’t let developers push their work directly to these branches.
- Force developers to work on their own branches and create pull (merge) requests.
- Setup a CI and test the codebase at every pull (merge) request. Run linting and deploy preview (build the code with AoT compile).
Before you start using a third-party library in your project, visit the npm page of the lib and check the latest commits on git and the dates of the releases. Make sure the author of the library updates that at least after every major release of Angular to keep the compatibility.
Before you upgrade to the latest version of Angular and other libraries, I recommend waiting a few days or weeks for the first patch versions. Once you’re ready to upgrade, make sure you test it locally, then on a separate testing/staging environment to avoid any issue.
Read the changelog of the libraries, especially after major releases, and see if there is any breaking change. If there are breaking changes, update your application locally, then push the fixes with the updated package.json.
I also recommend generating a fresh project with the latest version of the Angular CLI after each major version update and comparing that with your project. However, there is an ng update command that runs upgrade scripts; it may not be perfect or cover all changes.
The authors of libraries also improve their work, which may result in syntax changes over time. This is mostly beneficial for developers as it means the new syntax may reduce boilerplate code or introduce performance updates.
The new syntax is usually backwards-compatible with the previous structure, so I recommend using the old syntax for the already implemented modules (to keep the code styling consistent) and using the new one for new modules.
As the new versions of the libraries are usually backwards-compatible, refactor your codebase only if you can gain performance improvements, smaller bundle size or better code quality. For example, the latest RxJs version supports pipeable operators, and the previously recommended way was using chainable operators. Although the RxJs team provides a compatibility library to still support chainable operators, after refactoring those to pipeable operators, you can remove that compatibility library.
Besides using lint libs in combination with prettier to format the code and to keep the code styling consistent, I strongly recommend doing code reviews before merging the pull (merge) requests, including reviewing all implementations of observables to make sure you avoid memory leaks.
See more tips at our blogpost about code review.
Two years ago, I worked on an admin dashboard. That project was started in AngularJS, and we continued in Angular as hybrid apps with the compatibility layers. We had to support many legacy codes. After a few months, we created a fresh Angular project, we revised the structure, and started working with the latest best practices. We connected the two versions of the dashboard via external routing.
I recommend doing the same for every escalated project. A fresh start is beneficial for the code quality and performance, and you can connect the separated instances via external routing as we did.
These tips and tricks are the key lessons I learned during building and maintaining our enterprise Angular applications. Building a complex Angular application is not as hard as it seems, but you need to be really careful when designing the structure, setting up linters and using third-party libraries. Also, make sure to only update to the latest main Angular version when it’s tested on your app in a safe testing environment.
I hope these will help your work as well.