[Complete] RFC: Angular Signals🚦 · angular/angular · Discussion #49685

Discussion options

RFC: Angular Signals

Authors: @alxhub, @atscott, @dylhunn, @jelbourn, @pkozlowski-opensource
Area: Angular Framework
Posted: April 3, 2023
Status: Open

(this is the main RFC document, which links to the others)

We teased this in February, and now it's time to dig into the details: the Angular team requests your comments on our plan to adopt signals as a reactive primitive for Angular.

Before you dive in

Background context

Before going further, it's helpful if you understand How Angular change detection works today.

What kind of feedback are we looking for?

While we're excited to hear any and all comments on Angular Signals, we have additionally called out specific discussion points throughout the RFC for directed feedback. When you leave a comment, be sure to note the open question(s) to which you're responding.

As always, keep our code of conduct in mind. We know that a proposal of this scope significantly impacts Angular and the way you use it in your projects. We appreciate your commitment and investment in this project and ask to keep comments respectful. Remember, we are all just folks doing our best with limited resources.

How this RFC is organized

Because Angular Signals is a large project, we've split this RFC into several smaller docs. We recommend first reading the overview in this document and then jumping to the more specific docs in order.

Goals

This is a big change to Angular, so it's important to talk about why we're choosing to take this step. As we began our investigation into reactivity, we set out several goals we wanted to achieve that we felt would greatly improve Angular, based strongly on developer feedback over the last few years:

  • Angular has a clear and unified model for how data flows through an application.
  • The framework has built-in support for declarative derived state (a common feature request).
  • Only the parts of the UI that need updating should be synchronized, at or even below the granularity of individual components.
  • Smooth interoperability with reactive libraries such as RxJS.
  • Better guardrails to avoid common pitfalls that lead to poor change detection performance and avoid common pain points such as ExpressionChangedAfterItHasBeenChecked errors.
  • A viable path towards writing fully zoneless applications, eliminating the overhead, pitfalls, and quirks of zone.js.
  • Simplification of many framework concepts, such as queries and lifecycle hooks.

We think the best way to achieve our listed goals is to add fine-grained reactivity to the framework with Signals.

An RFC in four parts

If you're interested in the choice of signals as the reactive foundation of the framework, see the sub-discussion RFC #1: Signals for Angular Reactivity.

If you want to discuss our signal API and implementation itself, see RFC #2: Signal APIs.

If you're interested in exploring how using signals will look in Angular, then start with RFC #3: Signal-based components.

And finally, if you're curious about interoperability with RxJS, see RFC #4: Observable and Signal Interoperability.

Wrapping up

That's it!

This RFC has been a long time in the making. We're excited (and relieved) to finally share the details. Whether you're a long-time Angular developer or just stopping by to check out this new buzz on Angular, we're looking forward to obsessing over your every comment.

We want to make a special thanks to all of the hard work and innovation that have inspired us in the web community. Signals are clearly having a moment in the discourse today. Our ideas build on top of a large body of work– Preact, Vue, and SolidJS in particular have been inspirations for this project.

Frequently asked questions

Is this change going to be backward compatible?

Absolutely! Backward-compatibility is non-negotiable and we do everything to assure that the existing applications and libraries continue working as-is, without any modification. This is a gradual, opt-in change.

Is this another Angular rewrite?

No! This is mostly an additive change with some deeper modifications to the change detection algorithm. We take backwards compatibility seriously, and validate all changes with both our own suite of comprehensive tests and against the tests of thousands of Google applications built with Angular.

Is Angular getting less opinionated?

It's true that recent (and upcoming) changes to Angular have introduced new ways of building Angular applications. Most notably this includes standalone components and now signals. We introduce these new approaches over time to evolve the framework based on community feedback and our own observations of Angular in the wild. Our commitment to maintaining backwards compatibility means that the ecosystem ends up supporting multiple ways of doing things.

The result isn't that Angular is less opinionated, but instead that the opinions change over time. Typically, the most recent features represent the way we think most Angular developers should build their apps. We will always clearly communicate the preferred approach and update documentation / tooling accordingly. At the same time, the old way of building will live on for backwards compatibility (following our support policy).

Why are you working on signals and not feature XYZ?

In any popular framework there are always more features requested than we have bandwidth to work on at any given point in time. We are always focusing on projects that are the most helpful and impactful given the long-term evolution and stability of Angular. Signals are one of those projects.

First of all, improved runtime performance and optional zone.js was on our public roadmap for quite some time. Signals allow us to tackle this item.

More importantly, reactivity is at the very heart of a model-driven UI framework. By rethinking change detection, we open doors to simplification and evolutions that were not possible before. Faster performance, better forms, improved state management, and streamlined authoring format are prominent examples.

By baking-in reactivity into the framework we introduce primitives that the community can build upon.

Having said all this, the work on reactivity does not stop the work on the other important framework improvements. As an example, Angular v16 introduces the improved hydration, required inputs and tons of other improvements. We will continue working on other roadmap items while the reactivity work is in progress!

Appendix: How Angular change detection works today

Angular was built on the idea of a declarative, model-driven UI. Your application state is the source of truth and the framework automatically updates the page based on model changes. You declaratively express the mapping of model to UI via an HTML-like template. To keep the page up-to-date, the framework must track model changes over time.

zone.js

Angular uses zone.js to track various events in a browser (ex. DOM events, network requests and timers). Zone.js tracks these events by monkey-patching (wrapping and patching a callback function at runtime) any API that might lead to an application model change. When such an event occurs, however, Angular does not have any information as to what specific changes have occurred, or even if there were any changes at all.

Upon receiving event notification from zone.js, Angular will read (pull) new model values and update UI based on diffing the previously seen model values.

This approach provides excellent developer experience for small and simple applications:

  • You can use plain JavaScript data structures
  • Your state can live anywhere
  • You can mutate your state any way, any place (no need for setState or similar APIs)

In practice, however, large applications often grow to see zone.js become a source of performance issues and developer-facing complexity. As the web platform continues to grow and evolve, it also represents a rising maintenance cost for the Angular team.

While zone.js provides the mechanism that tells Angular when to run change detection, the next section discusses what this change detection entails.

Global, top-down change detection

Angular's default strategy is to run change detection over the entire component tree to make sure that the DOM reflects the most up-to-date model. Because Angular has no information about which parts of the application state have actually changed, it must check everything. In practice, however, only a fraction of the entire application state changes and only a handful of components need to be re-rendered.

Unidirectional data flow

Angular's change detection was designed to refresh application state once. The change detection process starts from the root of the component tree and walks all components down to the leaf nodes.

A single refresh traversal is sufficient if and only if components don’t modify the state of any of their ancestors after they have been visited. Unfortunately, the framework provides several convenient APIs to mutate state exactly in this way mid-traversal.

The component tree matches the rendered DOM tree, which means that change detection traverses the application in rendering order. However, several common web interaction patterns roll up descendant node states into ancestor nodes (e.g. form validity is computed as a function of descendant control states). This leads to the most "popular" error in Angular - ExpressionChangedAfterItHasBeenCheckedError.

OnPush

Angular developers can optionally configure change detection to only run on a subset of the component tree using the OnPush strategy. Components configured as OnPush and their descendants are checked for changes only under specific conditions:

  • A browser event originated in a component in question
  • One of the component’s @Input()s changed as a result of a template binding
  • A component was explicitly marked for check

While the OnPush strategy can reduce some of the performance cost, this strategy is limited:

  • Because OnPush components prevent their descendants from being checked, descendent components that depend on global state may not correctly update if they depend on global state outside of their ancestor components.
  • Because change detection always starts from the application root, running change detection on an OnPush component additionally checks every component between that component and the root, limiting the value of the optimization.

RxJS integration

You might notice that none of this overview includes RxJS. Angular does not internally use RxJS to propagate state or drive rendering in any way. Instead, Angular uses RxJS as a convenient data structure to express streams of events over time (such as for EventEmitter), completely disconnected from the change detection and rendering system.

You must be logged in to vote
Comment options

What impact will Signals have on hydration and server-side rendering improvements that are both on the roadmap?

You must be logged in to vote

2 replies

