Master Angular 16: A study guide that helps you learn the new version of Angular
Gergely Szerovay
Full stack developer, data scientist. Editor of AIBoosted.dev and AngularAddicts.com
The new version of Angular is going to be released this week.
??Changes and new features
In this article, I list out the most important changes and new features, also share resources that will teach you how these new Angular features work:
Next to these features, Angular 16 has a new Vite + Esbuild based dev server.
Naturally, reading articles about the changes is a good idea, additionally,
also provide great insights, you should check these out, too.
??Signals
Official docs:?Angular Signals
GitHub discussion:?Angular Reactivity with Signals
RFC:?RFC: Angular Signals
A new primitive type called “Signal” has been introduced in Angular. It’s designed to store a value similar to a regular variable. When the Signal’s value changes, it notifies the interested consumers. Signals store both primitive data types and objects.
A “Computed Signal” derives its value from other Signals. To create a Computed Signal, we need to use the?computed?function and specify the derivation function.
In case we use the?OnPush?change detection in a component and it has a Signal in its template, Angular tracks the Signal as a dependency for the component and marks the component for check if the Signal’s value changes. In Angular 17 this will change, it will be possible to use Signal based per-component change detection without?zone.js.
Pawel Kozlowski ’s talk at the NgBe is a great introduction to Signals, what features are in Angular 16 and what’s expected in Angular 17:
Deborah Kurata ?wrote a detailed tutorial on Signals, she explained why we need Signals, what they are, and how to create, read and update them. She also demonstrates the concept of computed Signals and effects.
Manfred Steyer compares the current Zone.js based change detection with the new Signal based approach.
Stefan Haas explains how Signal and RxJS interoperability works.
Tomas Trajan explains how Signals work using the push & pull concepts.
??DestroyRef
Official docs:?DestroyRef
DestroyRef?lets you set callbacks to run for any cleanup or destruction behavior.
Example:
@Component({
? selector: 'component-1',
? standalone: true,
? template: ``,
})
class Component1 {
? constructor(private destroyRef: DestroyRef) {
? ? destroyRef.onDestroy(() => {
? ? ? // run this cleanup code, when the component is destoryed
? ? });
? }
}
In his article,? Netanel Basal shows an example for how to create a reusable logic that performs a cleanup task when a scope is destroyed:
??takeUntilDestroyed
takeUntilDestroyed?completes an observable in case the calling component (or directive, service or pipe) is destroyed.
In the following example, when the component is created, it starts to show ‘Tick’ messages on the browser’s console, using a subscription to a 2 second interval(). When the component is destroyed, it unsubscribes from the interval():
@Component({
? selector: 'component-1',
? standalone: true,
? template: ``,
})
class Component1 {
? constructor() {
? ? interval(2000).pipe(takeUntilDestroyed()).subscribe(
() => console.log('Tick')
);
? }
}
It’s also possible to pass a specific?DestroyRef?as a parameter to?takeUntilDestroyed, so we can create reusable functions with subscriptions that unsubscribe when the context is destroyed:
function reusableTicks(destroyRef: DestroyRef): void {
? interval(2000).pipe(takeUntilDestroyed(destroyRef)).subscribe(
() => console.log('Tick')
);
}
@Component({
? selector: 'component-1',
? standalone: true,
? template: ``,
})
class Component1 {
? constructor(private destroyRef: DestroyRef) {
? ? reusableTicks(destroyRef);
? }
}
??Required inputs
Official docs:?Input
We can mark component- or directive inputs as required. The following example fails in compile time, as in the Component2’s template we didn’t provide the required text input:
@Component({
? selector: 'component-1',
? standalone: true,
? template: ``,
})
class Component1 {
? // ? this is a required input
? @Input({ required: true }) text: string;
}
@Component({
? selector: 'component-2',
? standalone: true,
? template: `
? ? <component-1></component-1>
? `,
? imports: [Component1]
})
class Component2 {
? constructor(private destroyRef: DestroyRef) {
? ? destroyRef.onDestroy(() => {
? ? ? // run this cleanup code, when the component is destoryed
? ? });
? }
}
??Bind Router information to component inputs
Official docs:?Router / Getting route information,?withComponentInputBinding
This new feature simplifies the process of getting route information.? Enea Jahollari explains how this new feature works by examples.
??Node.js v14 support has been removed
Changelog entry:?Node.js v14 support has been removed
领英推荐
Node.js v14 is planned to be End-of-Life on 2023–04–30. Angular will stop supporting Node.js v14 in Angular v16. Angular v16 will continue to officially support Node.js versions v16 and v18.
??TypeScript 5
From Angular’s perspective, the two most important new features in Typescript 5 are:
Decorators
TypeScript 5 supports a new version of the?ECMAScript decorator proposal, referred to as ‘Standard decorators’.
Kevin Kreuzer explains us, how these new decorators work.
Multiple configuration file support in?tsconfig.json's extends
For example, both?strict?and?noImplicitReturns?are enabled in the final?tsconfig.json?in the following example:
// tsconfig-a.json
{
? ? "compilerOptions": {
? ? ? ? "strict": true
? ? }
}
// tsconfig2-b.json
{
? ? "compilerOptions": {
? ? ? ? "noImplicitReturns": true
? ? }
}
// tsconfig.json
{
? ? "extends": ["./tsconfig-a.json", "./tsconfig-b.json"],
? ? "files": [
? ? ? "src/main.ts",
? ? ? "src/polyfills.ts"
? ? ]
}
You can find more details of the new Typescript features in their official announcement.
??Angular Compatibility Compiler (ngcc) has been removed
Changelog entry:?Angular Compatibility Compiler (ngcc) has been removed
Angular 9 transitioned its rendering architecture from the “ View Engine” to “Ivy”. However, to support libraries that were still dependent on the “View Engine”, Angular Compatibility Compiler (ngcc) was created. In Angular 16,?ngcc?and all other codes related to the old “View Engine” have been removed, so “View Engine” libraries can no longer be used in v16+.
To learn more about “Ivy”, read? Maria Korneeva 's article about how “View Engine” and “Ivy” works and what is new in “Ivy”.
??NgZone is configurable in bootstrapApplication
Official docs:?provideZoneChangeDetection
There are two zone configuration related changes in Angular 16:
// custom zone implementation
class CustomZone extends NoopNgZone { }
bootstrapApplication(
StandaloneCmp, {
providers: [
// provide a custom zone implementation
{ provide: NgZone, useValue: new CustomZone() }
]
}
);
// enable eventCoalescing and runCoalescing
bootstrapApplication(
StandaloneCmp, {
providers: [
provideZoneChangeDetection({
eventCoalescing: true,
runCoalescing: true
})
]
});
??Server Side Rendering improvements
Non-destructive hydration
With non-destructive hydration, Angular has the capability of reusing pre-existing DOM structures on the client-side that were initially rendered by the server. This prevents the flicker that occurs when the page is rendered and ready for interaction by users.
The results of the request done on the server side can be reused on the client side
To avoid the need of refetching the same data on the client side, requests made on the server side will be cached and accessible on the client side.
Jessica Janiuk summarized the current state and future of the server side rendering in her blog post.
??Strict type checking for ngTemplateOutlet
Previously, when we passed a context to?ngTemplateOutlet, it was passed as an Object, so in the following example there was no compilation error:
interface Context1 {
prop: number;
}
@component({
standalone: true,
imports: [NgTemplateOutlet],
selector: 'person',
template: `
<ng-container
*ngTemplateOutlet="
myTemplateRef;
context: { prop: 1, missingProp: 2 }
"></ng-container>
`,
})
export class Component1 {
templateRef!: TemplateRef<Context1>;
}
Now in Angular 16 the code in the previous example fails with a compile time error, as?missingProp?is not defined in?Context1?. We can fix this by adding the?missingProp?property to Context1 or add?$any(…)?inside the template to preserve the previous behavior.
??provideServiceWorker function to register service workers in standalone applications
Official docs:?Service workers?/?provideServiceWorker
Previously to register a service worker in a standalone app, we had to use?importProvidersFrom(ServiceWorkerModule.register(…)).
provideServiceWorker?is a new way to register service workers in standalone apps, usage example:
bootstrapApplication(AppComponent, {
providers: [
provideServiceWorker('my-service--worker.js')
],
});
Experimental Jest support
The Angular Team added initial experimental support for Jest in Angular 16. In Angular 17, they’ll replace the deprecated Karma test runner with the?Web Test Runner.
? Have you seen any other resources I should add to this?Angular 16 Study Guide? Please send it to me so that I can feature it in the article!
?? ??About the author
My name is?Gergely Szerovay, I work as a frontend development chapter lead. Teaching (and learning) Angular is one of my passions. I consume content related to Angular on a daily basis — articles, podcasts, conference talks, you name it.
I created the Angular Addict Newsletter so that I can send you the best resources I come across each month. Whether you are a seasoned Angular Addict or a beginner, I got you covered.
Next to the newsletter, I also have a publication called — you guessed it —?Angular Addicts. It is a collection of the resources I find most informative and interesting. Let me know if you would like to be included as a writer.
Let’s learn Angular together!?Subscribe here???
Senior Software Engineer at Microsoft
1 年Thanks for the mention!