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.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s