@atscott

Comment options

Signals don't have immediate impact on hydration and SSR improvements. These improvements are actively being worked on and will be included in the v16 release as developer preview APIs. Is there anything specific you were curious about?

@jessicajaniuk

Comment options

Immediately out of the gate, Signals has no impact on hydration and server side rendering improvements. That work is independent, but we'll be looking at signals in relation to SSR and hydration more directly later on this year. So stay tuned.

Comment options

Why decorators are magic for devs? Why perfectly designed class components should be replaced with some "react style" hooks?

Looks like angular has lost it's popularity and you are trying to return back peoples attention. I really consider that react hooks are mess.
Angular was such a great framework for big projects with a lot of bussness logic that noone of vue or react can handle properly. Without awful ngrx, angular is such a great instument, why should I use "that", "that" you've just inroduced to us? I really do believe that I'll get it, but if i don't understand react hooks, i'll never understand this.
I think of using Ember (,:

You must be logged in to vote

15 replies

@AndriiDidkivsky

Comment options

@flashios09 and this is looks great!
I am afraid of "react style" code, when instead of class i have to use function and component state stored somewhere outside. And to avoid a lot of function/vars recreation I use useCallback useState, etc. If we still have classes but without decorators, I'll might get it, but different codestyles looks weird, IMHO. I wanna use entire power of the js, and have ability to use inheritance, decorators, etc. For me it's not magic. You might say that React Hooks are optional but we all know how it's going in the real world, where any component of any complexity created with hooks. I've seen this image in twitter yesterday. It's a nightmare for me.

future_of_angular

@Coly010

Comment options

^ I don't hate that tbh.

With some extra work, that style of API could be made to be composable.

@e-oz

Comment options

I do hate it with every molecule of my body. Remembering all these "methods" inside the functions from AngularJS... 🤮

@gioragutt

Comment options

Also, count = signal(0); is by definition something that won't work. This is trying to replicate Vue's Composition API, but without it being part of a template that can do the wiring between the variables and the HTML.

Without seeing how such an API will be in a broader scale (not just a simple snippet but a functioning application), it's not something I personally like.

@dionatan-g

Comment options

This is not twitter, please, keep this kinda of useless discussion outside of this important RFC.

Comment options

With a Zoneless application using signals, will this negate the need to trigger change detection when writing unit tests?

Writing unit tests for OnPush components by wrapping them in a host component is a common pain point for me. If going Zoneless with signals solves/simplifies this, that'll be amazing!

You must be logged in to vote

1 reply

@atscott

Comment options

An application/test with all components authored using "signal: true" should be able to loop running change detection until there are no longer any "dirty" views or pending effects. We will be investigating the testing story more carefully as we get deeper into the project. We're not quite happy with where things are today and would love to improve it.

Comment options

Will a zoneless application using Signals offer bundle size improvements over a zoneful one, or are they marginally the same?

You must be logged in to vote

1 reply

@alxhub

Comment options

It very much remains to be seen, given that most of this code doesn't exist yet.

But zone.js isn't tiny, so we'll see.

Comment options

Interesting times ahead for #angular 😁

You must be logged in to vote

1 reply

@ts-dot-rs

Comment options

The comeback we never knew we needed #bing

Comment options

Really appreciate the thoroughness and thoughtfulness of this RFC. Look forward to digging into the sub sections. But, overall, I'm excited for this development in the framework, especially with regard to its impact on performance, and enabling teams to create more performant components without having to hand-hold change detection so much. Eager for a zoneless future.

You must be logged in to vote

0 replies

Comment options

I'm curious how using signals as a reactive base for Angular will affect a part such as "Reactive forms module",
And moving forward to use more functions than using classes I think it will change many things in a good way.

You must be logged in to vote

3 replies

@dylhunn

Comment options

This change definitely has implications for Angular Forms. We haven't yet decided exactly what path we want to take.

At the very least, Forms will need to become signals-aware, e.g. to allow a signals-based component to respond to forms values, validation status, etc. We may take this opportunity to make other improvements as well.

@mikeandtherest

Comment options

@dylhunn Is there a roadmap for this? I'd love to see an RFC for signal-based Reactive Forms.

@DibyodyutiMondal

Comment options

Instead of making them signal-aware, why don't we make it completely based on signals. Where rather than emitting observables, we emit signals for values, status and errors.

Consumers can then choose to use toObservable if they wish.

I understand if this may be a bad idea. But I'm curious to know the reasons why, because I can't think of any.

EDIT: This would also probably be a step forward in making libraries such as angular material signals-based. And I'd love material to be signals based because it's the only thing that's preventing me from removing zone.js.

Comment options

I'm wondering how will the use of Signals affect Angular’s internals that depend on observables such as forms, router, and http client?
Is it going to be rewritten to use Signals internally?

You must be logged in to vote

1 reply

@Coly010

Comment options

I noticed there is a suggestion of an interop layer. Perhaps the thoughts are to use that.

Comment options

I think this will also pave the way to having functional components in the future. It is very understandable, and I imagine a component built entirely on signals would be way more readable and simple than a "traditional" one.

You must be logged in to vote

41 replies

@timonkrebs

Comment options

I can't wait to debug code like this:

effect(() => {
  const isEven = computed(() => source() % 2 === 0);
  const isOdd = computed(() => source() % 2 === 1);
  (computed(() => isOdd() || isEven()))();
  source.set(source() + +isOdd() || +isEven() );
}, { allowSignalWrites: true });

Please release already, and everybody let's join in the fun!

We will have devtools that can really help with understanding what is going on. Like with solidjs devtools:

@lvetskov

Comment options

Breaking changes of this scale will not only attract people - they will move people away. Angular, once again, will look like a non-reliable framework where everything can be “deprecated” just because. The main users of Angular were “enterprise” - they do not like such things.

I cannot agree more on that. Angular has always been the chosen frameworks in the enterprise because of its stable, iterative and well predicted future releases and longtime support. If Google wants now to fragment Angular just because they want to have yet another React clone and attract the cool kids... then that will be terrible experience yet again. Even just the thought of doing that make me consider on how we should proceed with our next enterprise solution.

@Jordan-Hall

Comment options

I agree, told a client just last week we should consider a rewrite of the application UI layer. Angular is fast becoming out of favour for my recommendation for enterprise applications. Especially thanks to NX work for helping people with other framework migrations

@elgreco247

Comment options

@lvetskov What breaking changes are you talking about specifically? Do you consider signal-based components as a concept a breaking change? Functional lifecycle hooks? Read-only signals as inputs?
Are you not satisfied with the team's assurances that zone-based components will be supported for a long time?
Why do you assume to know the team's intentions concerning this RFC have anything to do with React or "cool kids"?

@michaelfaith

Comment options

Couldn't disagree more. I'm excited by the innovation (anybody that's read the RFC would know that this isn't just a "react clone"), but also by their long-standing commitment to backwards compatibility (this hasn't changed).

Comment options

You must be logged in to vote

0 replies

Comment options

You must be logged in to vote

4 replies

@timonkrebs

Comment options

Why do you think signals are a all or nothing option? I see no conflict in using signals and rxjs together... Signals should be used as a much more powerful replacement for zone.js not as a replacement for rxjs.

I do not see how this would lead to a multi-paradigm approach. There is still one approach for change detection (signals) and one approach for handling events (rxjs). Sure signals are that much more powerful than zone.js, so that it could even remove/reduce the need for rxjs in (simple) applications.

But if you replace zone.js (with a much more lightweight solution in size and performance and complexity ...) and even reduce the need for rxjs in some simple cases, that looks to me much more like a huge reduction of complexity...

@kyjus25

Comment options

Signals are not all-or-nothing, they are opt-in at the component level.

Kind of mimicking what @timonkrebs said, I don't see Signals as Angular becoming multi-paradigm (I do for standalone components, but that's a different topic). Signals need to be adopted gradually, and they are the recommended approach for new components. I don't look at it as multi-paradigm, I see it as backwards compatibility. It's intended that Signals eventually phase out Zone.

@michaelfaith

Comment options

I do mean at the component level. In a video earlier today, it looked like if you opt into signals for a component, then you are using signals. You can interop with rxjs manually, but the component is a signals component, vs. a classic component. This seemed to be by design. Is this not the case?

You can still use signals outside of Signal-based components though (e.g. services, zone components). However, if you use signals in a zone-based component you just won't be excluding the component from the zone-js global change detection algorithm. It's that, that's defined at the component/directive level. Which is great, because it allows teams to migrate over time.

I don't look at it as multi-paradigm, I see it as backwards compatibility. It's intended that Signals eventually phase out Zone.

Well put. This is how I see it too. I honestly see standalone components sort of in this way too. But that may be up for debate.

@timonkrebs

Comment options

@jrista supporting a class-based or functional approach. What does that mean, from an overall complexity standpoint, at the whole framework level?

Why do you think that function components may be a key reason why signals are being introduced?. They really thoroughly explain why they would want to introduce signals. Nothing points to function components. Do you belief they hold information back? But then why would they do all of this RFC stuff? They could do anything they want without going through all this pain talking and listening to us...

I also do not see what would be better with functional components. But react does support function and class components and still have enough resources to work on new and shiny things like RSC. So why do you think this would hold back the angular team?

Only for the record: I really do not see any benefit coming from going to function components. But I also do not see how this signals RFC would be connected with this.

Comment options

Is OnPush directly correlated to ZoneJS, or are they separate entities? More specifically, can I utilize a library using OnPush and still be able to remove zone.js from my application running Signals?

You must be logged in to vote

3 replies

@atscott

Comment options

OnPush is based on ZoneJS, top-down change detection. It's hard to make OnPush work without ZoneJS, but it can be done and people do it in applications even today. If you were to use an OnPush library, it wouldn't be guaranteed to work unless the author created it in a way that considered zoneless applications. Most code makes assumptions about the existence of ZoneJS (click events automatically trigger CD, setTimeout triggers another CD, etc.).

@ysk3a

Comment options

So, would this mean that it would be difficult to migrate to adding signals to the app if the application uses a mix of default, onpush already?

Ah nevermind. I think that was answered in #49685 (comment)

@atscott

Comment options

So, would this mean that it would be difficult to migrate to adding signals to the app if the application uses a mix of default, onpush already?

Ah nevermind. I think that was answered in #49685 (comment)

Right and I'll also respond directly here as well. You can read signals in existing components. When those signals update, Angular effectively calls ChangeDetectorRef.markForCheck in those components, similar to how the AsyncPipe works.

We will also make sure components authored with signals: true (or whatever the opt-in is) work in a way that makes sense in an existing OnPush/Default change detection application.

Removing ZoneJS completely from the application is a different story. That's something that would take a lot more consideration.

Comment options

I think this is the most exciting evolution of Angular since 1.0, and the evolution since 1.0 has been solid. I'm extremely happy with the overall design, and what it unlocks for Angular going forward - namely clearer code and performance. Kudos to the team members leading this effort for the thoroughness of these RFCs and the prior work to refine the concepts and ensure backward compatibility in the design.

I've always felt that zone.js and the change detection model was the worst/clunkiest part of Angular - to clarify, zone.js is an impressive building block, but it and the change detection model are the hardest parts to understand and troubleshoot. In addition to potential hidden efficiency problems, there are unintuitive rules - eg change detection doesn't propagate unless inputs have changed or a DOM event has occurred; and host attribute/style changes require a change detected on the parent. It requires regular developers to have a deeper understanding of the internals of Angular than it should. So I've avoided relying on zone as much as possible, use OnPush or ChangeDetectorRef.detach, and come up with my own pipes and primitives for understandable and more granular updates in performance sensitive cases.

Hindsight is 20/20, but it's clear to me that this is the "correct" approach for Angular, and is needed to make/keep Angular competitive with newer frameworks.

You must be logged in to vote

0 replies

Comment options

HI :) got this error while using fromObservable: "ERROR Error: fromObservable() signal read before the Observable emitted"

