Angular 10 in depth

Angular 10, the latest major version of Angular has just been released. Time to discover what’s new!

Sébastien Dubois.
Jun 26 · 11 min read

NEWS: Angular 11 is out. Check out my article to learn everything about it.

Image for post
Image for post

In this article, I’ll go over (almost) everything noteworthy in this brand new release. I’ll also highlight what’s changed around Angular.

If you want an helicopter view of what’s included, then check out the official Angular blog. Here, I’ll try to dig deeper into the release notes.

Angular 10 is already here, just four months after version 9. Of course during this short time period, there’s not that much that has changed. Still, there are quite a few noteworthy features, in addition to the large number of bug fixes brought by this release.

As a reminder, the Angular team tries to release two major versions per year, so Angular 11 should arrive this fall.

Support for TypeScript 3.9.x

I’ve already published an article about the new features of TS 3.9, so if you didn’t read it, go ahead and upgrade asap, it’s really worth it! I have also written another one about what’s coming with TypeScript 4.0.

Note that Angular 10 has dropped support for TS 3.6, 3.7 and 3.8! I hope that it won’t hold you back.

Thanks to its support for TS 3.9.x and other improvements in the compiler CLI, type-checking is faster than ever in Angular 10, which should be positive for most projects out there; especially larger ones.

Aside from that, Angular 10 also upgraded to TSLib 2.0. For those who don’t know, TSLib is an official library providing TypeScript helper functions that can be used at runtime. TSLib works in combination with the importHelpers flag of “tsconfig.json”; when enabled, it allows the compiler to generate more condensed/readable code. Anyways, nothing to worry about; TSLib hasn’t changed much..

Optional stricter settings

Angular 10 brings the possibility to create stricter projects right at creation time, which is great and should certainly be used for all new projects. To create a project with stricter defaults, use:

ng new --strict

This will allow you to detect issues much sooner (finding out about bugs at build time is better than at runtime, right?).

This new option enables TypeScript strict mode (which you should all enable on your projects!).

Next to that, it also enables strict Angular template type checking, which I wrote about last week.

It also lowers the budgets in “angular.json” quite drastically:

This is good as it will encourage new users to pay attention to the bundle size of their applications (about that, I’m planning an article on how to analyze the bundle size of your apps).

It also enforces a stricter TSLint configuration which bans “any” (“no-any” is set to true), and also enables quite a few interesting rules provided by codelyzer. Note that even though strict, you can still go much further with TSLint. For instance, here’s the config of one of my projects, which you can use as starting point.

I think that this new “strict” option is awesome, but am a bit sad that it isn’t the default rather than an optional flag. I feel like stricter means safer, so why make safer optional? I imagine that the rationale is that by being more lenient by default, Angular feels less scary at first?

Anyways, if you do create a new project, please enable this and go even further; you’ll thank me later.

New TypeScript configuration layout

So why all these configuration files? To better support the way IDEs and build tools look up the types and compiler configuration.

With the new setup, “tsconfig.json” simply contains TypeScript project references based on the so-called “solution style” (Visual Studio is back? :p) brought by TypeScript 3.9, which is great to improve compilation times and enforce a stricter separation between parts of the project:

In this case, the separation is there to cleanly isolate application code (taken care of by “tsconfig.app.json”) from tests (handled by “tsconfig.spec.json”).

If you look at the “tsconfig.base.json” file, then you’ll find the bulk of the TypeScript configuration:

Note that this one was generated using the strict option discussed in the previous section.

As you can see above, this file only configures TypeScript compiler and Angular compiler options; it doesn’t list/include/exclude files to compile.

The answer is indeed in the “tsconfig.app.json” file, which lists the “main.ts” and “polyfills.ts”:

If you have an existing project without this layout, then you should probably review your TypeScript configuration in order to stay aligned and benefit

Ok ok, enough about the TypeScript config.

NGCC

Note that in this release, NGCC is more resilient. Previously, it couldn’t always recover when one of its worker processes crashed. So if you sometimes saw issues with NGCC hanging, this should now be fixed.

There were also quite a lot of improvements made to NGCC, including performance-related ones, which is clearly my biggest pain point around NGCC ;-)

New default browser configuration

As explained in the official blog post, the side effect of the new configuration is that ES5 builds are disabled by default for new projects.

Of course, at this point it doesn’t make much sense anymore to generate ES5 code. Modern Web browsers support at the very least ES2015. If you still use Internet Explorer, then it’s clearly time to let go of the past!

To get the exact list of supported Web browsers, just execute the following command in your project:

npx browserslist

The output is generated based on the contents of the “.browserslistrc” file at the root; by default it now looks as follows:

You can find out more about this here.

Bazel

Bazel will never be the default build tool in Angular CLI after all…

I won’t go over the reasons here, but make sure to take a look at the article of Alex as it is very interesting (as usual).

@angular-devkit/build-angular 0.1000.0)

The newest version of this package brought us some cool new features.

The coolest one (if you’re using SASS that is) is the fact that build-angular will now rebase relative paths to assets.

As stated in the commit, previously, paths like url(./foo.png) referenced in stylesheets and imported in other stylesheets would retain the exact URL. This was problematic since it broke as soon as the importing stylesheet was not in the same folder. Now, all resources using relative paths will be found. Cool!

Another hidden gem in that release is the fact that build-angular now dedupes duplicate modules that Webpack can’t handle. This is done through a custom Webpack resolve plugin.

And more…

Incremental template type checking

CanLoad

Note that this doesn’t affect preloading.

I18N/L10N

I can’t say much more about this since I’m only using ngx-translate & transloco these days… Check out this issue for more details.

Service Workers

Again, I can’t say much more as I’m not using NGSW but Workbox.

