Dragons when upgrading from Angular 2.1.x to 2.4.x

The reason why I decided to upgrade to 2.4.x was simple enough. On trying to redirect to a new URL I was getting a rather obscure error message, and no amount of URL fiddling worked to get a redirect to work or get me a sensical error message:

error_handler.js:47 EXCEPTION: Uncaught (in promise): TypeError: Cannot read property '_outlets' of undefined
TypeError: Cannot read property '_outlets' of undefined
at http://localhost:4200/main.bundle.js:14278:56
at forEach (http://localhost:4200/main.bundle.js:5901:13)
at PreActivation.deactiveRouteAndItsChildren (http://localhost:4200/main.bundle.js:14277:99)
at http://localhost:4200/main.bundle.js:14279:19
at forEach (http://localhost:4200/main.bundle.js:5901:13)
at PreActivation.deactiveRouteAndItsChildren (http://localhost:4200/main.bundle.js:14277:99)
at PreActivation.traverseRoutes (http://localhost:4200/main.bundle.js:14262:22)
at http://localhost:4200/main.bundle.js:14233:19
at Array.forEach (native)
at PreActivation.traverseChildRoutes (http://localhost:4200/main.bundle.js:14232:29) .

From the Github issue thread, the easiest fix was to upgrade to a later version of Angular2, which I tried and little did I know it opened up a brand new can of worms. Here is a summary of dragons that may lie in your path to an upgrade.

Lazy Loaded Module Paths

The most obvious errors you will get if you are using lazy loading of your modules using the CLI in 2.1.x and you upgrade to 2.4.x will be path resolutions errors. All lazy loaded modules in 2.1.x were loaded with a path relative to the src directory. In 2.4.x you will have to upgrade these paths to be relative to the file that is configuring the lazy loading.

Dependency Injection, Singletons and Lazy Loading

The most insidious “error” I ran into resulted actually from an enforcement of Angular2 DI rules. To describe the issue, trying to navigate to one of the routes of the application relied on the lazy loading of a module but I consistently got a blank page. Debugging the issue further, it turned out that the authentication guard that was placed on that route was failing, preventing navigation to the route. The user was definitely authenticated so this did not make sense. I dug further and it turned out that the Auth service which initially was using the rightfully authenticated logged value, was using a different value when used by the guard service. There were in effect 2 instances of what I assumed was a singleton in 2.1.x. You can see a similar description of the issue here.

You can read about Angular2’s hierarchical DI model but in the specific case of lazy loaded modules, you have to understand that they create their own branch on the Dependency Injection (DI) tree. The reason why is that as such,

it’s possible to have services that belong to a lazy loaded module, that are not accessible by the root module or any other eagerly loaded module of our application.

Why this was not enforced in 2.1.x, I don’t know but starting with 2.2.x the enforcement is definitely present. In order to create true singletons, you have to use Angular2′ hierarchical DI structure and have your lazy loaded module use the same dependency injection tree as the rest of the application. This tutorial covers the details in an excellent way and I highly recommend it.

Error: *Module is not an NgModule

Last but not least in the list of upgrade errors I ran into was this cryptic:

Error: *Module is not an NgModule

I put * because it happened for a couple of different modules for me and it’s listed as an issue on the Angular repo. This seems to be related between incompatibilities in third party libraries using versions of Angular < 2.2.x in a > 2.3.x environment. This happens when you list the module in question as part of the imports in a module. The suggested workaround that I used for now was to still import the module but to manually list the import components/services in the imports/exports section of the defining module until a fix is found.

Resolving these issues brought my app back to a seemingly working state, I might run into more issues and if I do and resolve them, I will make sure to share. If you have insights, explanations or fixes on any of the issues I listed here, please make sure to share in the comments.

Angular2: A couple of months in

Like any other Angular 1.x developer, I have followed the evolution of the next version of the platform from its announcement through its eventual release. I was not incensed by the lack of (complete )backwards compatibility, as some seemed to be on the initial announcement; the way I saw it, it was indeed a complete rewrite intended on fixing what was missed in the 1.x version using more modern concepts, which I am all for. The 1.x project I was on was mission critical so there was no way of attempting to rewrite it in 2.0 but I prepared by adopting John Papa’s excellent 1.x style guide recommendations, which if you are not, you should (Todd Motto’s is another excellent alternative). I followed the news on each of the RC releases, practiced with one of the initial SystemJS versions of the Tour of Heroes tutorial on the official site to get a feel for the platform and Typescript until I was finally able to work on a full fledged Angular2 project. This is a summary of my experience learning and using the platform two months in.

Learning Angular2

I started from the source, so after initially doing the SystemJS Tour of Heroes, I naturally went back to do it again this time using the CLI build version, having forgotten most of what I had learned initially. The second run through was informative, helping break in some of the new concepts by contrasting them at times with the way Angular 1.x did things. Overall I found the tutorial a good way to break into the framework, although some of the concepts can take a minute to sink in.

An additional hurdle for me was also making the transition to Typescript, which outside of typing can also be compiled to include most of the ES6 features. This made the learning curve a bit more steep but as with everything I have learned in programming so far, nothing builds confidence like practice. The addition of types makes code in my opinion clearer in defining contracts when creating APIs. It looks daunting from the outside but once you get of hang of it, it becomes second nature and your brain gets better at understanding and processing the code when scanning it. Now to get to the meat of the matter, what does it feel like to work with Angular2?

Angular2 is a good/great framework

There is one reason why Angular has spread in the enterprise world the way that it has and contrary to what you might have heard with all the new frameworks popping up, it’s not going anywhere anytime soon. To build large scale enterprise application within the context of a team where knowledge has to be shared, it’s in my opinion one, if not the best frameworks out there. The addition of Typescript, like it or not, has in a way reduced the barrier of entry for those who were considered before pure backend developers. Anecdotally, friends of mine in the .Net world have found the transition to buildings UIs a lot less complicated when using Angular2. Something about types and static language developers…

To get back to what makes Angular2 a good/great (depending mainly on the type of problem you are trying to solve) framework, here is a list based on my experience:

  • Angular2 is well designed, you can tell by comparison with Angular 1.x, which was built out of the concept of providing easy two-way data binding, that lessons were learned and applied .
  • Documentation is good: with the new site, the accent is really put on getting you going as fast as possible but with access to more advanced concepts not too far away. It can be confusing and overwhelming at times, but I found it so far to be useful.
  • Component based approach: That’s the way of the future, and it has been made trivial in Angular2. It’s an easy and natural way to represent and application. The only hard part, which is not unique to Angular2 is to decide how atomic to get in the creation of components.
  • Routing: The one weak point of vanilla Angular 1.x which was easily remediated with the excellent UI Router. Now it’s a module on itself with all kinds of functionality, everything you need to handle your routing needs.
  • LifeCycle hooks: Finally Angular officialised a way to hook into initialization and finalization in a way that did not feel hackish when creating views/components (Yes I know, using .component in 1.x offers the same functionality).
  • Quirky function and component names: You loved them in 1.x, they’re back in 2. forRoot anyone?

But seriously I felt Angular2 gave me all the tools needed to be able to develop my application and even more should I want to dig deeper. There were dragons though.

Angular2 is difficult to grasp (initially)

I know you all remember the famous graphic listing the Angular 1.x learning curve, i feel like that initial curve is even steeper. As i said earlier, the introduction of Typescript makes it even more intimidating. I am a seasoned veteran, with years of JS and Angular development behind me but it took me a bit of time to get comfortable with the framework, especially in trying to use best practices when designing and implementing features. It’s nothing for the most part that going back to the documentation often and Google Fu won’t fix, but it’s not always obvious. To summarize my feeling about it, as I was struggling through the initial phases of learning, I thought about all the new developers coming to the Web Development world through self learning and all these bootcamp type of schools and wondered how the learning curve would be for them. Maybe it is a case of old dog learning new tricks but with the emergence of Typescript, ES6, RxJS and functional programming, I feel like the barrier of entry into Front End Development has been kicked up quite a notch.

Angular 1.x was famously known for it’s steep learning curve but for a complete newbie, a good preparation in Javascript would be good enough to eventually understand it and become proficient in it, but now there are new concepts (mainly related to RxJS) that have been made part of the core framework which significantly kick up the complexity level of the framework. With the case of promises and observable for example, the intent for the makers of the framework is clearly to move into the Observable direction, but for the purpose of backwards compatibility, support for Promises is still around and it is also the way to handle HTTP calls used in the basic tutorial until you go deeper. It’s a good thing and a bad thing at the same time for me because as I learned Angular2, I wanted to learn the best practices at the same time, so even though the example with the Promises made sense, from everything I had read before I knew that it was not the “best” way of going about interacting with the API but I guess it helped easing me into the framework by proposing something familiar but in hindsight I would have liked a more tear the BandAid approach to getting up to speed with Angular2.

Angular2 annoyances and gotchas

  • How do I add custom tasks to the CLI?
  • Watch out for Shadow DOM style scoping: ( :host \deep\ shall be your friend). i.e if you’re losing your mind trying to override global styles in a component, read the documentation.
  • An HTTP call returns an Observable, but the HTTP call itself won’t fire if you don’t subscribe to the returned observable. It seems obvious now but in practice, not so much.

In summary, after working with it for 2 months now, I am still a believer in the Angular way. I think the team solidly positioned Angular2 to move forward with the best that is being done in Front End development moving forward and to do so, moving away from 1.x was necessary. So far I have seen good support for the 1.x version of the framework, and applications written with it at this point are “outdated” only in your mind. Angular2 is a different approach and you should definitely consider it for your next project but be prepared for a steeper learning curve.