I have to add a startWith as a workaround. Is this an on-purpose behavior?

isNewChange$ = this.form.controls.isNew.valueChanges.pipe(
    // startWith(this.form.controls.isNew.value),
    tap(console.log)
);
isNewChange = fromObservable(this.isNewChange$);
You must be logged in to vote

2 replies

@e-oz

Comment options

yes, unfortunately. see RFC#4.

@theophane-girard

Comment options

okay we can also fix it like this, didn't see :)

  isNewChange = fromObservable(this.isNewChange$, this.form.controls.isNew.value);
Comment options

Awesome works from you folks! 🔥

Do you already have some vision on the long term plans? I mean, are you aiming (in a future version like 18 or 19 or 20...) to make signal based components by default (and standalone as well) which will imply the deprecation of input/output decorators and ngOnInit and other lifecycle hooks.

I'm asking that because as the primary goal of what's coming since v14 is to reduce the learning curve and increase the traction I guess new comers will get confused if both worlds (signal based and zone based components) are living together in the framework, I'm afraid some developers might get discourage when asking themselves "should i go signal based or zone based" which will requires a lot of digging to understand the pros and cons (thus the learning curve will stay the same).

I'm a fan of opinionated technologies and I hope Angular will stay opinionated and that we are currently in a transition to full standalone and signal based apps. 🫶

You must be logged in to vote

0 replies

Comment options

Great work guys! I've played around with signals and I think you're getting it right. It feels like the good parts of Vue.

One thing I thing we could do better is the value calls on primitives.

  1. At the very least it would be great if we didnt have to add () in the template to get Signal values.
  2. It would be even better if we could figure a way to avoid value calls this.count() in computed callbacks.

Could this be possible with primitive values?

class WritableSignalPrimitiveConversionImpl<T> extends WritableSignalImpl<T> {
  [Symbol.toPrimitive](hint: string): T {
   switch (hint) {
      case 'string':
         return String(this.value);
      case 'number':
         return Number(this.value);
      default:
        return this.value;
   } 
 }
}

Sorry very rudimentary idea but maye using Symbol.toPrimitive could get the desired API?

You must be logged in to vote

0 replies

Comment options

How about using objects inside a signal? What do you think about it? can I use it? angular will support such a thing?

user = signal<User>({ name: '..', ... });

When I change name property does angular know about that? or is it just a solution for primitive type (number, string, boolean..)?

@alxhub @pkozlowski-opensource

You must be logged in to vote

5 replies

@mfp22

Comment options

This works. There's nothing special about objects. You can pass a new object into set or mutate the object inside update.

I guess this is a fair question though, considering that input treats objects as special.

@mlc-mlapis

Comment options

@wizardnet972 You can use any data structure.

The default equality function compares primitive values (numbers, strings, etc) using === semantics but treats objects and arrays as “always unequal”.

The .mutate method will always send change notifications, bypassing the custom equality checks on the signal level.

The combination of the .mutate method and the default equality function makes it possible to work with both mutable and immutable data in signals. We specifically didn’t want to “pick sides” in the mutable / immutable data discussion and designed the signal library (and other Angular APIs) so it works with both.

@michaelfaith

Comment options

It would be something similar to

user.mutate((currentUser) => currentUser.name = newName);

which would tell Angular the signal changed

@mlc-mlapis

Comment options

There is probably a question about clarifying the following sentence. Does it mean that even when using a custom equality function, it's impossible to evaluate that two objects/arrays are the same?

The .mutate method will always send change notifications, bypassing the custom equality checks on the signal level.

@alxhub

Comment options

Does it mean that even when using a custom equality function, it's impossible to evaluate that two objects/arrays are the same?

In mutate, there aren't two arrays/objects, but one object which gets mutated. So the concept of equality doesn't really apply, since there is no separate, unchanged "before" value to compare the changed value against.

Comment options

Is there a way to implement the signal change detection into the async pipe?
We got the view where is used and we got the subscription to track.

You must be logged in to vote

5 replies

@alxhub

Comment options

No need - starting in v16, signals will automatically mark OnPush components for check - no async pipe needed.

@retry2z

Comment options

More I ask about in context of observables if we don't use signals

@DibyodyutiMondal

Comment options

signals will automatically mark OnPush components for check - no async pipe needed.

