The 9.0.0 release of Angular is here! This is a major release that spans the entire platform, including the framework, Angular Material, and the CLI. This release switches applications to the Ivy compiler and runtime by default, and introduces improved ways of testing components.
This is one of the biggest updates to Angular we’ve made in the past 3 years, and we’re excited for all of the ways it empowers developers to build better applications and contribute to the Angular ecosystem.
Visit update.angular.io for detailed information and guidance. To have the best update experience, we recommend you first update to the final release of Angular 8.
First, update to the latest version of 8
ng update @angular/[email protected] @angular/[email protected]
Then, update to 9
ng update @angular/cli @angular/core
To review the key changes with this update, including deprecated APIs, see Updating to Angular version 9 in the Angular documentation.
Version 9 moves all applications to use the Ivy compiler and runtime by default. In addition to hundreds of bug fixes, the Ivy compiler and runtime offers numerous advantages:
Here’s a breakdown of some of the more notable improvements.
The Ivy compiler has been designed to remove parts of Angular that aren’t being used via tree-shaking and to generate less code for each Angular component.
With these improvements, small apps and large apps can see the most dramatic size savings.
Small apps could see around a 30% decrease in bundle size, large apps will see a 25–40% decrease, and medium apps decrease minimally.
We have also revamped the implementation of [TestBed](https://angular.io/api/core/testing/TestBed)
in Ivy to make it more efficient.
Previously, TestBed
would recompile all components between the running of each test, regardless of whether there were any changes made to components (for example, through overrides).
In Ivy, TestBed
doesn’t recompile components between tests unless a component has been manually overridden, which allows it to avoid recompilation between the grand majority of tests.
With this change, the framework’s core acceptance tests are about 40% faster. We would expect users to see their own application test speeds to be around 40–50% faster.
Ivy provides you with more tools to debug your applications. When running an application in Dev Mode with the Ivy runtime, we now offer the new [ng](https://v9.angular.io/api/core/global)
object for debugging.
applyChanges
Ivy also improves the stack trace for debugging issues such as the ExpressionChangedAfterItHasBeenCheckedError
. Previously the stack trace could be unhelpful:
With Ivy, you see a more useful stack trace that allows you to jump directly to the template instruction with the expression that has changed.
For example, if you click on AppComponent_Template
in the stack trace above, you can see the specific line in the generated code where the error is being thrown:
If you’re so inclined, you can also step into any of these framework instructions to walk through how the framework creates or updates your components.
The Ivy compiler and runtime provides improvements for handling styles. Previously, if an application contained competing definitions for a style, those styles would destructively replace each other. With Ivy, the styles are merged in a predictable way.
Consider the following template and component snippets:
snippet.html
<my-component style="color:red;" [style.color]="myColor" [style]="{color: myOtherColor}" myDirective></div>
snippet.ts
@Component({
host: {
style: "color:blue"
},...
})
...
@Directive({
host: {
style: "color:black",
"[style.color]": "property"
},...
})
...
Previously, whichever binding was evaluated last would win, and this could depend on the timing of changes to these expressions. If myColor
and myOtherColor
both were undefined, the static ‘red’ style would be ignored.
With version 9, you can manage your styles through a clear, consistent order of precedence that isn’t dependent on timing. The most specific styles always have the highest precedence. For example, a binding to [style.color]
overrides a conflicting binding to [style]
.
However, for backwards compatibility reasons, we have left [ngStyle]
and [ngClass]
bindings behavior the same as before. When their binding values are updated, the new values will override any competing bindings.
You can read more about styling precedence rules in the Template Syntax guide in the documentation.
As a side effect of the styling refactoring, you can now also bind to CSS custom properties (also known as CSS variables).
custom-properties.html
<div [style.--main-border-color]=" '#CCC' ">
<p style="border: 1px solid var(--main-border-color)">hi</p>
</div>
The Angular compiler can check more of the types of your application, and it can apply more strict rules. These features will help you and your team catch bugs earlier in the development process.
We support two main flags for additional type checks in addition to the default:
fullTemplateTypeCheck
— Activating this flag tells the compiler to check everything within your template (ngIf
, ngFor
, ng-template
, etc)strictTemplates
— Activating this flag will apply the strictest Type System rules for type checking.To learn more about template type checking options, see the Template type checking guide in the documentation.
The new Ivy compiler is not only faster and offers stronger type safety, it also makes all of the error messages easier to read.
In version 8 or View Engine, a typical compiler error would look like the following:
In version 9 with Ivy, the same error looks like:
Thanks to Ivy’s new architecture, we’ve made significant improvements to the compiler’s performance.
We measure our compiler’s performance in terms of the overhead on top of a plain TypeScript compilation of an application. For our documentation app (angular.io), this overhead decreased from 0.8x to 0.5x with Ivy, an improvement of nearly 40%.
These improvements mean that AOT builds can be noticeably faster. Thanks to this speedup, for the first time ever we’re using AOT even for dev-mode builds. This means that ng serve
now benefits from the same compile-time checking as production builds, significantly improving the developer experience for Angular.
Thanks to the changes in the compiler and runtime, we also no longer require [entryComponents](https://v9.angular.io/guide/deprecations#entryComponents)
. These components will be discovered and compiled automatically by their usage.
Internationalization has been a core feature of Angular, where you could build your application once per locale and receive highly optimized and localized applications. In 9.0, we’re making this faster by moving the build-time i18n substitutions later in the build process. This change allowed us to make it up to 10 times faster.
Read more about the new i18n: @angular/localize
and the new angular.json
configuration.
The team has also been hard at work continuing to improve the full experience of using Angular.
We’ve made some changes to how ng update
works to make it more reliable and informative.
ng update
now does more to tell you what is going on under the hood. For each migration, you’ll see information about the migration.ng update
runs all of the migrations and leaves the aggregate changes on disk for you to inspect. The version 9 update also introduces the new **--create-commits**
flag. When you run ng update --create-commits
, the tool commits the state of your codebase after each migration, so you can step through and understand or debug the changes we are making to your code.When you create an @Injectable
service in Angular, you must choose where it should be added to the injector. In addition to the previous root
and module options, you have two additional options.
platform
— Specifying providedIn: 'platform'
makes the service available in a special singleton platform injector that is shared by all applications on the page.any
— Provides a unique instance in every module (including lazy modules) that injects the token.Learn more about providedIn in our API documentation.
Testing components has historically relied on using implementation details such as CSS selectors to find components and to trigger events. This meant that whenever a component library changed its implementation, all of the tests relying on those components would need to be updated.
In version 9, we are introducing component harnesses, which offer an alternative way to test components. By abstracting away the implementation details, you can make sure your unit tests are correctly scoped and less brittle.
Most of Angular Material’s components can now be tested via harnesses, and we are making harnesses available to any component author as part of the Component Dev Kit (CDK).
Here’s an example test before harnesses:
test-before.ts
it("should switch to bug report template", async () => {
expect(fixture.debugElement.query("bug-report-form")).toBeNull();
const selectTrigger = fixture.debugElement.query(
By.css(".mat-select-trigger")
);
selectTrigger.triggerEventHandler("click", {});
fixture.detectChanges();
await fixture.whenStable();
const options = document.querySelectorAll(".mat-select-panel mat-option");
options[1].click(); // Click the second option, "Bug".
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.debugElement.query("bug-report-form")).not.toBeNull();
});
And the same test with harnesses:
test-after.ts
it("should switch to bug report template", async () => {
expect(fixture.debugElement.query("bug-report-form")).toBeNull();
const select = await loader.getHarness(MatSelect);
await select.clickOptions({ text: "Bug" });
expect(fixture.debugElement.query("bug-report-form")).not.toBeNull();
});
Learn more about Material’s component harnesses or building your own with the CDK.
You can now include capabilities from YouTube and Google Maps in your applications.
Significant improvements have been made to the Angular language service extension on the Visual Studio Marketplace. Along with major architectural overhaul to address performance and stability issues, many long-standing bugs have also been fixed. Besides that, some new features include:
templateUrl
and styleUrls
Angular has been updated to work with TypeScript 3.6 and 3.7, including the extremely popular optional chaining feature in TypeScript 3.7. To stay in sync with the ecosystem, we’ve also updated our version of other ecosystem dependencies such as Zone.JS and RxJS.
This release is the culmination of over 2 years of work. We’re really excited about the future and possibilities that this work opens up. This wouldn’t be possible without the work of hundreds of people in the community.
☞ Angular Tutorial - Learn Angular from Scratch
☞ Angular and Nodejs Integration Tutorial
☞ JavaScript Programming Tutorial Full Course for Beginners
☞ Learn JavaScript - Become a Zero to Hero