The old AngularJS and new Angular logo. Not confusing at all.
If you do have an old AngularJS app kicking around, it’s definitely time to consider uplifting it. AngularJS was superseded by version 2 of the framework back in 2016. Confusingly, all of the 1.x versions are now known as AngularJS, while everything from version 2 onwards is called Angular. Angular is a complete re-imagining of the AngularJS framework: while both frameworks share many of the same concepts, they are not compatible with each other. In addition, Google has dropped support of all versions prior to 1.7, and version 1.7 will reach end-of-life on June 30, 2021.
What does this mean for you? Firstly, if you’re using an earlier version of AngularJS, you’re not getting any security updates, which leaves you at risk of a data breach. It’s also becoming increasingly difficult to hire developers to work in AngularJS, as most would prefer to work in a more modern framework, and most new developers haven’t had any experience working with the older framework.
The new Angular framework also offers many advantages over AngularJS. It has a better change detection cycle, and supports modern features like lazy-loading and server-side rendering, allowing for improved performance. It also has an improved component model, uses TypeScript and provides an extensive CLI, to speed up development. As a result, the experience of both the user, and the developer is greatly improved.
Unfortunately, the upgrade path from AngularJS to Angular isn’t entirely straightforward. As a result, the Angular team have created a package called ng-upgrade, which allows you to run both AngularJS and Angular in the same application. This allows you to upgrade your app incrementally, building new features in Angular, and gradually replacing the existing AngularJS features.
ng-upgrade was created by the Angular team to help ease the transition from AngularJS to Angular by allowing you to run both frameworks, side-by-side, in the same application. While this does incur a slight performance penalty, this is usually offset by improvements in the way the application is built, and the ability to use Angular’s lazy loading features.
In order to use ng-upgrade, you need to add a new Angular app inside your existing AngularJS application. You can create the application using the Angular CLI
It’s best to do this in a separate folder and then copy the generated files over, so you don’t overwrite any of your existing configuration files, like package.json. Files that exist in both your AngularJS repository and the new Angular application will need to be merged manually.
The easiest way to use ng-upgrade is to let the Angular CLI handle the build process. To do this, you need to do two things.
- Move all the relevant stuff from your old index.html to Angular’s index.html, which is located at /src/index.html
- Get Angular to bootstrap the AngularJS app module, instead of the Angular app module, via UpgradeModule
src/index.ts: bootstrapping an AngularJS module from Angular
Once this is done, you’re free to generate new Angular components and providers to use in your AngularJS templates, or to upgrade existing AngularJS components to use in your new Angular features. The ng-upgrade documentation at angular.io (https://angular.io/guide/upgrade) has pretty good instructions for how to do this. However, it’s lacking in a few important details.
Follow the Angular style-guide
First of all, the ng-upgrade instructions suggest that you should refactor your existing codebase so that it follows the Angular style guide. This probably isn’t going to be the best use of your time.
If your codebase already follows the style-guide, then, yes, you are going to have an easier time upgrading. If your codebase looks more like most of the legacy AngularJS code I’ve seen, with all the logic in a single controller, 2,000 lines long, then things are going to be a bit more difficult. However, it’s likely to be just as much effort to refactor it as it would be to just upgrade it as-is.
I’ve upgraded an application written in AngularJS 1.4, with over a hundred controllers, some over a thousand lines long, all in a single module, with no apparent idea of isolated scope. It wasn’t a particularly enjoyable experience, but refactoring the code wouldn’t have been either. On top of that, unless you have very good tests, refactoring carries the risk of introducing all kinds of bugs into the codebase. My advice would be to leave the AngularJS code alone until you really need to touch it.
Using a module loader
As mentioned in the upgrade guide, you’re going to need a module loader, so that Webpack and the TypeScript compiler can manage the legacy code. The good news is that this isn’t necessarily that difficult to setup.
You’ll need to import all of your project files, along with any dependencies from your node_modules directory. Now, importing like this isn’t ideal, as you miss out on the dependency tree management that webpack provides, so there’s a chance you could be importing things you don’t need. It’s also a bit tedious to setup, so I’d recommend scripting it. Something like
The advantage of doing things this way is that you can move on with more valuable work quite quickly. And, you now have a list of all the things that need to be upgraded. Imagine the satisfaction you’re going to get as you delete each item off that list. As with the previous section, I’d recommend using this quick and dirty set-up, up until the point it starts causing you issues.
Populating the template cache
Every AngularJS app I’ve ever worked on has used external HTML templates, and a gulp plugin or similar to populate the template cache. However, the template cache just isn’t a concept that exists in Angular. As such, I found it a bit suspicious that the official ng-upgrade guide doesn’t make even a passing mention of how to deal with upgrading it. I suspect it’s because there isn’t a great solution out-of-the-box. While a webpack version of gulp-angular-templatecache does exist, using it requires ejecting our application, rendering the CLI unusable. And we don’t really want that.
The simplest solution I have found for this problem is to use the webpack raw loader to populate the cache ourselves. We can use a script similar to the one that found all our JS files to also find all our HTML files. Then we can do something like this to them…
Again, this definitely isn’t something I would do with an app under active development. For our use case though, it’s fine. We’re never going to add any new templates to the template cache, as any new components we build will be created in Angular, and the CLI knows how to deal with those templates. Plus, we get another list of things that we’re going to delete!
Is it worth it?
The answer to that is going to depend on your specific situation.
If you have no reason to worry about data breaches, your app is working fine, and you’re not planning on changing it any time soon, then upgrading is unlikely to be worth the effort. This could easily be the case for internal facing apps, or apps which provide non-critical data, and don’t allow any updates.
If your app doesn’t fit into this category, then you definitely want to move away from AngularJS. For smaller apps which aren’t under active development, ng-upgrade adds a bit of complexity, without really providing much value. In these cases, a complete rewrite could be the better option.
ng-upgrade really provides the best value for medium to large sized projects where the upgrade needs to happen while the app is under active development. In this situation, ng-upgrade provides a neat way to separate the upgrade work from the on-going development work, increasing development speed, and reducing the amount of duplicated work.
The actual effort involved in setting up ng-upgrade for your project is going to depend a lot on the state of your application. For a reasonably modern app, built with components, and already using a module loader, you’re looking at a few days’ worth of work. Things begin to get a bit more complicated if you’re using an older version of AngularJS, you don’t have a module loader, or the code isn’t following best practices. Either way though, the gains in security, development speed, and ease of hiring will outweigh the costs quite quickly.
Angular is absolutely still a viable framework, with many active users, and its batteries-included approach makes it the ideal choice in a lot of situations. ng-upgrade extends that approach to provide you with a well-defined path to move away from AngularJS, without sacrificing productivity. While there are a few gotchas to keep in mind – aren’t there always? – once you get up and running, the process is very smooth, and developer productivity (and happiness) is sure to increase.
Need help reviewing your tech? Get in touch here.