Juri Strumpflohner
Juri Strumpflohner Juri is a full stack developer and tech lead with a special passion for the web and frontend development. He creates online videos for Egghead.io, writes articles on his blog and for tech magazines, speaks at conferences and holds training workshops.

Update to Angular Version 8 now!

What's new in Angular v8, how to update and what to watch out for

8 min read

Let’s dive into the latest Angular version 8 that just got released. We’ll quickly explore what’s new, why you should update, how that works and what you should watch out for.

Before you start, there’s also an official post about the release from the Angular team:

Table of contents

What’s new? What to expect

So what’s new in v8. Many of the things have already been announced at this year’s NGConf and I’ve blogged about it here:

Here are the main key points:

  • Differential loading - This feature produces separate bundles for legacy and evergreen browsers,thus reducing the amount of polyfills that have to be downloaded (~2-10% smaller bundles).
  • Builders and Deploy - If you ever looked at the angular.json you may have notices the builder API (also known as Angular Architect). While it could already be used (i.e. ngx-build-plus), in v8 the API stabilized and gives 3rd party tooling to hook into the Angular build process. Moreover related to this change, the team also collaborated with the major cloud providers to integrate automated deployment of Angular apps to their respective infrastructure.
  • Web Workers - Angular 8 now allows you to offload heavy work into a separate web worker, thus freeing up the main thread. This allows to further improve the speed and even execute things in parallel in the browser.
  • Service Worker Improvements
  • Code-splitting via import - import() can now be used to execute code splitting
  • AngularJS $location support - Some enhancements have been made to provide better integration with the AngularJS $location service in hybrid (AngularJS <=> Angular) apps.
  • Better IDE completion
  • Simplified Getting Started Guide - The team has worked hard as well to simplify the “Getting Started” Guide and help new people onboard.

But wait 🤔, where’s Ivy? Right! Angular v8 ships with Ivy, however it won’t be enabled by default, yet. The team has enabled Ivy within Google but wants to take another 6 months till v9 to get feedback from community projects. You can see Angular 8 as the transition to full, default Ivy support.
That said, you can totally enable Ivy. Here’s a guide how to do that.

$ ng new my-app --enable-ivy

Or for an existing app, by adding the enableIvy option to the tsconfig.app.json.

{
  "compilerOptions": { ... },
  "angularCompilerOptions": {
    "enableIvy": true
  }
}

If you enable Ivy and encounter any kind of issues, let me know!

Another experimental feature is Bazel. Bazel is Google’s open source variant of their internal general purpose build system that powers their entire infrastructure. The Angular team jumped onto this bandwagon with https://bazel.angular.io/, providing automated Bazel builds via the Angular CLI. Bazel is made to scale via

  • incremental builds (sharing cache between team and CI)
  • full-stack support
  • scale on the cloud

…and comes with some really good first performance improvement results

First build time improvement results by Brad Green at ng-conf 2019

You can opt-into Bazel via

$ npm i -g @angular/bazel
$ ng new my-app [email protected]/bazel

Stay up to date! Evergreen Angular

It’s again time for a new release. As you probably know, when the Angular team started with “the new Angular”, one of the promises was to be very serious about semver when releasing new versions (something that wasn’t the case with Angular v1). Having such “contract” allows us to seamlessly upgrade minor and patch versions throughout the year. At the same time, however, this also means that at some point there will be breaking changes that are necessary to have the framework evolve.

Currently we have the following release schedule

  • patch releases every week
  • ~3 monthly minor releases after each major release
  • a major release every 6 months (usually September/October & April/May)
  • 12 months long-term support (LTS)

Two major releases a year also means two potentially breaking changes, right? While this might seem to be an issue to worry about, it is not, thx to automated migration scripts. The team behind Angular is very cautious about breaking changes. One of the reasons being that they serve Google-internal teams and inside Google, breaking something means fixing it. You can imagine that updating hundreds of apps is not scalable. That’s why the awesome tooling behind the Angular CLI provides “schematics”, “intelligent” scripts that are executed during the upgrade process and modify your codebase to automatically fix breaking changes. Have a look in the video below to see that in action.

