Academind Logo

Angular 6 - What's New & Upgrade Guide

Angular 6 is out and introduces updates and changes. But what's breaking and what's useful? Let's find out and let's dive into it core updates. Most importantly: Learn how to upgrade!

Created by Maximilian Schwarzmüller
#

Angular 6 - Changes & Updates Overview

Don't miss the video above this article - it walks you through all changes step by step!

In general, your Angular 5 code should still work.

There only is one breaking change which is introduced by a third-party library (RxJS).

Here are all the changes:

#

Updating easily via ng update

This article covers how you may adjust your Angular project to still work with Angular 6. The updating process itself (i.e. installing the new package versions) can be automated though.

The Angular CLI has a new command for that:

ng update

In order to be able to use this command, you need to update your CLI both globally on your machine as well as in the project you want to update:

npm install -g @angular/cli@latest
npm install @angular/cli@latest

To update your project to a CLI 6.0+ project, you can run the following command (inside the project):

ng update @angular/cli

The general folder structure won't really change by a lot (you got a new angular.json file instead of the old .angular-cli.json file) but under the hood, the new CLI is used.

Once you did that, you can analyse an existing project by running:

ng update

This will spit out a table of outdated libraries and how to update them. For some, you'll have to run npm install ... commands manually. For others, it'll offer ng update ... commands.

For example, to update Angular, you run:

ng update @angular/core

If you're facing any errors whilst doing this, make sure to delete node_modules and the package-lock.json file in your project and re-run npm install. If you can't succeed with updating, you can always roll back by installing the older CLI version again (npm install -g @angular/cli@1.7), copying over the src/ code into a newly created project (with that CLI version) and continuing with that project.

#

RxJS 6 Changes - Quick Fix

Angular 6 uses RxJS 6 and that in turn introduces a new internal package structure and operator concept which requires you to update your existing code.

To update to RxJS 6, you simply run:

npm install --save rxjs@6

The quick fix to make your old code work again (with the new Angular and RxJS version) is to simply run the following command in your updated or new Angular project:

npm install --save rxjs-compat

Alternatively, ng update rxjs should do the RxJS update + the installation of the rxjs-compat package automatically.

rxjs-compat is a package that basically adds functionality to the new RxJS version to still support your old import paths and operator usage.

Using rxjs-compat is a fine fix that ensures that your old code continues to work. Ultimately, you should update your code to work without that package though.

This requires two adjustments:

  1. Change your import paths

  2. Change the way you use operators

Don't miss the detailed article I also wrote on the RxJS 6 updating strategy.

#

RxJS 6 Changes - Updated Import Paths

After you got rid of rxjs-compat, you need to adjust your RxJS-related import paths.

import { Observable } from 'rxjs/Observable'
import { Subject } from 'rxjs/Subject'

becomes

import { Observable, Subject } from 'rxjs'

So all from 'rxjs/Something' imports become from 'rxjs'.

Additionally, operator imports have to change - because the way you use operators differs (see next section).

import 'rxjs/add/operator/map'
import 'rxjs/add/operator/throttle'

becomes

import { map, throttle } from 'rxjs/operators'

Instead of patching the Observable prototype - that's what happened in the past - you now explicitly import operator functions like map or throttle. You'll see how to use these functions in the next section.

Last but not least, you also have to adjust your Observable-creator imports.

import 'rxjs/add/observable/of'
// or
import { of } from 'rxjs/observable/of'

becomes

import { of } from 'rxjs'
#

RxJS 6 Changes - Changed Operator Usage

With the imports updated, you're almost there to use RxJS 6 without rxjs-compat.

But since you now import operators as functions (see last section), you need to change the way you use operators.

Instead of

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/throttle';
myObservable
.map(data => data * 2)
.throttle(...)
.subscribe(...);

you now use the new pipe() method introduced by RxJS:

import { map, throttle } from 'rxjs/operators';
myObservable
.pipe(map(data => data * 2), throttle(...))
.subscribe(...);

You simply wrap your operator function calls with the pipe() method and it'll execute them - on the observable data - from left to right.

There also are some other changes - renamed operators for example - but I strongly recommend that you dive into the separate article I wrote on that.

#

Using "angular.json" instead of ".angular-cli.json"

The Angular CLI also received an update and new Angular projects now use an angular.json file instead of a .angular-cli.json file.

This config file still fulfils the same tasks as before, it's schema just changed slightly. If you needed to add a style import to styles[] in there, you'll still find that array in the file though. The same goes for your other config items.

You can automatically update your existing .angular-cli.json file to the new angular.json file by running this command (make sure enable ng update first:

ng update @angular/cli --from=1 --migrate-only
#

"template" is Deprecated

Angular 6 deprecates the <template> element - you can't use it anymore inside of your component templates. Use <ng-template> instead.

Important: <template> has nothing to do with the template or templateUrl of your @Component({...}) decorator! You still use that.

<template> simply was an HTML element you use inside of your component templates, for example in conjunction with ngIf.

<template [ngIf]="isAuth">
<p>This only renders if isAuth is true</p>
</template>

You might not've used this syntax too often because ngIf actually offers a syntactically nicer version: *ngIf. This automatically compiles to the above example when added to the <p> tag.

Or it did so to be precise.

With Angular 6, you should use <ng-template> instead of <template>.

<ng-template [ngIf]="isAuth">
<p>This only renders if isAuth is true</p>
</ng-template>
#

Alternative Way of Providing Application-Wide Services

If you want to provide a service to the entire application, you add it to providers[] in the AppModule.

// my.service.ts
export class MyService { ... }
// In app.module.ts
import { MyService } from './path/to/my.service';
@NgModule({
declarations: [...],
providers: [ MyService ] // The same instance of the service is now available across the entire app
})
export class AppModule {}

This approach still works and there's nothing wrong with it!

But with Angular 6 released, you can also use an easier way of marking a service as global:

// my.service.ts
@Injectable({providedIn: 'root'})
export class MyService { ... }
@NgModule({
declarations: [...],
providers: [] // Service does not need to be added here
})
export class AppModule {}

Both code snippets lead to exactly the same behavior, the second one obviously saves you some lines of code.

#

Angular Elements

Angular 6 introduces Angular Elements - a feature that allows you to compile Angular components to native web components which you can use in your Angular app.

This is important: You can use them in your Angular app. In the future, this may change but right now, you don't get web components you could dump into a web app using a different (or none) JS framework!

How does it work then?

I created a video & article where I show an example.

#

A First Look at the new Ivy Renderer

The last important addition of Angular 6 is a new Renderer - the engine which renders your Angular app behind the scenes (i.e. which works with the DOM etc).

Angular 6 introduces Ivy and for now, it's only in beta. It's not stable, not feature-complete and not ready for production!.

You can see a demo here.

The goal of Ivy is to drastically reduce the bundle size of your app and speed up its loading time. It aims to be backward-compatible but as you can see in the above demo, it uses a different approach for rendering Angular components.

Feel free to play around with it, dive into the official status tracker to see what you may use already but keep in mind that this only becomes a real alternative when Angular 7+ is released.