Advice I Wish I Had Been Given Before Upgrading From AngularJS to Angular 2+
As you probably know, there is a world of differences between AngularJS and the new Angular (versions 2 and up). Even thinking of upgrading is an adventure on its own. Luckily the developers behind Angular have put a lot of effort into making sure the experience is as painless as possible. But the road to Angular is still challenging when you want to upgrade anything other than a small web app.
I know there are already many articles discussing this, but most of them are tutorials for super simple cases. That’s not what you’re about to read… For a technical step by step, visit Angular.io (after reading this article, of course).
At Poka, we’ve slowly upgraded to Angular 2 (then 4 in the process) while still developing new features for our clients. It took a year (part-time) from beginning to end and we’ve encountered a lot a issues and obstacles along the way. We want to share our experience with you while offering you some tips and tricks.
This is a general guide on what to expect, how to prepare, and when to do what as you’re upgrading your app to Angular 2 and up.
To fully take advantage of Angular, you’ll absolutely want to move from vanilla JS to TypeScript. Don’t worry, this step might just be the simplest one of them all.
If you wanted to, you could just change your file extensions from .js to .ts and you’d be done. If you’re in a hurry to switch away from AngularJS, maybe skip ahead to the next step… But by doing so, you’ll be missing out on all the cool TypeScript features.
If you want to take the time to do this right, add type annotations to your existing code. You might discover that some of your code was not optimal, or you might even find some unsuspected bugs that you never knew existed.
Developing and building your hybrid app
Depending on your project or preferences, you will want to use either AngularCLI or a custom Webpack config to develop your Angular app.
If you don’t have super specific custom needs, I highly recommend using AngularCLI. It has great developer support and also everything you need to develop, test, lint and build. As Angular will evolve, so will the CLI.
However, if your app has particular technicalities making AngularCLI unsuitable for it (like ours at Poka), go for a Webpack configuration of your own.
Make sure the solution you pick suits your app perfectly. Switching mid-conversion can be a real pain…
Angular has this thing called TestBed. According to the doc, TestBed:
Configures and initializes environment for unit testing and provides methods for creating components and services in unit tests.
It allows way more than just unit tests. It compiles and simulates your components’ templates and checks for errors; the whole package! It’s a complete testing tool that will allow you to test in a more realistic fashion… But it’s slow. Real slow.
On our main web app, we have more than 3,000 tests. When we ran our tests with TestBed initiated for every component, it would take between 40 minutes to an hour for the first pass. We thought that by switching from PhantomJS to HeadlessChrome we would win a couple of minutes. We were wrong.
Now I’m going to swim against the current here and recommend you do not use it. Every official doc and tutorial says you should… and maybe you should for small projects. However, on a big app like ours, or if you do TDD, it’s downright unusable.
I’m not suggesting you shouldn’t test your code. You should. Seriously, do it. But if you have a lot of tests (1000+), you should only focus on simple unit testing without using the TestBed. Anyway, since you’re converting from AngularJS, that’s probably all you have right now. Don’t bother using Angular’s (amazing) TestBed. It’s great, but it’s too slow…
You’ll now need to begin converting. Keep in mind that the foundation of your application will be your main AngularJS component as long as your app is hybrid.
If your app is split in independent modules, you should convert a whole module at a time. If it’s more of a giant module with a lot of interdependencies, consider starting with your AngularJS directives if you have any, then your components (except your main AngularJS component), then your filters, and finally your services.
Note: routing will be covered in the next section.
While converting, you’ll need to upgrade and downgrade your components. Here are a few tips to avoid going crazy when unsuspected errors occur.
- In your bootstrapping, you’ll need to add an array of entryComponents. These are Angular components that (may) appear when the AngularJS app starts. The thing is, from the standpoint of AngularJS, pretty much any Angular component can be entry points to the Angular app. If you’re having trouble reaching a component, try adding it to your entryComponents.
- When downgrading converted components, don’t forget to specify what its inputs and outputs are. If you add or remove any input or output from a component, don’t forget to reflect those changes in your AJS declaration.
inputs: ['kyberCrystalStatus', 'crew', 'director'],
}) as angular.IDirectiveFactory)
- When using Angular components inside AngularJS components, do not write your inputs and outputs as you normally would. In other words, use
[death-star-plans]. Don’t forget to put everything back in
camelCasewhen converting a component containing already converted components.
- Take notes of any weird bug that you’ve had and resolved. If your upgrading process takes as long as ours took, you might forget what you’ve done to solve the problem. This could save you hours of head scratching and avoid a lot of frustration.
Routing and main component
Your routing should still be handled by AngularJS at this point. It’s now time to convert the last pieces of your application.
I suggest you do both routing and your main component in a single step. The latter will seem fairly easy as you should be very at ease with component conversion by now.
The routing can seem a bit tricky, though. If you’ve only used the basic AngularJS router in the past, you might be impressed with the nestable routing Angular offers. It’s super flexible and easy but again, depending on the size of your application, I’d suggest to keep your routing to a single level for now and keep optimizations for later. We want to leave the hybrid state as soon as we can!
Getting rid of AngularJS and optimize!
You’ve made it! Remove everything AngularJS related and enjoy the beautiful code of your superb Angular app. At last you can focus on making your app even better.
Here’s how you can improve your app further:
- With Typescript: Create interfaces and use them. If everything in your app has type definitions, you’ll fully enjoy Typescript. Also, don’t be shy to use ES2015 and ES2016 features. It’ll just be converted in ES5 anyway :)
- With RxJS: You absolutely have to harness the power of reactive programming! Maybe not everywhere in your app, but at least where there is any kind of user interaction. It makes your code so much cleaner and effective. Learn more about RxJS here and if you can’t wrap your head around how Observables work, check out this post by André Staltz.
- With AoT and Tree Shaking: Every time a component is used, it must first go through the Angular compiler to convert your template and code. This is done client-side (Just in Time compilation) and takes some precious time. Ahead of Time compilation or AoT is the same process, but as a build step. If you can, you should use AoT along with tree shaking as it will considerably speed up your app and reduce its size. I say “if you can” because as of today, if your app is too big, your build step might fail when trying to compile using AoT. This is a documented issue and I’m optimistic it will be fixed soon.
Hopefully this will help you crush the upgrading process of your Angular app. If you’ve been through this before and want to leave more tips and tricks, feel free to help your fellow developers and add them in the comments below.