That said, it’s extremely important to keep your app up-to-date with the latest Angular version. Upgrading step by step will be much easier than not upgrading for years and then have to upgrade over multiple major versions.

How to update

When it comes to the update process itself, the update.angular.io site is extremely helpful.

The site allows you to choose the start and target version and then gives you a set of instructions on how to update your codebase.

Check out the video below where I update an Angular Material based project from v7 to v8.

What to watch out for

Here are some of the things you might immediately notice at the code level.

Lazy routes

A couple of weeks ago I published an article about the various possibilities we have to apply lazy loading in Angular. You can find it here:

One of them is via routing, and I’m pretty sure you’ve seen that already:

const routes: Routes = [
  {
    path: 'issues',
    loadChildren: './issue-list/issue-list.module#IssueListModule',
  }
];

So far, what we’ve been using in Angular is this “magic string” passed to loadChildren, which was in turn picked up by the Angular CLI to know where to apply code splitting and load the JS file at runtime. Starting with v8, this magic string is no more necessary and has been aligned with the standard way of doing lazy loading across the various tools, which is by simply use an import() statement. As a result, we can now write the lazy route like

const routes: Routes = [
  {
    path: 'issues',
    loadChildren: () => import('./issue-list/issue-list.module').then(m => m.IssueListModule)
  }
];

Note that when updating via the Angular CLI, the schematics will automatically transform your existing loadChildren to the new syntax 🎉.

Queries

When talking about queries, we mean

  • @ViewChild
  • @ContentChild,
  • @ViewChildren (not affected by the upgrade)
  • @ContentChildren (not affected by the upgrade)

When upgrading to v8, there’s a small breaking change related to the @ViewChild and @ContentChild. The team tried to avoid it, but such things happen.

During the upgrade you will get a notification with a link to more details.

You can read up all the details at https://angular.io/guide/static-query-migration.

If the Angular CLI is not able to automatically infer whether to use the static or dynamic resolution, it’ll add a corresponding comment and warning on the console

To summarize, what is it all about?

Assume you have the following:

<div foo></div>

In your code you’d use a @ViewChild such as

@ViewChild(Foo) foo: Foo;

(where Foo is some Angular directive)

Usually it’s always safe to assume foo will be populated after the ngAfterViewInit (or ngAfterContentInit for content queries with @ContentChild). However, some of them were also accessible already in the onInit directly. The reason is that the compiler behind the scenes categories them in

  • static queries available immediately
  • dynamic queries available only at runtime

Our code example above would be an example of a static query because <div foo> it is immediately available. We could safely access it in the ngOnInit. On the other side, assume we change the code like

<div foo *ngIf="isVisible"></div>

In such case, it would only become available once isVisible evaluates to true, which might happen at any time while executing the app. Such queries are dynamic queries.

The main problem is that this wasn’t explicit. Hence, when upgrading to v8, the code migration will automatically transform your code to

// query results available in ngOnInit
@ViewChild('foo', {static: true}) foo: ElementRef; 

// query results available in ngAfterViewInit
@ViewChild('foo', {static: false}) foo: ElementRef;

TypeScript upgrade

By upgrading to Angular 8 you’ll also upgrade to TypeScript 3.4. If you’re curious about the new features here’s the corresponding documentation.

As a result after the upgrade (even though that completes successfully), you may get errors. Most probably they are due to better type inference which reveal new potential typing issues.

Other Deprecations

Check out the new deprecation guide on the official site. Still have questions? Open an issue in the Angular CLI repository if it’s related to the upgrade or on the Angular repository if it’s framework related. Or simply ping me on Twitter 😃


Questions? Thoughts? Hit me up on Twitter
comments powered by Disqus