How should AngularJS 1.x be used, to make things easier (as easy as they can be…) if the time comes to port an application to Angular 2? This is a frequent topic of discussion at our Angular Boot Camp classes, which are still quite popular (in early 2016) for AngularJS 1.x even as Angular 2 grows close to release.
We often have students or private class managers ask that our class cover this topic, but they really don’t even need to ask. Over the last 6-9 months we have revamped our curriculum and approach to teaching AngularJS 1.x to pervasively answer aspects of this question. Here it is, in a more explicit summary:
- Build your application mostly from components. If you are able to use 1.5 right now, go ahead and use the new .component() API extensively. If you are stuck on an older version, use component style directives. Regardless, mostly follow the component pattern, only reach for a standalone controller or template in rare cases.
- The migration tools coming from the core team are about migrating from 1.5 forward, not about older versions; so if you have an application built on an 1.4, 1.3,, or even older, now is a good time to move past whatever is stopping you from upgrading to 1.5. There are numerous other benefits to upgrading also, each incremental version of AngularJS 1.x has improved performance and other areas.
- Make your components mostly push data downward using data binding.
- Make your components mostly push information about things that happened upward, mostly using “&” hooks (the closest thing in A1 to A2 events).
- Mostly use the A1 features data binding, to avoid needing to write things like manual $watches. We have found at Oasis Digital that nearly every manual watch can be removed and replaced with data binding, letting AngularJS itself watch (and stop watching when appropriate) an expression instead.
- Minimize or avoid the A1 scope event system; use it only in very unusual cases. There is nothing like it in A2, and even in A1 it is of limited utility with a component-centric approach. Those isolate scopes will stop events anyway. We typically use the scope event system only for things like talking to APIs which are exposed in that way (like route change notifications).
- Consider TypeScript, today, even on AngularJS 1.x. Here at Oasis Digital, we have done this and been very pleased with the results. We have found and fixed numerous bugs with the help of the type system, which otherwise would have been fixed later and a greater expense and risk, with testing or with production failures.
An application built in this way (and following some other things that I have overlooked) is ready to walk the Google-sanctioned migration path, mentioned from conference stages by Google team members. First make old code look more like Angular 2 (ng-forward), then put Angular 2 on the page alongside AngularJS 1.x (ng-upgrade), then convert components one at a time, then eventually remove AngularJS 1.5 from the page.
Sometimes Reality Is In The Way
We have worked with numerous teams working on numerous medium and large AngularJS applications; and sometimes the reality is not so compatible with the idealized path described above. For older, large AngularJS 1.x projects, the upgrade path might actually look something like this:
- Rewrite your AngularJS 1.x application, to follow 2015/2016 best practices, instead of the 2012 practices it is built with.
- Then you can follow the recommended upgrade path to make it a Angular 2 application.
Obviously this is not an especially appealing path. We believe there will be many large AngularJS 1.x projects that simply remain in that framework for a long time to come; and this is okay, a working application does not necessarily need to be rewritten. For many applications the path to the next framework (whether that be a newer version of Angular, or one of the many competitors) is to write the replacement application far in the future, in that new framework.
For that reason and many others, perhaps the best advice is this: don’t write huge applications at all. If you have a problem space which appears to warrant a huge application, think about it carefully and divide it up into several cooperating medium-sized applications, which might appear as one from a user point of view but which are not entangled with each other technically more than necessary. With such a system design, if the day comes that it will be moved to another framework/library (Angular 2, React, Vue, Mithril, Elm, Ember, Reagent, Om, I could go on…) you have the option of converting a portion of an overall system at a time. This is both faster, cheaper, and less risky than migrating a gigantic monolith all at once.