Case 1: Imagine the root component has a signal counter$, used in the template:

<div>{{ counter$() }}</div>

Case 2: Imagine the root component has a signal counter$, used in the template, but passed as an input:

<counter [count]="counter$()"></counter>

In each of the above cases, will it re-render the entire template of the root component? Or just the html element/component that has the signal in it?
I mean, how 'fine-grained' is it?

@mlc-mlapis

Comment options

It's grained per a view.

"Views" in Angular are static fragments of templates - sets of known UI elements, directives, and child components. Views are composed together to create templates that can express conditional or repeated sections of UIs.
For example, the following component template is a single view:
<div>
  <label>Who: <input name="who"></label>
  <label>What: <input name="what"></label>
</div>
Whereas this template has two views - the outer DOM with "Who" and "What", and an embedded view which is conditionally shown which contains "Why":
<div>
  <label>Who: <input name="who"></label>
  <label>What: <input name="what"></label>
  <ng-container *ngIf="showWhy">
    <label>Why: <input name="why"></label>
  </ng-container>
</div>
Each branch of an NgIf or NgSwitchCase and each row of an NgFor are examples of independent views in Angular.

@DibyodyutiMondal

Comment options

So in essence,
Step 1: Always follow the rule "template data MUST be a signal if it is dynamic or a read-only property if it does not change"
Step 2: As far as makes sense, break template into views using ngIf, ngFor, ng-container and ng-template. Plus the usual optimisation such as trackBy for ngFor. Don't overdo it, though.

Am I right so far? What else can we do to keep dom changes as small as possible?

Comment options

This feels like, we're reinventing the wheel... I mean: Angular is and was built to be reactive. The original idea was to use RxJs's Observables to mutate the DOM, when an Observable changes. And it can actually be done, when using for examples Stores or developing in reactive programming.

Signals are reactive programming but with a different syntax. More precisely, they are BehaviorSubject.
So, if I had to guess, we'll see soon a tons of pipes/functions to play with Signals in React, and we'll encounter the same in Angular. BUT all of this already exists in Angular, simply using RxJS... We'll end up with 2 Observable like libraries in the same framework. This sounds like craziness, all of this due, in my opinion, to an unjustified "hype train".

Maybe we should let the things settle down, and provide a very robust paper: why Angular should move to Signals ? Are the benefits really worth it ? Are they other solutions, maybe better ?

I mean, Angular is a widely used framework, mainly by companies requiring a stable, scalable, and robust framework. So we should not be blind, jumping from the latest trend just to attract "the cool kids". Angular's target should remain to focus on companies requirements, not on the "fun" and "latest" tool. They may be great, but they should not interfere with a long term vision.

You must be logged in to vote

9 replies

@lifaon74

Comment options

@Harpush

That's why computed value can be accessed for example while piped behavior subject can't

Yes, this is actually a very convenient way to access value. I agree that using Observables requires to think differently, and this is something not easy, especially when we are used to sync code.

