Standalone Components: o Angular sem NgModules
O componente declara as próprias dependências e a burocracia dos NgModules vira opcional: bootstrap por função, lazy loading direto por rota e a migração quase mecânica.
Pergunte a quem tentou aprender Angular antes de 2023 onde travou, e a resposta tem nome: NgModule. Para mostrar um "olá mundo", era preciso entender declarations, imports, exports, providers e por que o componente "não é conhecido" apesar de estar ali do lado. Uma burocracia que existia por razões históricas do compilador, não por necessidade sua.
Standalone components removem essa camada: o componente declara as próprias dependências, e os NgModules viram opcionais. Desde o Angular 17, standalone é o padrão oficial para código novo (angular.dev).
O antes e o depois
// ANTES: o componente e a burocracia em arquivos separados
@Component({ selector: "app-card", templateUrl: "./card.html" })
export class CardComponent {}
@NgModule({
declarations: [CardComponent],
imports: [CommonModule, MatButtonModule],
exports: [CardComponent],
})
export class CardModule {} // só para o de cima funcionar
// DEPOIS: o componente declara o que usa, e acabou
@Component({
selector: "app-card",
imports: [CurrencyPipe, MatButtonModule],
templateUrl: "./card.html",
})
export class CardComponent {}
A mudança parece cosmética e não é: a dependência ficou local e explícita. Olhando o componente, você sabe exatamente do que ele precisa; movê-lo de lugar (ou de projeto) deixa de quebrar um módulo distante. O acoplamento invisível entre "quem declara" e "quem usa" morre.
O aplicativo sem módulos
O bootstrap troca o AppModule por uma chamada de função com providers:
// main.ts
bootstrapApplication(AppComponent, {
providers: [
provideRouter(rotas),
provideHttpClient(),
provideAnimations(),
],
});
E o lazy loading, que antes exigia um módulo por feature, agora aponta direto para componentes:
export const rotas: Routes = [
{
path: "relatorios",
// carrega o código só quando a rota é visitada
loadComponent: () =>
import("./relatorios/relatorios.component").then((m) => m.RelatoriosComponent),
},
{
path: "admin",
loadChildren: () => import("./admin/admin.routes").then((m) => m.ADMIN_ROTAS),
},
];
O carregamento preguiçoso ficou tão barato de declarar que a pergunta certa inverteu: em vez de "o que vale lazy?", "o que precisa mesmo estar no bundle inicial?". Para o LCP, essa inversão vale ouro.

Migrando um app existente (sem drama)
A migração é o raro caso de modernização quase mecânica:
- O schematic oficial faz o grosso:
ng generate @angular/core:standaloneconverte componentes, remove módulos desnecessários e ajusta o bootstrap, em três passadas guiadas. - Convivência total: standalone importa módulo antigo, módulo antigo importa standalone. Nada precisa migrar junto; é a substituição incremental de sempre.
- A ordem que funciona: componentes folha primeiro (os que nada declara além deles), depois as features, por último o shell e o bootstrap.
O que não migrar por reflexo: bibliotecas internas que expõem dezenas de componentes podem manter um NgModule de conveniência para os consumidores; o padrão standalone não proíbe, só desobriga.
O que isso conta sobre a direção do Angular
Standalone não veio sozinho: com Signals, control flow no template (@if, @for) e o caminho zoneless, o Angular está sistematicamente trocando cerimônia por clareza local: menos arquivos de cola, mais componente autocontido. Para times, o efeito prático é onboarding mais rápido e menos "arqueologia de módulo" na revisão de código.
Se o seu app ainda é 100% NgModule, a migração standalone costuma ser o primeiro passo que destrava as outras modernizações, e é um projeto bem definido, de risco baixo, do tipo que executamos no serviço de Desenvolvimento Web, Mobile e Desktop.
Quantos NgModules o seu app tem só para satisfazer o compilador? Rode o schematic num branch e conte o diff, ou descreva seu app para a IA da Rabelo Digital, aqui no canto da tela, e ela estima o esforço. Sem formulário, sem espera.


Deixe um Comentário