Upgrading from Angular 5 to 6

Home / Upgrading from Angular 5 to 6

In case you missed it, Anuglar 6 was released a few days ago. I decided to take one of my primary Angular 5 projects and upgrade it. Man, it was painful ..


Up front, the main thing that makes upgrading Angular is that React 6.x is required. RxJs has a lot of breaking changes. Before we get into that, though, here’s my package.json so that you can see exactly what I’m using / wound up with after the upgrade. My application is also aVisual Studio 2017 / VSCode solution, so I’m not really using angular-cli.

{
  "name": "aspnet-core-demo",
  "version": "1.0.0",
  "description": "Simple demo",
  "author": {
    "name": "Stephen Long",
    "url": "http://long2know.com"
  },
  "license": "MIT",
  "homepage": "http://long2know.com",
  "repository": "https://github.com/long2know",
  "dependencies": {
    "@angular/animations": "6.0.0",
    "@angular/common": "6.0.0",
    "@angular/compiler": "6.0.0",
    "@angular/compiler-cli": "6.0.0",
    "@angular/core": "6.0.0",
    "@angular/forms": "6.0.0",
    "@angular/http": "6.0.0",
    "@angular/platform-browser": "6.0.0",
    "@angular/platform-browser-dynamic": "6.0.0",
    "@angular/platform-server": "6.0.0",
    "@angular/router": "6.0.0",
    "@angular-devkit/schematics": "0.6.0",
    "@ng-bootstrap/ng-bootstrap": "2.0.0",
    "@ngtools/webpack": "1.8.0",
    "@ngx-translate/core": "8.0.0",
    "@types/jquery": "3.2.12",
    "@types/webpack-env": "1.13.1",
    "angular2-template-loader": "0.6.2",
    "aspnet-webpack": "2.0.3",
    "awesome-typescript-loader": "3.4.1",
    "bootstrap": "4.1.1",
    "bootstrap-datepicker": "1.8.0",
    "bootstrap-select": "1.13.1",
    "bootstrap-toggle": "2.2.2",
    "bootstrap-vertical-tabs": "1.2.2",
    "toastr": "2.1.4",
    "core-js": "2.5.6",
    "css": "2.2.1",
    "css-loader": "0.28.7",
    "event-source-polyfill": "0.0.9",
    "expose-loader": "0.7.3",
    "extract-text-webpack-plugin": "3.0.0",
    "file-loader": "0.11.2",
    "font-awesome": "4.7.0",
    "html-loader": "0.5.1",
    "jquery": "3.2.1",
    "json-loader": "0.5.7",
    "node-sass": "4.5.3",
    "popper.js": "1.14.3",
    "raw-loader": "0.5.1",
    "rxjs": "6.1.0",
    "sass-loader": "6.0.6",
    "style-loader": "0.18.2",
    "to-string-loader": "1.1.5",
    "typescript": "2.7.2",
    "url-loader": "0.5.9",
    "web-animations-js": "2.3.1",
    "webpack": "3.6.0",
    "webpack-hot-middleware": "2.19.1",
    "webpack-merge": "4.1.0",
    "zone.js": "0.8.26"
  },
  "devDependencies": {
    "tslib": "1.9.0",
    "@types/chai": "4.0.4",
    "@types/jasmine": "2.6.0",
    "chai": "4.1.2",
    "jasmine-core": "2.8.0",
    "karma": "1.7.1",
    "karma-chai": "0.1.0",
    "karma-chrome-launcher": "2.2.0",
    "karma-cli": "1.0.1",
    "karma-jasmine": "1.1.0",
    "karma-jasmine-html-reporter": "0.2.2",
    "karma-webpack": "2.0.4",
    "gulp": "3.9.1",
    "gulp-concat": "2.6.1",
    "gulp-watch": "4.3.11",
    "gulp-cssmin": "0.1.7",
    "gulp-uglify": "2.1.2",
    "gulp-append-prepend": "1.0.3",
    "gulp-async-tasks": "1.0.0",
    "merge2": "1.0.3",
    "rimraf": "2.6.1"
  },
  "scripts": {
    "dev-build": "node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js",
    "test": "karma start ClientApp/test/karma.conf.js"
  }
}

In order to get things working, I had to grab the latest version of NodeJs and install it (8.9 or newer is required). After upgrading all of my node modules, the fun began.

As I said before, the primary changes are related to RxJs. All imports have changed, especially in regards to operators. For example:

This:

import { Observable, Subscription } from "rxjs";
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/finally';

Becomes this:

import { Observable, Subscription, timer, of, from } from "rxjs";
import { map, tap, catchError, finalize } from "rxjs/operators";

Creating Observables with the “Observable.of” method has been reduced to “of.” Similarly, “Observable.from” is reduced to simply “from.”

The biggest change, along the same lines, is that most methods, which created a sort-of fluent API, have been removed from being attached directly to an Observable. Instead of calling methods like map, switchMap, merge, etc etc directly on the Observable are delegated through the new “pipe” method of an observable.

As an example, the one modal “spinner” request interceptor I use went from this in the intercept method:

return next.handle(req)
	.do((event: HttpEvent<any>) => {
		// Reset the timer ..
		if (this._idleTimeoutSvc) {
			this._idleTimeoutSvc.startTimer();
		}

		if (event instanceof HttpResponse) {

		}
	})
	.catch(err => {
		if (err instanceof HttpErrorResponse) {
			if (err.status === 401) {
				// JWT expired, go to login
				// Observable.throw(err);
			}
		}

		console.log('Caught error', err);
		return Observable.throw(err);
	})
	.finally(() => {
		this.turnOffModal();
	});

To this:

return next.handle(req).pipe(
	tap((event: HttpEvent<any>) => {
		// Reset the timer ..
		if (this._idleTimeoutSvc) {
			this._idleTimeoutSvc.startTimer();
		}

		if (event instanceof HttpResponse) {

		}
	}),
	catchError(err => {
		if (err instanceof HttpErrorResponse) {
			if (err.status === 401) {
				// JWT expired, go to login
				// Observable.throw(err);
			}
		}

		console.log('Caught error', err);
		return Observable.throw(err);
	}),
	finalize(() => {
		this.turnOffModal();
	})
);    

You’ll notice also that some things are renamed; do becomes tap, catch is catchError, finally is finalize, etc. You can see that most of these is changed to avoid collisions with JavaScript / TypeScript keywords.

So, basically, I had to step through all of my components replacing the RxJs imports, replace all Observable methods to delegated “pipe” methods, etc. All in all, the process was tedious, but everything seems to be working in my application.

Here are a few links that I found useful over the past few days as well:

https://www.academind.com/learn/javascript/rxjs-6-what-changed/
https://alligator.io/angular/angular-6/
https://www.learnrxjs.io/

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.