Saltar al contenido
< samuelsantana.dev />
Volver al BlogDiagrama: Zone.js verifica cinco componentes (header, cart, sidebar, footer, modal); com signal(), só o cart é atualizado

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

Samuel Santana
Publicado el 07 de julio de 2026(Editado el 25 de julio de 2026)
AngularPerformance

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:
  1. signal(): O estado mutável básico.
  2. computed(): Estado derivado puro. Ele só é recalculado se os Signals dos quais depende mudarem, e o valor é guardado em cache (memoizado).
  3. 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 com effect() 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...