Angular 19 chegou: tudo o que você precisa saber!

Conheça as atualizações e novos recursos do Angular 19 com exemplos práticos de código.

Seguindo a frequência de lançamentos já conhecida pela comunidade, mais um fim de ano está chegando e, com ele, mais uma major version do Angular está disponível. Neste artigo, irei destacar as novidades que mais despertaram meu interesse com base no artigo original do lançamento, em alguns artigos que li e vídeos que assisti (você encontrará as referências/fontes no final).

Introdução

Para quem vem acompanhando os últimos lançamentos, acredito que é possível perceber um claro esforço do Angular em melhorar a qualidade de vida do desenvolvedor (o que chamamos de developer experience) e a performance do framework. Para que isso seja possível - e, ainda mais importante, para que as melhorias sejam assertivas e realmente adotadas pela comunidade -, o time da Google vem analisando como os últimos lançamentos foram vistos (e até julgados) pelos desenvolvedores.

TL;DR

O Angular continua a evoluir em direção a uma experiência de desenvolvimento mais intuitiva, performática e poderosa. O foco agora parece ser, cada vez mais, em funcionalidades que tenham como base o SSR (Server-Side Rendering), pois a versão 19 traz a hidratação incremental e uma configuração de renderização de rotas mais granular. Já os componentes standalone passam a ser o padrão, enquanto ganhamos a possibilidade de declarar variáveis localmente no template. Por fim, podemos destacar o lançamento de melhorias muito aguardadas pela comunidade, como a remoção de imports não utilizados e um novo componente seletor de hora.

Novidades

Hidratação incremental em “preview”

Essa funcionalidade permite ao desenvolvedor dizer ao Angular quais partes do template ele deseja carregar e “hidratar” em momentos específicos - tudo isso utilizando a sintaxe @defer. Veja essa animação retirada do anúncio oficial para entender melhor como isso funciona:

Demonstração da hidratação incremental

Esse vídeo exibe uma página renderizada com SSR (no lado do servidor), na qual três efeitos visuais foram adicionados: 1) os componentes em cinza, indicando que ainda não foram carregados nem hidratados pelo Angular; 2) a animação de “pulsar” que representa o momento em que o Angular está fazendo o download desse componente através da rede; e 3) a borda roxa que indica que o Angular fez o download e hidratou o componente (que já não possui mais a cor cinza).

Controle de renderização de rotas

Quando o SSR é habilitado na aplicação, o comportamento padrão do Angular é renderizar todas as rotas parametrizadas no servidor e pré-renderizar todas as rotas sem parâmetros. Na v19, a nova interface (ServerRoute) disponibilizada vai permitir que, individualmente, o comportamento das rotas seja configurado e determinar se a rota será renderizada no servidor, pré-renderizada ou renderizada no lado do cliente.

export const serverRouteConfig: ServerRoute[] = [
  { path: '/login', mode: RenderMode.Server },
  { path: '/dashboard', mode: RenderMode.Client },
  { path: '/**', mode: RenderMode.Prerender },
];
  • RenderMode.Server: a rota será renderizada no lado do servidor

  • RenderMode.Client: a rota será renderizada no lado do cliente

  • RenderMode.Prerender: a rota será pré-renderizada

Standalone agora é o padrão!

Na verdade, permita-me explicar dois cenários diferentes para que esse título não cause confusão: atualmente, ao criar um novo componente utilizando o Angular CLI (ng g c MeuTexto, por exemplo), esse componente já é criado como standalone. Contudo, antes da versão 19, ao criar um componente sem utilizar a propriedade standalone: true no decorator, esse componente não seria um componente standalone - e aqui entra a grande novidade: a partir da v19, ele é!

Isso quer dizer que na nova versão, esse componente vai ser considerado standalone:

@Component({
  imports: [],
  selector: 'meu-texto',
  template: './meu-texto-component.html',
  // mesmo não possuindo a propriedade, será standalone no Angular 19!
})
export class MeuTextoComponent {…}

