💻 Exemplos: Capítulo 01: Ecossistema Angular 18, Angular CLI e Standalone Architecture
Especialização em Front-End com Angular • Demonstrações Práticas Compiláveis
💻 Código de Exemplo 01 — Standalone Architecture e Bootstrap com Angular 18+
Este exemplo demonstra a criação e inicialização canônica de uma aplicação corporativa em Angular 18/19 baseada 100% em Standalone Architecture (eliminando a necessidade de NgModule), com configuração moderna de providers via bootstrapApplication.
1. Ponto de Entrada da Aplicação: src/main.ts
// src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter, withComponentInputBinding } from '@angular/router';
import { provideHttpClient, withFetch } from '@angular/common/http';
import { AppComponent } from './app/app.component';
import { appRoutes } from './app/app.routes';
bootstrapApplication(AppComponent, {
providers: [
// Roteamento moderno com injeção de parâmetros direto nas inputs
provideRouter(appRoutes, withComponentInputBinding()),
// Cliente HTTP nativo com API Fetch para alta performance e suporte a SSR
provideHttpClient(withFetch())
]
}).catch((err) => console.error('[Bootstrap Error] Falha ao inicializar o Angular:', err));
2. Componente Raiz Standalone: src/app/app.component.ts
// src/app/app.component.ts
import { Component, signal } from '@angular/core';
import { RouterOutlet, RouterLink } from '@angular/router';
import { CommonModule } from '@angular/common';
interface ClusterNode {
id: string;
name: string;
region: string;
status: 'HEALTHY' | 'DEGRADED' | 'DOWN';
activePods: number;
}
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, RouterOutlet, RouterLink],
template: `
<div class="min-h-screen bg-slate-100 flex flex-col font-sans">
<!-- Barra Superior de Navegação -->
<header class="bg-white border-b px-6 py-4 flex items-center justify-between shadow-sm">
<div class="flex items-center gap-3">
<span class="w-3.5 h-3.5 rounded-full bg-red-600 animate-pulse"></span>
<h1 class="font-extrabold text-xl text-slate-900 tracking-tight">
Angular 18 Enterprise • Standalone Architecture
</h1>
</div>
<div class="flex items-center gap-2">
<span class="text-xs px-2.5 py-1 bg-slate-100 rounded-md font-mono text-slate-600">
Ambiente: <strong>Production-Edge</strong>
</span>
<button
type="button"
(click)="simulateHealthCheck()"
class="text-xs font-semibold px-3 py-1.5 bg-red-600 hover:bg-red-700 text-white rounded-lg transition-colors"
>
Executar Health Check
</button>
</div>
</header>
<!-- Painel de Telemetria do Cluster -->
<main class="flex-1 max-w-5xl w-full mx-auto p-6 space-y-6">
<div class="bg-white border rounded-2xl p-6 shadow-sm space-y-4">
<div class="flex items-center justify-between">
<div>
<h2 class="text-lg font-bold text-slate-800">Cluster de Microsserviços</h2>
<p class="text-xs text-slate-500">Arquitetura sem NgModule compilada via esbuild/Vite</p>
</div>
<span class="text-xs font-bold text-slate-400 font-mono">
Total de Nós: {{ nodes().length }}
</span>
</div>
<!-- Grade de Nós -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div
*ngFor="let node of nodes()"
class="border rounded-xl p-4 bg-slate-50 space-y-2 hover:border-slate-300 transition-colors"
>
<div class="flex items-center justify-between">
<span class="text-xs font-mono font-bold text-slate-700">{{ node.id }}</span>
<span
class="text-[10px] font-extrabold uppercase px-2 py-0.5 rounded-full"
[ngClass]="{
'bg-emerald-100 text-emerald-800': node.status === 'HEALTHY',
'bg-amber-100 text-amber-800': node.status === 'DEGRADED',
'bg-red-100 text-red-800': node.status === 'DOWN'
}"
>
{{ node.status }}
</span>
</div>
<h3 class="font-bold text-slate-900 text-sm">{{ node.name }}</h3>
<div class="flex justify-between items-center text-xs text-slate-500 pt-1 border-t">
<span>Região: {{ node.region }}</span>
<span class="font-mono font-bold text-slate-700">{{ node.activePods }} pods</span>
</div>
</div>
</div>
</div>
<router-outlet></router-outlet>
</main>
</div>
`
})
export class AppComponent {
// Estado local gerenciado com Angular Signals nativo
nodes = signal<ClusterNode[]>([
{ id: 'node-us-01', name: 'Auth & Security Gateway', region: 'us-east-1', status: 'HEALTHY', activePods: 24 },
{ id: 'node-sa-02', name: 'Transactional Payment Core', region: 'sa-east-1', status: 'HEALTHY', activePods: 42 },
{ id: 'node-eu-03', name: 'Audit & Compliance Collector', region: 'eu-west-1', status: 'DEGRADED', activePods: 18 }
]);
simulateHealthCheck(): void {
const updated = this.nodes().map((node) => ({
...node,
status: Math.random() > 0.15 ? ('HEALTHY' as const) : ('DEGRADED' as const),
activePods: Math.floor(Math.random() * 30) + 15
}));
this.nodes.set(updated);
}
}
3. Rotas Básicas: src/app/app.routes.ts
// src/app/app.routes.ts
import { Routes } from '@angular/router';
export const appRoutes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: 'overview'
},
{
path: 'overview',
loadComponent: () =>
import('./pages/overview/overview.component').then((m) => m.OverviewComponent)
}
];
🖥️ Saída / Comportamento Esperado
Ao inicializar via Angular CLI (ng serve):
Application bundle generation complete. [0.428 seconds]
Watch mode enabled. Ready for changes...
➜ Local: http://localhost:4200/
Estado Inicial:
Header: "Angular 18 Enterprise • Standalone Architecture"
Painel com 3 cards:
Card 1: node-us-01 | [HEALTHY] verde | 24 pods
Card 2: node-sa-02 | [HEALTHY] verde | 42 pods
Card 3: node-eu-03 | [DEGRADED] âmbar | 18 pods
Ao clicar no botão "Executar Health Check":
O método simulateHealthCheck() muta o signal nodes.set(...).
Os status e números de pods são atualizados reativamente sem necessidade de Zone.js forçar verificação pesada.
🔍 Destaques da Implementação
standalone: truecomo Padrão: Não há arquivosapp.module.ts; cada componente declara suas dependências pontuais emimports: [...].bootstrapApplication: Inicializa o runtime com providers funcionais (provideRouter,provideHttpClient), diminuindo o bundle inicial do esbuild.withFetch(): Ativa a API Fetch nativa do navegador noHttpClient, garantindo compatibilidade imediata com Cloudflare Workers e Node SSR.