Angular Material

I won’t go over these in this article as it is quite long already, so go check out the release notes if you’re interested!

Bug fixes galore

If you were the victim of known bugs in previous versions of Angular, then it’s probably time to take a look around and see if those aren’t fixed by Angular 10.

A funny one (to me that is) is the fact that enabling strict template type checking caused issues with routerLinks because their underlying type didn’t include null/undefined. Another one that was fixed is the KeyValuePipe, which didn’t play along well with the async pipe.

While we’re on templates, note that the language service of Angular now supports more array-like objects such as ReadonlyArray and readonly property arrays for *ngFor loops. How cool is that? :)

Deprecations and removals

IE 9, 10 and Internet Explorer Mobile are not supported anymore. But again, if you ask me, you should just ditch IE altogether at this point. It’s nonsense to keep zombies around.

There are quite a few deprecated elements such as ReflectiveInjector, CollectionChangeRecord, DefaultIterableDiffer, ReflectiveKey, RenderComponentType, ViewEncapsulation.Native, ngModelwith Reactive Forms, preserveQueryParams, @angular/upgrade, defineInjectable, entryComponents, TestBed.get, etc.

You can check out the full list here.

Classes using Angular features without an Angular decorator are not supported anymore

With Angular 10, it is now mandatory to add an Angular decorator if a class uses Angular features. This change impacts all cases where you have components extending from a base class and one of the two (i.e., parent or child) is missing an Angular decorator.

Why is this change mandatory? Simply put, because Ivy needs it!

When there’s no Angular decorator on a class, the Angular compiler doesn’t add extra code for dependency injection.

As stated in the official doc, when the decorator is missing from the parent class, the subclass will inherit a constructor from a class for which the compiler did not generate special constructor info (because it was not decorated as a directive). When Angular then tries to create the subclass, it doesn’t have the correct info to create it.

In View Engine, the compiler has global knowledge, so it can look up the missing data. However, the Ivy compiler only processes each directive in isolation. This means that compilation can be faster, but the compiler can’t automatically infer the same information as before. Adding the @Directive() explicitly provides this information.

When the child class is missing the decorator, the child class inherits from the parent class yet has no decorators of its own. Without a decorator, the compiler has no way of knowing that the class is a @Directive or @Component, so it doesn't generate the proper instructions for the directive.

The nice thing about this change is that it brings more consistency into the Angular world (and consistency is good :p). Now things are simple: if you use Angular features, then you must add a decorator.

To give you an example, the following code won’t compile with Ivy:

To fix the issue, you need to add a decorator to the Base class.

You can learn more about this change here.

Mandatory generic type for ModuleWithProviders

It’s a good thing for type safety anyways, so hopefully you already had the parameter defined:

If you stumble upon the following error because of a library that you’re using:

error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).

Then you should contact the library author to get it fixed as ngcc can’t help there. A workaround there is to set skipLibChecks to false

Other breaking changes

  • Resolvers behave differently; those that return EMPTY will now cancel navigation. If you want to allow navigation to continue, then you need to make sure that your resolvers emit a value; for instance using defaultIfEmpty(...), of(...) and the like
  • Service worker implementations that rely on resources with Vary headers will not work like they did previously. Vary headers will be ignored. The proposed “solution” is to avoid caching such resources as they tend to cause unpredictable behavior depending on the user agents. Because of this, resources may be retrieved even when their headers are different. Note that cache match options may now be configured in NGSW’s config file
  • Property bindings such as [foo]=(bar$ | async).fubar will not trigger change detection if the fubar value is the same as the previous one. The workaround if you rely on the previous behavior is to manually subscribe / force change detection or adapt the binding in order to make sure that the reference does change
  • The following format codes of formatDate() and DatePipe have changed; apparently the previous behavior was incorrect for day periods that crossed midnight
  • The function that stands behind the UrlMatcher utility type (function alias) now correctly states that its return type may be null. If you have a custom Router or Recognizer class, then you need to adapt those
  • Additional occurrences of ExpressionChangedAfterItHasBeenChecked can now be raised by Angular for errors that it didn’t detect before
  • Angular now logs at error level when it notices unknown elements / property bindings in your templates. These were previously warnings
  • Reactive forms’s valueChangeshad a bug with FormControls that were bound to inputs of type number (they fired twice since 2016! A first time after typing in the input field and a second time when the input field lost focus). Now, number inputs don’t listen to the change event anymore, but to the input event. Don’t forget to adapt your tests accordingly. Note that this breaks IE9 compatibility, but that’s not a problem for anyone.. right? ;-)
  • The minLength and maxLength validators now make sure that the associated form controls values have a numeric length property. If that’s not the case, then these won’t be validated. Previously, falsy values without a length property (e.g., false or 0) were triggering validation errors. If you rely on that behavior, then you should add other validators like min or requiredTrue

Upgrading

If you do the upgrade manually and still use Protractor (just in case), then don’t forget to update protractor to 7.0.0+ as previous versions had a vulnerability.

Conclusion

All in all, even if this isn’t an earth shattering release, it’s clearly a rock solid one with tons of bug fixes and a few gems.

As usual, we can only be thankful for all the efforts made by the Angular team and the community that surrounds it!

That’s it for today.

Liked this article?

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Sébastien Dubois.

Written by

Author, CTO. Subscribe to my newsletter: https://mailchi.mp/fb661753d54a/developassion-newsletter. Follow me on Twitter https://twitter.com/dsebastien

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Sébastien Dubois.

Written by

Author, CTO. Subscribe to my newsletter: https://mailchi.mp/fb661753d54a/developassion-newsletter. Follow me on Twitter https://twitter.com/dsebastien

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store