E, para criar um componente que não seja standalone, a propriedade standalone deverá ser explicitamente adicionada:

@Component({
  imports: [],
  selector: 'meu-texto',
  template: './meu-texto-component.html',
  standalone: false
})
export class MeuTextoComponent {…}

Ps.: essa regra é aplicada para componentes, diretivas e pipes.

Variáveis locais no template

Com essa nova sintaxe, o Angular simplifica muito o processo de definir e reusar uma variável no template, atendendo uma demanda muito requisitada pela comunidade e permitindo nos livrarmos de alguns workarounds (palavra bonita para gambiarra! 😝) que eram usados. A nova forma trabalha elegantemente com referências e com a async pipe.

<!-- Exemplo com a variável referenciando um elemento -->
<input #nome type="text">
@let texto = 'Olá ' + nome.value;
<span>{{ texto }}</span>

<!-- Exemplo com a async pipe -->
@let usuario = usuario$ | async;
<div>Detalhes do usuário: {{ usuario.nome }}</div>

Identificando imports não utilizados em componentes standalone

A animação abaixo demonstra perfeitamente (com o RouterOutlet) os benefícios desse comportamento. É muito comum que durante a criação das telas, com o uso dos componentes standalone, vários imports sejam feitos - pois são através deles que obtemos todas as “peças” necessárias para montar um componente. Contudo, algum tempo depois pode ser necessário mudar o template daquele componente e existe a chance de um import que antes era obrigatório tornar-se desnecessário. Com essa adição, não precisaremos de nenhuma configuração extra na IDE ou de plug-in, pois a própria Angular CLI indicará isso.

Caso você queira desabilitar essa validação (entendo que pode ser necessário em casos de projetos legados; caso contrário, não faça isso), basta atualizar seu arquivo angular.json:

{
  "angularCompilerOptions": {
    "extendedDiagnostics": {
      "checks": {
        "unusedStandaloneImports": "suppress"
      }
    }
  }
}
💡
Outro detalhe interessante é que, ainda nessa versão, também teremos a validação de funções não invocadas: basicamente, isso irá destacar casos onde uma função é usada para um evento, mas não é chamada - frequentemente devido à falta do uso de parênteses no template. Exemplo: change=”onChange” ao invés de change=”onChange()".

Novo componente "seletor" de hora (time picker)

Como a própria nota de lançamento afirma, um dos pedidos mais populares no GitHub tem sido um “seletor de tempo” para o Angular Material. E, finalmente, ele foi lançado! Veja uma animação do componente na prática e um trecho de código demonstrando uma abordagem mais simples:

<mat-form-field>
  <mat-label>Pick a time</mat-label>
  <input matInput [matTimepicker]="picker">
  <mat-timepicker-toggle matIconSuffix [for]="picker"/>
  <mat-timepicker #picker/>
</mat-form-field>

Conclusão

É claro que estas não são as únicas novidades dessa versão. Temos outras opções interessantíssimas, tais como: as novas primitivas de reatividade introduzidas (linkedSignal e a resource API); diversos novos comandos schematics (que nada mais são do que geradores de código); atualizações na função effect; e muito mais!

Mas eu resolvi destacar aquilo que eu achei legal, misturando game-changers que colocam o Angular em um novo nível (como a hidratação incremental) com coisas simples, mas que melhoram muito nosso dia a dia (como o alerta para imports não utilizados).

Quais novidades você sentiu falta? Teve alguma coisa que você não gostou nessa nova versão ou algum detalhe que você acha que eu deveria ter abordado com mais detalhes? Me deixa saber nos comentários, esse espaço é nosso! 😁👇🏼

Referências

  • Post oficial no blog do Angular (link)

  • Post do Andrew Rosário no Medium (link)

  • Post do Mateusz Dobrowolski no Angular.love (link)

  • Vídeo do Joshua Morony no YouTube (link)

  • Vídeo do Maximilian Schwarzmüller no YouTube (link)

Escrito com 💙 e 🎯 por Manual do Front.