Förderjahr 2023 / Projekt Call #18 / ProjektID: 6798 / Projekt: RxAngular
After the very informative and inspiring netidee Community Camp, our team put their heads together and reiterated the current state of the project and the desired milestones we’d like to achieve within the year of 2024. Everyone is full of energy and enthusiasm to provide the best possible improvements and new features for the RxAngular library, especially in regards to the recently kicked off “Angular Renaissance” and how the RxAngular library can also benefit from it.
What is RxAngular
For everyone who is unfamiliar with what RxAngular is all about, let’s quickly introduce the project and ourselves.
As the name already suggests, the RxAngular project is specifically designed to be integrated with the very well known Angular framework. RxAngular is an open source, community focused project housing a handful of packages. It offers a comprehensive toolkit for handling fully reactive Angular applications with the main focus on runtime performance, template rendering, and Developer eXperience.
The packages of the RxAngular project work together or standalone.
@rx-angular/state
A powerful state management library, providing a fully reactive way to manage state in components and services.
@rx-angular/template
A set of directives and pipes designed for high-performance and non-blocking rendering for large-scale applications.
@rx-angular/cdk
A Component Development Kit for high-performance and ergonomic Angular UI libs and large-scale applications.
@rx-angular/isr
A library that enables Angular Universal applications to generate static pages at runtime and then update them incrementally on demand or on a schedule.
@rx-angular/eslint-plugin
A set of ESLint rules for building reactive, performant, and zone-less Angular applications.
The Team
Of course we also need to introduce the core team standing behind the project. Without this amazing crew of inspiring, smart, kind and knowledgeable people the project wouldn’t be in its current state.
Edouard Bozon * Enea Jahollari * Julian Jandl * Kirill Karnaukhov * Lars Gyrup Brink Nielsen * Michael Hladky
Our goals
As the RxAngular project is an already existing and actively maintained project, our goals primarily focus on improving the current state of the project by improving the developer experience and introducing new, mostly performance related, features.
We have identified three key areas to improve and put them together into milestones we strive to achieve within this year. The following sections cover these goals in a digestible level of detail. For everyone who is interested in more technical details, I recommend reading the official documentation of our project, as it explains many concepts in much detail.
Optimize List Rendering Performance
As of angular version 17 a new control flow was introduced to the framework. With it, a new reconciliation algorithm for processing changes in lists of items.
The RxAngular project currently ships a customized version of the former list iteration directive, rxFor. Our goal is to implement a forked version of the new reconciliation algorithm and apply it to our customized directive.
The benefits of the new algorithm are already battle tested and measured (see the above linked blog post), which made this decision obvious.
Investigate new APIs to improve the runtime performance
The prime feature in terms of performance is the RxAngular concurrent mode in combination with local change detection. The current implementation behind the scenes is an adjusted version of the react scheduler. As the JavaScript ecosystem is constantly in development, new and very interesting APIs caught our attention.
We are going to investigate if the following APIs can be integrated and bring measurable performance benefits for the @rx-angular/template package:
We are also going to identify areas how and where the new angular signal API is beneficial especially for the @rx-angular/template package.
Simplify the usage of RxAngular RenderStrategies
RxAngulars `RenderStrategies` build an abstraction layer around the concepts of scheduling, coalescing & scoping.
Let’s quickly go over these concepts.
Coalescing
Coalescing means multiple things "merge" into one.
If two or more things coalesce, they merge into one thing or system. Natively Angular is using this under the hood already for a long time.
In RxAngular coalescing is used for merging multiple emissions, streams or calls that happen during a given timeframe. As one of the key building blocks for performance, this technique is utilized to improve the change detection cycles of angular applications.
The next example shows the effect of coalescing visualized in flame charts.
no coalescing vs. coalescing on microtask. visualized in flame charts
Scoping
Scoping is an additional concept you can add on top of coalescing in order to achieve coalescing between multiple consumers tied to a scope.
Essentially this means multiple triggers from different consumers result in a single action executed, see the following example where we use debounceTime to coalesce operations and to demonstrate the scoping problem.
Scoping would help us to combine the two scopes into one, reducing the number of computations being done.
Scheduling
JavaScript is single threaded. Internally, it uses an Event Loop to execute all tasks in order. Whenever a task is being executed, nothing else can happen in between. In other words, the browser cannot present any update to the user while a task is being executed.
This also means, long running tasks are a problem for user experience, as users are essentially blocked from interacting with your application.
In order to distribute work on the main thread, the JavaScript language provides a set of scheduling techniques, allowing developers to schedule any arbitrary work to a future point in time.
The following scheduling APIs are available:
- queueMicrotask
- Promise
- MessageQueue
- setInterval
- setTimeout
- postMessage
- requestAnimationFrame
- requestIdleCallback
We can also use this technique to split up long running tasks and execute them after each other, in order to give the browser time to interact and update in between.
Render Strategies
All these concepts are baked into and abstracted by the Render Strategies.
RxAngulars Render Strategies provide explicit, fine-grained control of change detection in Angular. A strategy exposes the work to perform (e.g. cdRef#markForCheck, cdRef#detectChanges) as well as the scheduling mechanism to developers for configuration & customization via the interface RxStrategyCredentials. Internally, RenderStragies make use of coalescing, scoping & scheduling in order to execute change detection in a performant way.
The following example shows the current public API available as of now:
The above strategy defines detectChanges as its work. In order to coalesce and schedule the work, it uses an internal scheduler with the normal priority.
Our goal is to further simplify this interface to make it easier to digest & integrate for fellow developers. This effort requires a very well defined migration path as we most probably have to re-shape the whole public facing API.
Let’s go! Stay Tuned
As already stated in the very beginning of this post, our team is very enthusiastic about this year. We are immediately starting to work on our roadmap and will update y’all about our progress.
There will be upcoming posts explaining our achievements, challenges and failures in very detail, stay tuned!