Modern Angular
Standalone sem transformar NgModules em vilões
Standalone muda o default arquitetural, mas não transforma todo NgModule existente em urgência. Componentes são standalone por default desde o Angular v17 e NgModule virou opcional desde a v19. A documentação oficial da migração standalone é explícita: apps existentes podem adotar incrementalmente sem breaking changes.
A pergunta melhor
Em um app Angular maduro, a conversa sobre standalone não deveria começar com 'como removemos todos os módulos?'. Comece com uma pergunta menor: onde mora a fronteira dessa feature hoje, e standalone deixaria essa fronteira mais fácil de ler, carregar e testar?
Componentes Angular já são standalone por default no Angular atual. Isso muda o padrão para código novo. Não significa que uma biblioteca interna estável, uma integração de terceiro ou um feature module legado precise virar reescrita antes do próximo release.
Eu manteria um LegacyPaymentsModule estável se ele encapsula um SDK de terceiro, expõe uma API pública conhecida e não bloqueia lazy loading, ownership ou testes. Isso não é nostalgia; é controle de escopo.
A tabela de decisão
| Situação | Movimento padrão | Evidência necessária |
|---|---|---|
| Rota ou feature nova | Use componentes standalone e providers na rota | Imports explícitos e rota dona da facade da feature. |
| Módulo que só existe para declarations | Migrar quando tocar na área | Build e smoke test da feature passam sem churn amplo de imports. |
| SharedModule com tudo | Quebrar por uso real | Lista de dependências mostra o que cada feature realmente usa. |
| Módulo estável de biblioteca | Manter até existir motivo de release | O módulo ainda expressa API pública ou contrato de terceiro. |
| Wrapper de SDK de terceiro | Manter ou isolar atrás de uma rota | A migração adicionaria risco sem melhorar ownership. |
| Providers globais demais | Mover estado de feature para mais perto da rota | Navegação, reuso e teardown foram entendidos. |
Rota é fronteira melhor que slogan
A migração standalone útil muitas vezes é uma migração de rota. A rota pode carregar um componente sob demanda, escopar providers e mostrar a fronteira da feature sem o time abrir um arquivo de módulo primeiro.
Se todo provider continua em root e todo componente importa um balde compartilhado, o código não ficou muito mais modular. Ele só perdeu uma camada de cerimônia.
export const routes: Routes = [
{
path: 'billing',
providers: [BillingFacade],
loadComponent: () =>
import('./billing/billing-page.component')
.then(m => m.BillingPageComponent),
},
];O que evitar
Evite abrir uma branch de migração cuja única promessa é 'remover NgModules'. Esse tipo de branch toca arquivos demais, cansa review e costuma entregar pouco valor de produto.
O movimento melhor é mais estreito: use standalone como default para código novo, migre módulos que bloqueiam lazy loading ou escondem dependências e deixe módulos estáveis em paz até o time ter motivo para mexer neles.
Artefato para reaproveitar
Regra de adoção standalone
- Use standalone por default em código Angular novo.
- Use rotas como fronteiras de feature, não SharedModule como primeira ferramenta de design.
- Mantenha NgModules quando ainda expressam uma integração estável.
- Migre módulos tocados apenas quando o diff melhora ownership, loading ou review.
Fontes consultadas
- https://angular.dev/guide/components
- https://angular.dev/reference/migrations/standalone
- https://angular.dev/guide/di/dependency-injection-providers
- https://angular.dev/api/router/Route
- https://angular.dev/api/core/inject
- https://blog.angular.dev/announcing-angular-v21-57946c34f14b
Modern Angular Playbook
Este artigo é um play.
O Playbook do Angular Moderno reúne o diagnóstico, a matriz de adoção, onze jogadas e o plano de 30 dias. Grátis, em inglês e português.
Você recebe os dois PDFs por email, pela lista do Dojo IA.
André Ramosdisponível para vagas remotas, UTC−3Entre em contato →