@e-oz
I took time to read it, and I took time to test Signals (with react). I don't say that the Angular team is composed of new developers, I'm saying that, in my opinion, things are rushed. The underlying goal, is probably to attract developers, surfing on the hype. A W3C, WICG or tc39 spec takes months (and usually years) of thinking to create something very robust. I would prefer that the Angular team does the same instead of rushing it. I mean: signals have been introduced a month ago for angular, and seven for react (approximately, don't focus on the exact date, this is not the point of the debate). This is extremely fresh, and maybe lacks of debates or alternatives.

@eneajaho

Comment options

Hello @lifaon74
What signals did you try in react? Afaik they are hooks and not signals, two different things imo.

@pkozlowski-opensource

Comment options

two different things imo.

React hooks and Angular signals are very, very different mental models and syntaxes. We didn't mention React hooks in this RFC as for us the two technical solutions are so far away, almost on the opposite side of a spectrum. But it seems like we might add a dedicated section in the RFC.

In any case: none of the React's hooks considerations apply to the proposal discussed here.

@mikeandtherest

Comment options

@lifaon74 The idea is that we need a fine grained reactivity in Angular. I totally agree with the team that going further with the current dirty global Change Detection (bandaged a bit with OnPush) won't play out well in the years to come. Probably the signals decision is also part of the current 'hype train' as you say, but that doesn't mean it's a bad thing, if they offer exactly what we're missing.

Now about Observable used as a reactive primitive. Even though I love RxJS so much and I don't quite like that the Angular team seems to try to not include it more in the core, I personally don't think it would have been a good candidate for synchronous reactivity.
In my opinion, Observers are intrinsically asynchronous and that would either make it hard for the Angular team to obtain the targeted fine grained reactivity, or it would permit less experienced developers to created a lot of bad code in the actual projects that will make use of this (something that's not async and also not sync, but a weird and bugous mix of them).

So having a clear separation between a sync reactive primitive (Signal) and the async counterpart (Observable) seems to me like a reasonable and safer decision.


There are other aspects in these five RFCs that I don't quite like and I've added my comments regarding them. But the Signals as a core concept and the fine grained reactivity that they make possible, I truly feel it's the way to go forward.

@jelbourn

Comment options

Angular is and was built to be reactive. The original idea was to use RxJs's Observables to mutate the DOM, when an Observable changes.

This is a pretty common misconception- Angular has never, in any capacity, used RxJS to drive change detection or rendering. From the beginning, Angular was always build around top-down, pull-based, global change detection. The original design intent was to evolve the mechanism used by AngularJS to be more "invisible" to developers (via zones) and more performant by limiting the number of cycles (unidirectional data flow). RxJS came into the picture primarily as a convenient data structure to express a stream of data and/or events over time for features like HttpClient and EventEmitter.

Alex has a long explanation of our rationale for using signals for reactivity over RxJS in #49684. We know, though, RxJS is an critical tool of many developers' toolboxes, and our goal is to make using RxJS with Angular better than it's ever been by having a clear interop story.

Comment options

Everyone should watch this entire video before posting here.
Signals in Angular with Pawel and Alex
There are so many misconceptions and nonsense questions that I feel like people don't even care to learn the basics before wasting developers time.

You must be logged in to vote

2 replies

@JHarrisGTI

Comment options

That video is over 5 hours long. I don't think requiring people to watch it before they're allowed to respond is helpful.

@tayambamwanza

Comment options

That video is over 5 hours long. I don't think requiring people to watch it before they're allowed to respond is helpful.

I don't think it should be a requirement, but it's kind of annoying to see questions asked that were already addressed in the video, some due diligence would be nice instead of perhaps even getting emotianal over something that you would've known had you taken the time, it's a conversation so one can even listen to it while coding or doing some busy work.

Comment options

Okay wanted to give some feedback, i have been testing out angular 16.0.0 rc and watched the whole talk about Signals RFC and in the end there is a question about thoughts on functional components in the future - where the answer is (if we get it) it will be added on.

So my question is keep adding features cant that exhaust newcomers to angular, i start to see a fairly complex component structure

  • Standalone/Non standalone
  • Signal based/Non Signal based
  • Class/function

What i have experienced over the years of using angular which has been ever since the first release of angular.js and up until now i feel a lot of people turn away because there is so much stuff, such a mountain to climb.

And i think this ever growing mountain will have an effect on how the community could grow in the future

Last but not least - I love the class based components and services

But i also think function based guards, interceptors and pipes makes sense tbh

You must be logged in to vote

3 replies

@timonkrebs

Comment options

I think the learning curve will get easier if there will be a recommended way to getting started with angular that is more intuitive. As a beginner I do not need to know everything about a technology. I just want to get an app up and running. I do not care if there are multiple ways of doing it if I have a reccomended way.

The best example is react where it is already possible to use class components and function components. And no one complains about that when it comes to the learning curve of react. React is even praised for its learning curve despite of this.

To go with your analogy of the growing mountain: If there is an elevator built that I can take to get to the top of the mountain I will not complain anymore about the hiking route beeing to steep...

@sp90

Comment options

While i do get your point - I think this is also the discussion that the Ziglang people had when developing they kinda wanted one way to do things (the right way)

So for angular i have always felt going into a new angular project i can instantly see what have been done and what is going on almost no matter how big it is. In extension to that I often experience that a lot of developers either dont know the "recommended way" or just ignoring it which inherently mean more bad codebases around. Where as if there was only the "right" way to do things this would make a stronger community as a whole. Also because libraries using angular features would also have to follow the only way (the right one).

@michaelfaith

Comment options

This was discussed in a few places, and commented on in the Signals live stream the team did. They're not really intending to provide an entire buffet of different but equal options (which would be hard to teach and could overwhelm people trying to architect an app for the first time). They're introducing new patterns that they're recommending to use going forward, while maintaining backwards compatibility. Leaving the old APIs in place, isn't meant to be yet another option, but it's to help teams opt-in gradually over time. So, in that sense, if you're a new Angular dev or going to teach a new developer how to work in Angular after the full rollout, then you don't even need to care about Zone, OnPush, ChangeDetection etc. All of those concepts go away. They co-exist in the framework, not to encourage their continued use, but to allow that measured migration path over time. Hopefully the eventual documentation that accompanies this change will articulate that clearly.

Comment options

Could we have a semantic command to detect the variables that should be signals and change their types?

You must be logged in to vote

0 replies

Comment options

I'm very excited about signals; they're going to make building complex forms much easier. Playing around with the release candidate, I accidentally a bug by pushing to an array returned by a signal without using set() or mutate(). Do you think that either TypeScript or the Angular Language Service for VSCode could warn me against doing that in the future?

You must be logged in to vote

0 replies

Comment options

Why is Angular trying to look like React or Vue ?

We liked Angular because it had a strong opinion about how web pages should be built. We liked Typescript, classes, separation of concerns, modularity, SOLID and DRY. We liked Angular for the way it approached web, for the way it was standing for all web pages as structured pieces of software. We could really talk about web engineering at the core of Angular.

I was ok with standalone components, I use them wisely enough to get proper benefits. I am ok with getting away from zone.js, I'm even okay for providing Rxjs as an option and not a requirement.

But trying to recreate React syntax on Angular is not the way to go. Until recently, it was quite difficult to write bullshit with Angular. You had to get it done the solid way, by default.

And I'm sure someday we'll be missing those days.

You must be logged in to vote

11 replies

@dionatan-g

Comment options

@Lerado you clearly didn't read anything about angular signals or if you did, you have no idea what you talking about.
Also, you don't know how reactivity works in react and vue, that's why.
The level of comments in this RFC is extremely sad.

@tronicboy1

Comment options

@dionatan-g
I think the majority of posts are constructive! I even had ideas about the implementation to make it easier to code.

I think it's a matter of not "taking the bait" of non constructive criticism.

@DibyodyutiMondal

Comment options

I really do not see how React syntax is the same (it's slightly similar, though, I agree). But even if the syntax is the same, the underlying logic and implementation is very very different - useEffect() from React and effect() from angular do very very different things, for example. So how does it matter that the syntax is similar? React principles don't apply to angular+signals and vice-versa.

I would dispute the fact that angular is moving towards a functional approach. Personally, I have felt that angular was always functional. Angular only used classes/objects to group/scope things to to the component/directive/service, and also to serve as a data-pool for component templates. This gave structure, but was also boilerplate-y. Another reason to use classes was because at the time, constructors were the only way to use dependency injection. But the main code that drove reactivity in angular always tended to be functional, because reactivity is by its very nature, functional.

None of the above have changed with the arrival of signals. We'll still use classes to create the basic units, be it directives, components or services. Because we still need the structure and grouping that classes provide.

As for the identity of the framework changing - I fail to see how the new changes make it easier to scribble away and make mistakes. I will not lie - early on, I was kinda excited to see how much it changes the way I author components. I assure you, structurally, it barely changed. But it did make things easier to read, and maybe even remove some code.

The only fundamental change in identity is that the magical change propagation, where changing a class property changes the DOM will no longer occur with signals. We must use signals' mutate/set functions for reactivity. But I'd argue that most apps used OnPush and gave up on the magic anyway, and used observables.

@sp90

Comment options

@Lerado i get where you're coming form and me personally dont want the functional components nor services because this is what for me is the fundamental super powers of angular.

I also did comment on it, and FYI they said in video about the RFC where they go over the whole thing that components would never be 100% functional they would always be given as an alternative.

I personally think that this is a bad decision because i guess a lot of devs trying to do angular is struggling with feature fatigue. I often meet devs who write angular but dont know that there are default overrides for datepipe, currencypipe, language helpers and the likes.

I feel that your message reads more angry than you probably mean to, I just wanna say essentially I can understand you and do agree with you to a certain extend

Last but not least i dont think we look anything like vue, vue looks more like angular.js meets grunt with some modern twists to its api. And react with JSX is far from what i believe angular and the team is trying to accomplish.

@tayambamwanza

Comment options

Typescript, classes, separation of concerns, modularity, SOLID and DRY.

What about these changes in Angular will stop you from applying these though? Angular implementing signals couldn't be further away from React, just ask the React team, they don't believe in signals being an optimal solution, so this is the least React thing they could've done.

I think your concern is more about the identity of Angular rather than that the changes are actually bad or not. Personally I'd prefer Angular to have the identity of a framework that adapts rather than just stays the same for all eternity, it will be around longer for it.

Just because another framework uses a certain technique doesn't mean we should not adopt it for fear of "looking like copying" imagine what world we'd live in if nobody re-used good ideas.

Comment options

Let me try to ask/write some things as company mindset = "STABILITY".

Considering RFC introduction / reasons :

RFC: the old way of building will live on for backwards compatibility (following our support policy)

As support policy is general guidance and are subjet to change, this is not clear about the future. How is possible to have a more official, precise and clearer response of support of "old way" which is already called "old way" instead "current way", to reassure companies choosing Angular2017 after migrating from angularjs2015 and be afraid of this choice. (i don't say it is but breaking-change, sometimes inevitable, is the word that scares companies/business the most).

"Better guardrails to avoid common pitfalls that lead to poor change detection performance"
"First of all, improved runtime performance"
"Faster performance"

It seems be out of scope to me. And I know i don't make friends saying that but without bad faith can someone explain what performance means here ?
How is this measured, are people writing angular application for Rocket 🚀 launches and Rocket explode ? Since 2017 my team is reengineering an entire ERP (writed in COBOL) : we have +1700 components, ≈400 lazy routes/feat. ngmodules, without any OnPush, fully FormReactive, with hundreds of users and application is surprisingly very very fast.
A change detection perf was never and ever a problem. NO we are not superman, we are not following best practices we have a lot templates with >1000 sloc 👎 . Due to this and with this size of app we encoured some other perf problem especially with previous version of CLI serving/rebuilding/building). If change detection perf is a problem and the main reason, why this couldn't be catched from the beginning (when decisions were made by ex-people much but much smarter than us) on a pretty fake large project when choosing whole tree check +5/6 years ago like I easily generated here https://github.com/elvisbegovic/ng-speed-rebuild ?
Is our app of +1700 components considered as little project and I should expect performance issues from more than 5000 components?

Considering deprecation practices :

  1. We work hard to minimize the number of breaking changes and to provide migration tools when possible

Thank you a lot to team member being part of migration tooling. Questions: what will be the priority of the migration tools regarding Signals? Because working hard is one thing but priority is another. I ask comparing to standalone which is in production state and some issues cross-cutting: standalone Issues related to the NgModule-less world block migration on med-project.

UPDATE 21.04.2023 (adding point 4)

Considering what I read somewhere in comments :

  1. "We take backwards compatibility seriously ... thousands of Google applications built with Angular."
    or
    "At Google there are thousands of Angular applications, some of them very huge ... we would be responsible for migrating every single one of those applications."

This kind of sentence or similar used by years is great to remind but IMHO this is not at all valable reassurance for companies. I know I still not make me friends but Angular Team should not be responsible for only migrating envery Google's application but for all existing companie’s app. And please be realistic/fair, Angular Team or other Google team is the same company, the fear of a breaking/refactoring/rewriting changes will not exist if companies have excellents developers from Google as internally help; instead companies have internals ressources for a limited time that not knowing how the heart works but juste lambda-business-developers. Please apologize, I am not saying this to disturb it is not question for laugts like "who from the top at Google is giving an end of life of Angular lol" , I am just afraid to see companies (like mine) leaving Angular without even necessarily following the departure of the very important and very competent resources of Angular Team.
(PS: don't know why I say that but want : don't care if react is TOP#15 in github rating repo.)

UPDATE (21.04.2023)
Is it too late to change anything? Due to big efforts already invested + hours and hours of videos about Signals already existing on web. I think not really late, so what you think guys ?

You must be logged in to vote

6 replies

@Jordan-Hall

Comment options

100% agree, one of the reason I promote Angular to clients is because of the robust and stable API. Current company has over 500k lines of code and developed by just 3 people now. Its a tall order and I cant relay on the following

"We take backwards compatibility seriously ... thousands of Google applications built with Angular."
or
"At Google there are thousands of Angular applications, some of them very huge ... we would be responsible for migrating every single one of those applications."

Also the addtional talks by some of Angular team publicly about more functional components etc just makes it feel like this is a new angular and as such all will be legacy in a year or two. I appreciate view engine took 3 years to finally remove, however can I ask why it took so long. Is it because of angular team migrating?

@DibyodyutiMondal

Comment options

It's really great to see that people have successfully built huge complex applications with Angular and are in general, very happy with the results.

It's a very valid point for enterprise teams to ask for a sense of stability when it comes to any framework. Too frequent major changes would indeed be very exhausting.

  1. There will be a lot of time for companies to adjust. But you know what? I don't see a reason for why you would have to wait. Take v15 for example. v15 is so robust, I could probably use it for the next 3-4 years (like how many people stay at v8/9 for a long time before suddenly migrating all the way to v14/15) and not have to migrate to v16 or higher at all. (Provided typescript and javascript don't do something too major that's too attractive to ignore)

    But then again, I can migrate to v16 today and not go above that. I'd still be able to use the older APIs, barely have to change my code, and yet that 3-4 period now becomes 4-5 years. That's plenty of time to migrate, don't you think?

  2. As far as I understand it, the real change here is not functional components. We can have functional components right now, today, simply by refactoring the decorators into a function, and it'd work exactly the same. No, the real change in this RFC is in the change in the mechanism for the 'magic' that allows angular to update the DOM when the state changes. And that magic, let's be honest, is part of the foundation of the framework itself.

    In fact, this change is so fundamental, I think it's amazing in and of itself that we will get intermediate releases where both old and new systems can co-exist. Not to mention that the team is trying its best to get as much community feedback as they can.

    To be honest, this change was long due. Because I think, this current change would not be possible without the introduction of the ivy engine. If you think about the larger direction:
    Step 1. Make a better, smarter template engine - Ivy
    Step 2. Introduce a faster, simpler way for change detection - signals
    Step 3. After thorough testing, remove the old CD mechanism
    Step 4. Remove zone.js and get rid of the unnecessary complexity and performance hit it brings

    Clearly, those are all huge changes by themselves, and even more so when you put them together. Ivy was introduced in v8 (I think?) and yet it took so long for it to become stable enough for the team to become free enough to research an alternative CD mechanism, and then they introduced signals. Signals may experience the same thing Ivy did - where there will be a very very large incubation period before they move to to step 3. Again, I feel it should be plenty of time.

  3. Angular is open source. It follows it's own direction. The fact that it's backed by a megacorp means nothing. The only thing that matters to us is that it's direction is not in our control. This risk of change is something we signed up for the moment we decided to use it, and it was probably one of the first decisions taken when the app was in the design stage.

    The good news is that we can choose not to use newer versions (see point 1). If we are lucky, we can use newer versions and still use the older system, and we are that lucky (see point 1).

    As was correctly pointed out, we can't really rely on them to provide good backward compatibility just because they're also responsible for Google's apps. But by that same logic, we shouldn't have any expectations from them at all; and yet here we are, in an RFC.

And we are in an RFC because of people like you, who have worked hard in the field and written a lot of things in angular, and know deeply the ins and out of the framework; so your feedback on how to make it work would be worth its weight in gold.

While your apprehension and exhaustion because of frequent major changes is understandable (and we all share it in varying degrees), I think we shouldn't let it cloud our vision of 'what could be'.

PS: Yes! Angular Material should be definitely used as a demo project for signals. (as well as for zone.js interop)

@Madhust

Comment options

These are some honest points. Love it. IMO, "Change is the only const thing". So I was not surprised with this change. Also instead of saying change, I would say it as an addition which I care less since it's not going to break anything in my app. I am pretty sure breaking-change brings frustration but with backward compatibility provided it's reasonable to me.

I'm following and using Angular to develop UI library from the day it's been introduced and every time it makes some changes I had to make changes to support the latest version and still feeling somewhat satisfied with it.
P.S: I'm not going to use signals in my application until I need it the most.

@elvisbegovic

Comment options

@DibyodyutiMondal thank you and can’t disagree, it is smart/nice approach and relatively valid point.

Please apologize me in advance because I am not Fluent in english. I am not sure I can be so diplomatic as you are nd I don’t use chatgpt 🤓.

As said what I write is « company mindset ». Everybody know it is possible to stay at ng8, angularJS or even jquery word everything will works thanks to ecms/JavaScript stability but even that is highly risky.

To rebounce on what you said let me answer with some potential « developer mindset » :

As developer, how many job offers from
bigcorp I refused because the app is still in AngularJS ? A lot (not in company advantage)

As developer or geek working at private company, I want follow the hipe and new things because we love learn new things, and developer or it-manager is often the person asking to direction or board member of companies that we need rewrite app because web-framework is deprecated and will not be supported in 3-4years (company holder writing app in COBOL since 35years can’t understand this)

Today it is backwarcompatible, in 1-2y deprecated, in 3-5y not existant in core. Can we ask to company which business is other than programmation, to follow same speed as framework-creator?!

@DibyodyutiMondal

Comment options

Absolutely!
I tend to reject assignments which have to deal with older versions too! 🙈

I feel we can divide angular's timeline into the following sections:

  1. Pre-angular/plain js
  2. AngularJS
  3. Angular 2-4 - Renderer1
  4. Angular 5-8/9 - Renderer2 or ViewEngine
  5. Angular 9/10 -> 14 - Ivy
  6. Angular 14+ - standalone components, inject(), etc

And it's just a personal feeling - each jump was less trouble than the previous jump. With the exception of Ivy, because 9-14 coincided with the same time as ecmascript was introducing major changes, typescript was introducing major changes, webpack introduced changes. A lot of things happened all together at the same time. Also, after typescript 4.5, typescript is getting better and more stable at compiling to javascript. Angular finally allowed us to change ecmascript target as well.

Because ecmascript/typescript changed, we had to change bits of code in many many places and it was such a headache. Not only framework-specific things changed, but component logic and utility functions needed to be updated. Patterns of writing code changed.

And for most people I have talked too, this particular period of instability is where this apprehension of angular migration is coming from.

Compare that with change introduced by standalone components: we copy/pasted imports from NgModule array to component array, then deleted the NgModule file and adjusted the import statements wherever necessary. Component logic hardly changed at all. Utility functions were not even touched.

The point I'm trying to make is that newer angular versions will last much longer than than previous angular versions.

EDIT: The only problem is, my point will become a reality in practice only after 2-3 years from now. Because I consider angular 14 as a tipping point.

Comment options

Foreword

Before you delve into the content below, we would like to make a few comments.

  • We appreciate that the Angular team is pushing for changes that will lead to advancements. Changes and improvements are the incentives for modern web development frameworks/libraries and Angular needs to be a part of that. The work visible in the proposals is a fantastic piece of engineering, even at the RFC level. Kudos to the Angular team for developing so many great patterns. The difficulty is finding the right balance between the scope of the changes, the severity, and the impact.

  • We want Angular to be successful in the long run, so we want to provide additional guidance for future consideration and planning. All of the concerns below have been summarized from comments loosely placed in the sub-RFCs and the main Signals RFC, and even from the community at large. We do not believe that anyone who actively reads the RFCs and leaves comments on them daily will find anything new here. However, this may help provide a more complete picture of the voices that have concerns about the evolving vision based on what we see and hear.

  • The concerned are in the minority, and that is only natural. Most of those who do comment seem to be satisfied, in whole or in part, with the picture that is being painted of the future. But with years of experience and the amount of applications one has designed and seen over the years, one develops a more sensitive mindset that can be of great benefit. The goal is to make the future bulletproof from potential undesirable effects of changes that initially seem groundbreaking and necessary. The concerns listed below are the voice of this minority, but they are veterans who have loved and worked with Angular from the beginning.

The goals are:

  • to ensure that the Angular team has this summary in a place that is easily accessible for future planning
  • to ensure that community members can also consider the downsides of the upcoming changes
  • to potentially get a response to all of these concerns from the Angular Team - because many of these concerns could turn into communication misunderstandings

Concern 1: Deviating from Angular's Identity

A significant portion of those who commented on all five RFCs are concerned that some of the proposed changes, along with other possible upcoming alternatives for code authoring, could make Angular too similar to other libraries and frameworks (such as React.js or Vue.js). On the one hand, this similarity could increase the adoption of Angular by developers coming from similar libraries/frameworks as the ones mentioned above.

But on the other hand, there is also a risk that by being too similar to these libraries/frameworks, Angular might lose its identity, which is defined by basic things like being opinionated, leveraging the power of OOP, having good homogeneity in most projects built with Angular, etc. In this process, Angular might get lost in the crowd and become just another web development framework that no longer offers anything unique to appeal to the current community as well as newcomers.

Concern 2: Confusion for Newcomers

Community members are also concerned about a steeper learning curve caused by implementing something in various ways. Angular has always been considered a framework that is quite challenging for beginners, and the need for simplification is understandable in that mindset. But allowing (too many) alternatives in how certain things are implemented is questionable and probably creates even more confusion for newcomers.

This growing complexity of Angular with different authoring styles (standalone/ngModule-based, signal-based/ngZone-based, class-based/functional, etc.) might discourage people from adopting Angular and make them choose other technologies that are simpler in their structure and style guide.

Concern 3: Backward Compatibility and Migration

A general concern about backward compatibility with existing features is raised, when new alternatives to them, such as signal-based components, are introduced. While it’s being said that there are no plans to deprecate ngZone-based components, it has been noted that a full automatic migration to signals won't be feasible and that some migration tools may appear along the way. This highlights the need for clear documentation and support for migrating to the new way of authoring components.

This will also affect third-party Angular libraries, as authors will have to split them into two parts starting with the next versions of Angular. One for the library users who do not need the latest features (e.g. signal-based components), the other for the users who want to benefit from the latest additions. This not only makes maintaining such libraries more difficult, but is also confusing for the community.

Concern 4: Impact on Enterprise Applications

The community is raising questions about the potential impact of introducing the Signals proposed changes for ongoing projects, and how they will have to be adjusted/rewritten in order to stay up to date with the latest versions of Angular and the latest recommended approaches on writing code. And this will be driven not only by the desire of staying in-sync with the latest trends, but also by possible breaking changes added along the way. As part of this, the community is emphasizing the importance of stability in enterprise applications.

Angular has been the go to web development framework not only for small to medium-sized enterprises, but even for the largest ones. That has been granted by its strengths, which make it well-suited for complex, large-scale and long-term projects. Just to name a few of what are considered to be its strengths:

  • being strongly typed (by using Typescript instead of JS)
  • leveraging classes and OOP (also made possible by Typescript)
  • using Decorators to augment and extend through composition different code structures (like Components, Directives, Pipes, input/output bindings, etc.)
  • low entry barrier and good adoption rate for developers coming from a .NET or Java backgrounds
  • being a comprehensive framework providing out of the box: a routing system, an HTTP client, HTTP interceptors, a reactive library providing data manipulation and streaming means (RxJS), unit and e2e testing integrated libraries, localization mechanisms, a build system (via WebPack), etc.

Transforming Angular into a hybrid version of its current form and a more functional version, similar to React or Vue, could have unintended consequences: instead of attracting new users, it could drive away both existing and future users. Given Angular's commitment to long-term support and backward compatibility, it's also important to consider the potential negative impact of introducing signal-based components and functional lifecycle hooks on enterprise-scale projects.

This is all in good spirit so we can avoid articles like this one being written for Angular:

https://betterprogramming.pub/i-almost-got-fired-for-choosing-react-in-our-enterprise-app-846ea840841c

Concern 5: Focusing on Learning Curve May Not Be the Primary Goal

There is a real possibility that in a few years AI-based tools will make the entry-level role obsolete and allow experienced developers to take care of the architectural and critical aspects of projects, while AI takes care of the general and repetitive tasks. Such a change would make the proposed simplification of Angular through alternative authoring experiences less relevant, as easier entry points for less experienced developers would no longer be necessary.

Concern 6: Moving away from Decorators in proposed Signal-based life cycle hooks

In several places in the RFCs there is a debate about the added value of decorators. Some say that they only make things more difficult and it would be better not to use them in the future. Others counter that decorators are one of Angular's strengths and a powerful feature that allows you to extend various structures of the framework with your own logic. And all this while ECMAScript is moving forward with the Decorators proposal, which is currently in Stage 3.

On the same topic, there is a heated discussion about the way the proposed lifecycle event hooks for signal-based components look. They are functional and do not use decorators or class methods, but are declared (at least part of them) in the constructor of the class. People are concerned that this creates a big difference between the look and logic of the lifecycle hooks of standard components and those of signal-based components. Many ask why the new components cannot be developed using the same approaches as the standard components.

Concern 7: Framework Fragmentation

With the introduction of signal-based components and functional lifecycle hooks, community members express concerns about possible fragmentation of the framework. They fear that the different ways to write components could lead to confusion and inconsistency in the community. The official Angular coding style guide will also have to recommend one of the two alternatives, which could lead to frustration among developers, teams and ultimately companies that are already familiar with the old approaches.

Concern 8: Reinventing the Reactive Wheel

There are also concerns about the introduction of signals in Angular, which are seen as reinventing the wheel, since Angular was originally developed with RxJS's Observables for reactive programming. Since integration with RxJS is still needed for asynchronous reactivity, some of the commenters on the RFCs wonder why it's not possible to adapt the RxJS functions so that sync reactivity can also be handled through RxJS. They fear that the framework could end up with two Observable-like approaches.

Concern 9: Proper Usage of Signals and their Relation to React Hooks

In the Angular signals discussion, community members debate the proper use of signals and how they relate to React hooks. Some concepts, like effects, could do more harm than good if abused by developers who do not understand what side effects are and when they are really necessary. The same thing has happened in the past with React hooks, but over time some best practices have emerged.

Will the Angular community have to go through a similarly lengthy process, or can there be a better way to get clear guidelines from the start on what to use and when?

In addition, this debate raises again the question of whether the new changes are influenced by other popular frameworks, potentially causing Angular to lose its current identity.

Concern 10: Adaptation to Industry Trends

Community members debate whether Angular should adapt to industry trends, such as by introducing more functional approaches, or whether it should retain its distinctive 'flavor' supported by classes, OOP, decorators, etc., that have been provided to users of the framework in an opinionated manner to date. Some believe that Angular's idiosyncrasy is an advantage, while others believe that the framework should evolve and adapt to remain competitive. Finding a balance between maintaining Angular's uniqueness and adapting to the needs of modern times is a challenge that needs to be carefully addressed.

Final words

This summarizes all the major and fundamental concerns raised in the main RFC and sub-RFCs. We believe that these are well-formed and well-founded arguments. They address several aspects of the framework, including its identity, learning curve, migration, backward compatibility, impact on enterprise applications, etc. These concerns highlight potential challenges and risks associated with introducing new features such as signal-based components and functional lifecycle hooks, while emphasizing the importance of preserving Angular's strengths and core principles.

Credits:

  • Enormous kudos to the whole Angular community for all of these discussions, concerns, ideas!
You must be logged in to vote

8 replies

@timonkrebs

Comment options

to ensure that community members can also consider the downsides of the upcoming changes

I think you made a great summary about the possible problems of this change. But it feels like you just left out what is generally considered beneficial about signals. Which would be at least as important to make a informed judgement.

It is for sure a good thing to consider the downsides of everything. But this discussion is closing and that is a point where focussing only on the downsides is maybe not the best time.

For example that we can get rid of zonejs for change detection is probably something that not a significant number of devs would consider bad... I can think of many more points, even more closely connected to signals, but I did not put in the time to write it down as nice as you did.

I just think that comments like this tend to steal the spotlight of other important comments, because they look like a summary rather than just a point of view.

Most of Angular developers will never spend time to read all of the comments and discussions. In a perfect world that would be best.

This was intended to sum up concerns in general not to be detailed summary of all ideas here.

I agree that most Angular devs will never spend the time to read all the comments. But that leads me to the conclusion that a detailed summary would be needed instead of only focusing on the potential problems.

Nontheless I think your concerns are a nice summary of the potential problems with angular signals.

I hope the Angular Team will do a detailed summary. Would be really interesting what they got out of these discussions.

@mlc-mlapis

Comment options

I agree that most Angular devs will never spend the time to read all the comments.

It's taken me nearly ten whole days to read all the RFCs and all comments, including understanding all nuances. 😃

@danielglejzner

Comment options

This is a good reply @timonkrebs :) - thanks for responding! I have written the "Foreword" intro to make sure and point out that this whole thing is not only about pointing to downsides/concerns. Far from it! Like I stated originally - the work done on this RFC is fantastic.

Work for summary has been done in a good spirit only. I have been also writing some articles in past days/weeks to bring wider audience here. Majority of Angular devs don't even know that this RFC has happened. That there is a way to interact with Angular Team and help shape the future. It is not widely known fact.

Articles have been intentionally lightweight, yet informative - thought provoking. With intention to bring as many people to discuss as possible. And pointing to concerns because in general only positives are brought up to wider reception. Which is not good for the final outcome. "I love what you are doing! Let's go!" is a fantastic sign of appropriation - but let's spark some more discussion so we are sure everything has been considered along the way.

Examples:
https://dev.to/this-is-angular/sub-rfc-4-for-angular-signals-sparks-interesting-discussion-started-by-rxjs-author-ben-lesh-9a2
https://dev.to/this-is-angular/signals-sub-rfc-3-new-angular-reactive-approach-or-a-path-to-confusion-1kkm
https://dev.to/this-is-angular/minko-gechev-on-angular-16-17-game-changer-or-loss-of-identity--5lk

Signals are definitely a good change and a way forward. However ... and here starts the rest that was stated in original "essay" - like you named it :). Introducing these changes involves very very detailed planning. And seeing the concerns clearly can help moving forward.

I understand your concerns that all of this might seems like it's closing with a feedback on concerns focusing only on them alone.

Here is why.

In general the feedback is positive, everyone is loving the changes. Problem is saying "I love what you are doing! Let's go!" - it doesn't bring a food for thought. There is like one article about how all of this is great every 3 days. On Twitter everyone is doing little experiments falling in love with new ways. Positives are widely known. And it's good.

Concerns however is something that majority is trying to avoid mentioning, and most likely cannot see. The work done here brings concerns that were hidden here and there and sums it up.

And as I also already stated. Concerns are crucial to make sure that moving forward with adoption has been done with careful consideration of potential downsides and implications.

I also would love to see a summary of everything from Angular Team :).

@timonkrebs

Comment options

Thank you @danielglejzner for your great reply. I think the thing that was lacking for me was:

Signals are definitely a good change and a way forward.

While you mentioned the incredible work done and also appreciation for it. It was not clear to me if you think that signals are a good way forward.

@danielglejzner

Comment options

So here I have stated my personal opinion. Where in the summary I just tried to sum up general concerns trying to stay away with opinion of my own. As I believe that Signals are bringing a lot to the table and in general Signals are a good change - as always the devil is in the details :).

I truly believe, that after evaluating this RFC. Angular team can consider all of the concerns and come up with a good strategy for future adoption that will ensure no harm to the future of the framework and current users.

Comment options

Feels like there is "new way" & "old way" and this is bad for all patterns and guides we follow, haven't seen someone who witch to reactive coding and going back. In a year ago I proposed to switch to Angular and from then we cleared a lot of issues with the code and the codebase goes a lot smaller the app faster and much more pros. We don't have any performance issues because of change detection well if we can do better than we are going to use the better way if there is again well guided way as anything else Angular provide and everyone embrace it. For one I think signals are just Async pipe on steroids for me.

So some smart people will probably do something like, or we can request it from the Angular team to implement.

users$ | signal

You must be logged in to vote

1 reply

@timonkrebs

Comment options

That is a very interesting way to think about signals...

Async pipe on steroid

That probably leads naturally to think about them in a way that they bring the most benefit/least problems. As in this framing using effects would not make sense. And also help with drawing a reasonable boundry between signals and rxjs. It makes clear that they are fundamentally a way to bind to the template.

But I am not so sure about the benefit of: users$ | signal

Comment options

It is always stressful to adapt to new changes in life.

The Vuejs team provides options for writing components (class-based, composition API, script setup). The React team also provides class-based components and hooks. On the other hand, the Angular team is now providing options for writing components, stand-alone signals, rxjs, etc. This is called evolution, caused by improvements in the code. Less is more, they say.

