Angular Signals: Optimize Your App Performance
Angular is getting a new exciting feature called signals.
Before discussing the topic, we want to know how angular change detection works.
Angular's primary key feature is its declarative, model-driven approach to building user interfaces. This means that the application's state (i.e., its current data and values) is the main source of truth, and any changes made to the state are automatically reflected in the user interface.
To connect the state to the user interface, developers use an HTML-like template to map the model to the UI elements.
As the application state changes over time, the framework keeps track of these modifications and updates the UI accordingly to keep it current. This allows developers to build complex and responsive web applications with ease.
Angular uses a tool called zone.js to keep track of events in the browser and update the web page accordingly.
When the webpage changes, Angular refreshes the entire webpage to make sure everything is up-to-date. This can be slow and complex for big web pages, so developers can use a different approach called OnPush to speed things up.
However, this approach has some limitations.
One limitation of the OnPush change detection strategy in Angular is that it prevents descendant components from updating correctly if they depend on a global state outside of their ancestor components.
This is because OnPush components only check for changes when certain specific conditions are met, such as when an input changes, an event originates in a component in question, or a component is explicitly marked for the check.
If a descendant component depends on a global state outside of its ancestor component, it may not get updated correctly because the OnPush strategy does not detect changes in the global state.
What is Signal?
A signal is a value that has a changing semantic, meaning that it represents data that can change over time.
In Angular, signals are represented by a function that takes no arguments and returns the current signal value. It accurately identifies where the change has occurred and updates it accordingly.
Signals are read-only, which means that we can observe change notifications, but we cannot modify their values directly.
In HTML, we display the signal value using the variable name with parentheses.
However, there is also a writable signal that can be changed using three methods: "set", "update", and "mutate".
These methods allow the application to modify the information stored in the signal as needed.
The set method is used to change the signal value for primitive values.
In the example above, the initial state of buzz is a string, which is a primitive data type that can be changed using the set method.
The update method updates the value of the signal based on its current value and notifies any dependents.
When the button is clicked, the update method provides the current value of the buzz variable. If we add one to it and continuously click the add button, it acts as a counter.
The mutate method is used for modifying non-primitive data types such as arrays and objects.
Computed signals are values that are created based on other values they depend on. If the values they depend on change, the computed signal will also change to reflect the new values.
Computed signals can be built on top of other computed signals, allowing for more complex layers.
An effect is a function that reads signals present inside it and automatically reruns whenever any of those signal values changes.
If multiple signals that an effect depends on change simultaneously, the effect will only be scheduled for execution once, resulting in a minimal number of executions.
Angular signals bring in major changes in code and performance.
Rather than triggering the change detection mechanism using zone.js, Angular can now precisely identify where a change has occurred.
In the upcoming Angular release, there is an RFC where signals can be used for specific components like standalone: true, and it is expected signals: true. These will be called signal-based components.
Eight lifecycle methods in zone-based components allow developers to integrate with various stages of Angular's change detection process. However, as these methods are closely linked to Angular's existing change detection model, they do not apply to signal-based components.
Signal-based components will have an entirely different set of lifecycle hooks such as afterInit, afterRender, afterNextRender, afterRenderEffect, and beforeDestroy.
These lifecycle hooks are currently present in the RFC, and we will discuss them in detail in our next blog post.
Need to augment your development team with experienced Angular developers?
Let's work together to build robust and efficient web applications using Angular!