Angular 2 rc.4 to rc.5 migration: quite smooth but still breaking!
Ten days ago I migrated this blog from Angular 2 rc.4 to Angular rc.5. Since all migration since beta.1 were not "free" I didn't expect to not spend some time on it but this time it didn't hurt as much as usually. Let's see the few pitfalls I hit.
NgModule
Angular rc.5 introduces the notion of module. This is very very close to Guice concept where you define a part of the application you can import in another part (module).
Typically for this blog I have for instance few components to show a post or a list of post. I was then able to define a module for these generic components reused accross the blog:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { PostList } from './post-list.component';
import { PostSummary } from './post-summary.component';
@NgModule({
imports: [
CommonModule,
RouterModule
],
declarations: [
PostList,
PostSummary
],
exports: [
PostList,
PostSummary
]
})
export class PostModule {
}
This module simply import Angular base components (CommonModule) and router components (to have routerLink links), declare the two generic components I defined and export them as reusable.
Then with rc.5 you need to define a main module you will use to bootstrap the application - I simplified the snippet since it is longer in practise but the overall idea is there:
import {NgModule} from '@angular/core';
// other imports
@NgModule({
bootstrap: [ App ],
declarations: [
// app component
App,
Home,
Login,
Logout,
AdminPost,
AdminPosts,
Search,
// ...
],
providers: [
// app services
NotificationService,
SecurityService,
RestClient,
// ...
],
imports: [
// app modules
PostModule,
// angular2-notifications
SimpleNotificationsModule,
// angular built-in modules
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot(routes, { useHash: true })
]
})
export class AppModule {
}
Defining a module is just a matter of defining some services (providers), components (declarations there), which component is used to bootstrap (main component) and which modules are imported.
Then the bootstrap itself of the application is as easy as referencing this module:
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app/app.module';
// note: you can desire to activate prod mode there too
platformBrowserDynamic()
.bootstrapModule(AppModule);
The implication is all components need to get rid of directives and providers since it is now handled at module level.
So this components:
@Component({
selector: 'users',
template: require('./users.pug'),
directives: [SimpleNotificationsComponent],
providers: [NotificationsService, NotificationService]
})
became:
@Component({
selector: 'users',
template: require('./users.pug')
})
Http service bug?
I was using a RestClient wrapper to Http service provided by Angular. It was mainly responsible of handling headers. I was setting Content-Type one to json by default and therefore was setting it to all requests including GET ones. This was not perfect but avoided to define a set of headers for requests with a payload and another one for other requests.
In rc.5 if you set Content-Type payload is parsed even if missing so a GET request with a Content-Type header will fail with a:
Can't call toString on null
The fix was of course to split the header sets for POST and GET requests. Having a custom RestClient made it easy and very localized in the code but i'm not sure why Angular doesn't tolerate it since it is actually quite common to do that and set globally write/read headers.
Conclusion
Blog is migrated to rc.5 and seems to run fine. I was quite happy to see that the dependency I used to get notifications (angular2-notifications) was migrated super fast to rc.5 and I didn't have to wait too long (actually less than a week) before being able to import its module and avoid to need to write my own version of the NotificationModule.
Angular2 ecosystem is hwoever still moving very fast and breaking API between each release. I'm not sure what's the goal is and even if the API is closer and closer to what we do in Java (yeah!) this is still not a good choice for customers. There are still several TODO in the code and it is moving too fast to not imply a cost we likely want to avoid in real life projects.
From the same author:
In the same category:

