
O Renascimento do Angular: Signals e a Nova Abordagem HTTP
Estás leyendo la versión en portugués de este artículo. Léelo en Español
Se você acompanha o ecossistema Angular de perto, sabe que o framework está passando pelo seu maior renascimento desde a reescrita do AngularJS para o Angular 2. Com a chegada das versões 16 e 17, e a consolidação nas versões mais recentes (18 a 22), o Google mudou as regras do jogo.
O foco agora é claro: Developer Experience (DX), performance e menos boilerplate. E no centro dessa mudança estão duas peças fundamentais: os Signals e a modernização do HttpClient.
Neste artigo, vamos dissecar como essas ferramentas mudam a forma como arquitetamos aplicações escaláveis.
O que são Signals e por que você deveria se importar?
Durante anos, o Angular confiou no Zone.js para detectar mudanças. O problema? O Zone.js é uma "marreta". Ele intercepta eventos assíncronos (cliques, timeouts, requisições HTTP) e, na dúvida, verifica a árvore de componentes inteira para ver se algo mudou — ao menos os componentes com a estratégia Default (hoje Eager); os OnPush são pulados quando não foram marcados. Em aplicações complexas, como plataformas SaaS multi-tenant com painéis de dados densos, isso gera gargalos de performance.
Os Signals trazem a reatividade de grão fino (fine-grained reactivity). Um Signal é um wrapper ao redor de um valor que notifica os consumidores apenas quando esse valor realmente muda. O framework passa a saber quais componentes leem aquele Signal e marca só esses para atualização, sem depender do Zone.js para descobrir que algo mudou.
Os 3 Pilares dos Signals:
signal(): O estado mutável básico.computed(): Estado derivado puro. Ele só é recalculado se os Signals dos quais depende mudarem, e o valor é guardado em cache (memoizado).effect(): Efeitos colaterais (como salvar no localStorage ou sincronizar uma biblioteca imperativa; para mexer no DOM depois da renderização, a API indicada éafterRenderEffect()) que rodam automaticamente quando suas dependências mudam.
Exemplo prático de uso:
import { Component, signal, computed, effect } from '@angular/core';
import { CurrencyPipe } from '@angular/common';
@Component({
selector: 'app-cart',
imports: [CurrencyPipe],
standalone: true,
template: `
<div>
<p>Quantidade: {{ quantity() }}</p>
<p>Preço Total: {{ totalPrice() | currency }}</p>
<button (click)="increment()">Adicionar Item</button>
</div>
`
})
export class CartComponent {
// Estado básico
quantity = signal(1);
unitPrice = 50.00;
// Estado derivado (só recalcula quando quantity mudar)
totalPrice = computed(() => this.quantity() * this.unitPrice);
constructor() {
// Efeito colateral focado em observabilidade ou debug
effect(() => {
console.log(`O valor do carrinho mudou para: ${this.totalPrice()}`);
});
}
increment() {
this.quantity.update(q => q + 1);
}
}
Casos de Uso e Vantagens
- Vantagem: Previsibilidade e performance. Mas não é o fim do
ExpressionChangedAfterItHasBeenCheckedError: a própria documentação avisa que propagar estado comeffect()ainda pode dispará-lo. - Casos de Uso: Gerenciamento de estado local complexo, formulários dinâmicos e interfaces de alta interatividade (como dashboards em tempo real).
A Nova Abordagem HTTP: Adeus Módulos, Olá Fetch API
Junto com a reatividade, a forma como o Angular lida com injeção de dependências e requisições de rede evoluiu. O antigo HttpClientModule está sendo deixado para trás na era dos Standalone Components.
A partir do Angular 15 (e consolidado como padrão no 17+), a recomendação é utilizar o provideHttpClient(). Mais do que uma mudança de sintaxe, essa nova API trouxe o withFetch().
O poder do withFetch()
Historicamente, o HttpClient usava a API XMLHttpRequest por baixo dos panos. Ao habilitar o withFetch() (do Angular 16.1 ao 21), o Angular passa a usar a Fetch API nativa. No Angular 22, o fetch virou o backend padrão e o withFetch() foi descontinuado: provideHttpClient() já basta, e withXhr() existe para quem precisa de progresso de upload, que a Fetch API não reporta. Em Server-Side Rendering (SSR) ou Static Site Generation (SSG), use o fetch: o suporte a XHR no servidor está descontinuado.
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient, withFetch } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(withFetch()) // Angular 16.1–21; no 22+, basta provideHttpClient()
]
};
Unindo os Dois Mundos: RxJS vs Signals
A pergunta que todo recrutador técnico ou Tech Lead faz hoje é: "Os Signals vão matar o RxJS?"
A resposta de um engenheiro sênior é: Não. Eles resolvem problemas diferentes.
O RxJS é excepcional para lidar com eventos assíncronos ao longo do tempo (como debouncing de inputs ou WebSockets). Já os Signals são perfeitos para estado síncrono. A beleza do Angular moderno está na interoperabilidade. Com o pacote @angular/core/rxjs-interop, podemos fazer requisições HTTP (que retornam Observables) e transformá-las em Signals de forma elegante com o toSignal:
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { toSignal } from '@angular/core/rxjs-interop';
interface User {
id: number;
name: string;
}
@Component({
selector: 'app-user-profile',
standalone: true,
template: `
@if (user(); as user) {
<h1>{{ user.name }}</h1>
} @else {
<p>Carregando...</p>
}
`
})
export class UserProfileComponent {
private http = inject(HttpClient);
// Transforma o Observable da requisição HTTP diretamente em um Signal
user = toSignal(this.http.get<User>('/api/user/1'));
}
Nota: A nova sintaxe de Control Flow (@if, @for) do Angular 17+ combina perfeitamente com Signals.
Para leituras reativas como esta, o Angular 22 estabilizou o httpResource() (de @angular/common/http): ele faz a requisição pelo próprio HttpClient (interceptors incluídos), expõe value(), isLoading() e error() como Signals e cancela a requisição pendente quando a URL reativa muda. Para mutações (POST, PUT), a documentação recomenda continuar usando o HttpClient diretamente.
Conclusão
A engenharia de software é sobre adotar os padrões corretos para resolver gargalos de escala. A migração mental para os Signals e o uso do novo HttpClient com Fetch API não são apenas "hype". São ferramentas tangíveis que reduzem a carga cognitiva do desenvolvedor e, com o modo zoneless (padrão desde o Angular 21), tiram o Zone.js do bundle e cortam ciclos de detecção de mudanças desnecessários.
Comentarios
Cargando comentarios...