Developers need to get used to the new way of writing Angular apps. Writing modern Vuejs and modern React don't confuse developers anymore. The same thing will happen in the Angular world.

Thanks to the Angular core team and the people contributing to improving the DX of building Angular apps. 👏🏽

You must be logged in to vote

6 replies

@devlinduldulao

Comment options

Do you know if I said that? No. But that's what is going to happen. Five years ago, JavaScript developers wouldn't use TypeScript in projects. But it is different now; most projects are now built in TypeScript. React apps nowadays are created using hooks. Vuejs apps nowadays are built using composition API.

Next, most future Angular apps will be using stand-alone components and signals.

@e-oz

Comment options

I quoted your words. We (developers) will pick what to adopt, not because we “need to get used to” something - I can not care less what you “need to get used to”.

@devlinduldulao

Comment options

Uhm.. Nevertheless, thanks for your sharing your thoughts.

@devlinduldulao

Comment options

@michaelfaith

Comment options

Developers need to get used

Because you said so? No, thanks.

Chill out bro. He was just saying that it's the nature of modern web development, to need to be comfortable with change and it's important to be able to adapt with the changing landscape. Anybody that wasn't trying to pick a fight would know that it wasn't how you framed it.

Comment options

Would anyone here like to share their thoughts about this sample repo that I made? I will start sharing these patterns with others if you think this kind of approach to Angular signals is an improvement with regards to having lesser code but testable code.

  • Global state management using Signals
  • HTTP Requests using Axios and Signals
  • RXJS in ReactiveForms only
  • Stand-alone components all the way
  • LocalStorage in Signals to persist data

https://github.com/webmasterdevlin/modern-angular-course-2023

You must be logged in to vote

3 replies

@michaelfaith

Comment options

This is nice. Thanks for putting it together. Especially like that you went all the way to e2e testing with Playwright. I'm not sure I see the need to move away from the HttpClient though. So, I don't know that I'd personally advocate for that, but it is pretty clean.

I also probably won't be doing inline templates or styles anytime soon. But, again, that's just my preference.

@lifaon74

Comment options

In my opinion, this is not enough. I mean, the work is great, but you barely use Signals. A real application has many complex components, with sometimes hundred of properties. Without providing such an example, we can't detect now the limits of Signals, and may encounter big traps later. This is usually the source of hidden bugs or bad designs: simple examples and tests that can't cover real cases (here I speak of 500K lines apps). They fail to detect defects in API design.

Maybe a good start could be to rewrite some common material components and see how we can use Signals there and if they help. For example, a Pagination or a table which are not extremely complex, but will cover more than the typical provided examples.
We may think too, to a simple game, like a connect four, which will leverage more complexity.

@devlinduldulao

Comment options

Comment options

The Signals RFC is now closed - we've posted a combined summary of the feedback in a separate discussion.

You must be logged in to vote

0 replies