跳转到主要内容
SEO Title

At the time of writing this article, angular just published its first release candidate version of v16. There are a lot of features/changes coming with this version. Much more than we have seen in any previous major release (of course, not considering angular to angular 2). Angular is seeing a kind of renaissance, and v16 is just the beginning. These are some of the prominent changes coming in this release.

ngcc is gone

Angular moved from its old view engine to ivy in v9. To support libraries which were still based on the old view engine, Angular Compatibility Compiler (ngcc) was introduced. In v16 ngcc has been removed along other all other view enginer related codes. As a result, angular bundle side should reduce as well as Angular View Engine libraries can no longer be used in v16+. Such libraries were not officially supported, but this is a hard break in compatibility.

With this, the transition of angular from view engine to ivy is complete.

Binding router information to component inputs

With this feature, the following router data will be available in the component directly as input. So, instead of using ActivatedRoute to get these values, we can use inputs. These can potentially remove a lot of boilerplate code from our application

  • Router data
  • Resolved router data
  • params
  • queryParams
// Current approach, which would still work
@Component({
  ...
})
class SomeComponent {
  route = inject(ActivatedRoute);
  data = this.route.snapshot.data['dataKey'];
  params = this.route.snapshot.params['paramKey']
}

//New approach
@Component({
  ...
})
class SomeComponent {
  @Input() dataKey: string;
  @Input() paramKey: string;
  
  //or
  @Input() set dataKey(value: string){
    //react to the value
  };
  @Input() set paramKey(value: string){
    //react to the vaue
  };
}

https://github.com/angular/angular/pull/49633

takeUntilDestroyed and DestroyRef

Angular has been slowly moving toward enabling a more functional approach of writing code. One feature in this direction is the introduction of DestoryRef and takeUntilDestoryed rxjs operator. These are replacement for ngOnDestroy lifecycle hook. Because ngOnDestroy is tied to classes, we can’t use it in functions, if ever we want to.

@Component({})
class SomeComponent {
  destroyRef = inject(DestroyRef);
  store = inject(Store);
  user
  constructor() {
    const sub = this.store.select(getUser()).subscribe((user) => {
      this.user = user    
    });
    destoryRef.onDestroy(() => {
      sub.unsubscribe()
    })
    

    //OR

    const sub = this.store.select(getUser()).pipe(takeUntilDestroyed())
      .subscribe((user) => {
      this.user = user    
    });
  }
}
  

takeUntilDestroyed operator can only be used in constructor context. To use it outside constructor we need to pass destroyRef as an argument.

This feature is internally used for cleaning up signal effects, hence no manual cleanup is required unlike subscriptions in rxjs. We’ll see more about them later

Required input

feat(compiler): add support for compile-time required inputs by crisbeto · Pull Request #49304 ·…

Adds support for marking a directive input as required. During template type checking, the compiler will verify that…

github.com

In react and other frameworks, we can pass props to components. There we can mark some of these props as required, and if they are not passed, typescript would throw error. Developers sourly missed this feature in angular.

There are a lot of use cases where a component requires input to serve its purpose. Without this input being passed from the parent, component may not work as intended. Currently, there are some hacky ways to enforce that inputs are getting passed to the component. But this feature brings this much requested feature in angular.

@Component({})
class SomeComponent {
  @Input({required: true}) someRequiredInput;
}

When input is marked as required, and it’s not passed in the template from the parent, compilation error will be thrown.

Note that this does not work for routed component and dynamic component. It only works for component added in the template directly

Esbuild dev server

Experimental support for ng build using esbuild is already available. In v16, support for ng serve using esbuild is also added. It is still experimental and some more performance related improvements and optimisations are to be made, but it already enables a much faster startup time (at least 2 times) than webpack implementation.

To enable this we need to change "@angular-devkit/build-angular:browser" to "@angular-devkit/build-angular:browser-esbuild"

Signals

If you are an angular developer and you have not been living under a rock, you would know about this one. Signals are the new reactive primitive provided by angular, which will help framework track changes to its model. This article can provide more detail of signal, its api and how it compares to rxjs. The following are benefits that signals promises to bring

  • Make angular simple: This reactive primitive can replace rxjs in most cases and reduce the complexity of the application.
  • Fine grained reactivity: Angular can become much more performant with signals. Because signals provide exact models which has changed, angular can do fine grained updated to the template instead of dirty checking the whole application.
  • Less concepts to learns: With signal component (coming in v17), developers needs to worry less about any performance related issue that can come due to nonoptimal code they write. Concepts like changeDetectionStrategy , onChanges lifecycle hook, even pipe to some extend will become unnecessary. It would get harder for developers to make mistakes which might hamper the performance of their application.
  • Zone-less application: Zone currently helps angular to know if something has changed and trigger change detection for the the whole application. zone monkey patches browser api to give signals (pun intended) to angular that something has changes. But it does not tell the framework what has changed. Also its adds to the bundle size and initial startup time of the application. Signals would make it possible for framework to know which exact model has changed. This enables us to have zone-less application

Angular also provides interoperability with Rxjs, which the current reactive library we use in angular. Using toSignalobservable can be easily converted to signal and using toObservable signal can be converted back to observable. This would allow us to incrementally start migrating things to signal from Rxjs, if we want to take advantage of signals.

SSR with hydration

This was a huge feature request from angular developers for a very long time. Without this, lot of developers who wanted to build end-user-facing application where initial startup time and SEO is very important, withheld from using angular.

Angular universal provided some level Server Side Rendering support, which only supported destructive hydration of the application. This leads to janky user experience for the users. With v16, angular would now enable real (non-destructive) hydration of server rendered application. This along with http request caching, the first render time should come down quite a lot and web vitals will improve for angular applications.

Conclusion

v16.0.0 should be launching sometime in May (May 4th is my guess). If you are an angular developer, or considering angular for your next project, knowing these new features are essential. Some of these are long standing features request from the community. Some features (signal, and SSR) bring Angular to par with other modern frameworks. With these features and more coming in v17, modern angular would start looking a lot different from what it is right now. Given the amount the changes angular is bringing in, if we don’t keep ourselves up to date, we won't be able to take advantage of these new features, and our codebase may start looking like a legacy code very soon.