O AngularJS já chegou ao fim de sua vida útil: sem patches de segurança, sem atualizações de dependências e com um número cada vez menor de desenvolvedores que o conhecem. Continuar a manter um aplicativo AngularJS em produção significa acumular risco de segurança, dívida técnica e custo de contratação. Este guia cobre toda a jornada para o Angular moderno: auditoria de código legado, escolha entre big bang e migração incremental de padrão estrangulador, bootstrap híbrido com ngUpgrade, mapeamento de conceito direto (controlador, diretiva, $http, roteamento, autenticação), testes, desempenho e um plano operacional de 30/60/90 dias com KPIs mensuráveis.
Por que migrar de AngularJS para Angular
O salto de AngularJS para Angular não é uma simples atualização de versão: é uma mudança de paradigma, de uma estrutura baseada em ligação de dados bidirecional e $scope para um modelo components com injeção de dependência digitada, alteração de detecção otimizada e Compilação AOT. Os benefícios são mensuráveis - pacotes menores graças ao TypeScript de ponta a ponta, um ecossistema mantido ativamente - mas devem ser equilibrados com o risco real de uma migração mal planejada: regressões funcionais, equipe paralisada por meses, lançamentos de recursos congelados.
Resumo dos benefícios e riscos
| Benefícios da migração | Riscos a serem gerenciados |
|---|---|
| Desempenho superior (detecção de alterações, AOT, trepidação de árvores) | Regressões funcionais em recursos legados não testados |
| TypeScript de ponta a ponta, menos bugs em tempo de execução | Custo inicial alto sem liberação imediata de valor |
| Ecossistema mantido, segurança atualizada | Equipe aprendendo novo paradigma sob pressão |
| Mais fácil de encontrar desenvolvedores no mercado | Código híbrido temporário mais complexo para depurar |
Avaliação inicial: auditoria de código AngularJS
Antes de escrever uma linha de Angular, você precisa mapear com precisão o que está migrando. Uma auditoria superficial é a causa mais comum de estimativas incorretas e de migrações que ficam presas no meio do caminho. A auditoria deve responder a três perguntas: quão grande é o código, quão acoplado ele é internamente e quais dependências externas estão envolvidas.
Lista de verificação de auditoria operacional
- Module Inventory: Lista cada módulo AngularJS (
angular.module(...)) e suas dependências declaradas. - Controller/directive/service count: Use
grep -rn "\.controller(\|\.directive(\|\.factory(\|\.service(" src/) para uma contagem rápida e objetiva. - Mapa de $scopes compartilhados - Identifique o uso de
$rootScopepor estado global — quase sempre o ponto ideal para migrar para serviços Angular. - Dependências específicas do AngularJS:
angular-ui-router,angular-translate,restangularnão têm equivalente direto e devem ser substituído, não traduzido linha por linha. - Cobertura de teste existente: Sem teste, cada refatoração é um salto no escuro; meça a cobertura atual antes de começar.
- Classificação por criticidade: divida os recursos em "negócio principal" (alto risco, migração por último, com mais testes) e "periférico" (bom ponto de partida).
Estratégia de migração: big bang vs incremental (padrão estrangulador)
Existem duas abordagens principais. O big bang reescreve todo o aplicativo em Angular antes de lançar qualquer coisa: arriscado em aplicativos grandes, mas mais fácil de raciocinar em projetos pequenos. O padrão strangler (incremental) permite que AngularJS e Angular coexistam no mesmo aplicativo via ngUpgrade, migrando um recurso por vez e liberando continuamente: mais lento no curto prazo, mas reduz drasticamente o risco e permite que o negócio continue a receber valor durante a migração.
Como escolher a abordagem certa
| Critério | Big bang | Padrão estrangulador (incremental) |
|---|---|---|
| Tamanho do aplicativo | Pequeno/médio (<50 componentes) | Grande, empresarial |
| Tolerância ao risco comercial | Alta (a liberação pode ser bloqueada) | Baixa (continuidade necessária) |
| Equipe disponível | Dedicada em tempo integral à migração | Dividida entre novos recursos e migração |
| Cobertura de teste existente | Não crítico | Fortemente recomendado |
Para a maioria dos aplicativos empresariais do mundo real, o padrãostrangler é a escolha correta: ele permite validar cada módulo migrado para produção antes de prosseguir com o próximo.
Configuração do ambiente de desenvolvimento
Antes de iniciar a refatoração, você precisa das ferramentas certas instaladas e configuradas corretamente, incluindo o pacote @angular/upgrade que permite a interoperabilidade entre as duas estruturas.
Lista de verificação de ferramentas necessárias
# Verifica versioni installate
node -v # Node 20.x LTS o superiore
npm -v
# Installa Angular CLI globalmente
npm install -g @angular/cli
# Crea il progetto Angular che ospiterà il bootstrap ibrido
ng new my-app --routing --style=scss
cd my-app
# Installa il modulo di interoperabilità con AngularJS
npm install @angular/upgrade
# Installa AngularJS stesso come dipendenza (per il periodo ibrido)
npm install angular@1.8.3
Refator e mapeamento de conceito: de AngularJS para Angular
A parte mais delicada da migração é traduzir corretamente os conceitos arquitetônicos. Cada construção AngularJS tem um equivalente Angular conceitualmente próximo, mas com semântica e ciclo de vida diferentes.
Tabela de mapeamento de conceito
| AngularJS | Angular Moderno |
|---|---|
$scope | Propriedades da classe de componente (this) |
$rootScope para estado global | Service @Injetável({ fornecidoIn: 'root' }) com BehaviorSubject ou sinal |
.controller() | Classe de componente com @Component() |
.directive() | Componente ou Diretiva (@Directive()) dependendo se possui um modelo |
.factory() / .service() | Classe com @Injetável(), injetado via construtor |
$http | HttpClient (RxJS observável em vez de promessa) |
$route / ui-router | RouterModule com rota independente ou carregado lentamente |
Encadernação =, @, & | @Input(), @Output() com Emissor de Evento |
Snippet 1–2: Controlador → Componente
// AngularJS — controller
angular.module('app').controller('UserListController', function($scope, UserService) {
$scope.users = [];
$scope.loading = false;
$scope.loadUsers = function() {
$scope.loading = true;
UserService.getAll().then(function(res) {
$scope.users = res.data;
$scope.loading = false;
});
};
$scope.loadUsers();
});
// Angular — component equivalente
@Component({
selector: 'app-user-list',
standalone: true,
templateUrl: './user-list.component.html',
})
export class UserListComponent implements OnInit {
users: User[] = [];
loading = false;
constructor(private userService: UserService) {}
ngOnInit(): void {
this.loadUsers();
}
loadUsers(): void {
this.loading = true;
this.userService.getAll().subscribe((users) => {
this.users = users;
this.loading = false;
});
}
}
Snippet 3–4: Diretiva Complexa → Componente
// AngularJS — directive con isolate scope
angular.module('app').directive('userCard', function() {
return {
restrict: 'E',
scope: { user: '=', onSelect: '&' },
template: '<div class="card" ng-click="onSelect({user: user})">{{user.name}}</div>',
};
});
// Angular — component con Input/Output
@Component({
selector: 'app-user-card',
standalone: true,
template: `<div class="card" (click)="select.emit(user)">{{ user.name }}</div>`,
})
export class UserCardComponent {
@Input({ required: true }) user!: User;
@Output() select = new EventEmitter<User>();
}
Snippet 5–6: Serviço AngularJS → Serviço Angular com DI
// AngularJS — factory
angular.module('app').factory('UserService', function($http) {
return {
getAll: function() {
return $http.get('/api/users');
},
};
});
// Angular — servizio con HttpClient e DI
@Injectable({ providedIn: 'root' })
export class UserService {
constructor(private http: HttpClient) {}
getAll(): Observable<User[]> {
return this.http.get<User[]>('/api/users');
}
}
Snippet 7–8: Roteamento e chamadas HTTP
// AngularJS — ui-router
$stateProvider.state('users.detail', {
url: '/users/:id',
template: '<user-detail user-id="$resolve.userId"></user-detail>',
resolve: {
userId: ['$stateParams', function($stateParams) { return $stateParams.id; }],
},
});
// Angular — Router standalone con lazy loading
export const routes: Routes = [
{
path: 'users/:id',
loadComponent: () =>
import('./user-detail/user-detail.component').then((m) => m.UserDetailComponent),
},
];
// Nel component: lettura del parametro via ActivatedRoute
export class UserDetailComponent implements OnInit {
userId = signal<string | null>(null);
constructor(private route: ActivatedRoute) {}
ngOnInit(): void {
this.userId.set(this.route.snapshot.paramMap.get('id'));
}
}
Autenticação e gerenciamento de estado
O fluxo de autenticação precisa ser repensado, não apenas traduzido. No AngularJS é comum manipular o token em $rootScope com um interceptor em $http; em Angular, o padrão correto é um AuthService centralizado com estado reativo (BehaviorSubject ou sinal) e um HttpInterceptorFn.
Migração de fluxo de autenticação
// auth.service.ts
@Injectable({ providedIn: 'root' })
export class AuthService {
private tokenSignal = signal<string | null>(localStorage.getItem('access_token'));
readonly isAuthenticated = computed(() => !!this.tokenSignal());
constructor(private http: HttpClient) {}
login(credentials: LoginPayload): Observable<AuthTokens> {
return this.http.post<AuthTokens>('/api/auth/login', credentials).pipe(
tap((tokens) => this.setTokens(tokens)),
);
}
refresh(): Observable<AuthTokens> {
return this.http.post<AuthTokens>('/api/auth/refresh', {}).pipe(
tap((tokens) => this.setTokens(tokens)),
);
}
private setTokens(tokens: AuthTokens): void {
localStorage.setItem('access_token', tokens.accessToken);
this.tokenSignal.set(tokens.accessToken);
}
}
// auth.interceptor.ts — funzione, non più basata su $http config
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = localStorage.getItem('access_token');
const cloned = token ? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }) : req;
return next(cloned);
};
Para um gerenciamento de estado mais amplo (não apenas autenticação), em aplicativos corporativos complexos, é melhor avaliar NgRx, que oferece um armazenamento centralizado previsível; na maioria dos casos, porém, serviços com BehaviorSubject ou sinal são suficientes e muito mais fáceis de manter do que introduzir um padrão inteiro semelhante ao Redux.
Integração progressiva com ngUpgrade
ngUpgrade é o pacote oficial que permite que um AngularJS e um aplicativo Angular sejam executados na mesma página, ao mesmo tempo, compartilhando serviços e comunicando-se entre componentes. É o coração técnico do padrão estrangulador.
Bootstrap híbrido: exemplo prático
// main.ts — bootstrap ibrido con downgradeModule
import { setUpLocationSync } from '@angular/upgrade/static';
import { UpgradeModule } from '@angular/upgrade/static';
@NgModule({
imports: [BrowserModule, UpgradeModule, AppRoutingModule],
declarations: [UserCardComponent],
})
export class AppModule {
constructor(private upgrade: UpgradeModule) {}
ngDoBootstrap(): void {
this.upgrade.bootstrap(document.body, ['legacyApp']);
setUpLocationSync(this.upgrade);
}
}
// Espone il component Angular come directive AngularJS,
// utilizzabile nei template AngularJS esistenti senza riscriverli
angular
.module('legacyApp')
.directive('appUserCard', downgradeComponent({ component: UserCardComponent }));
// Espone un servizio AngularJS ad Angular, per riuso durante la transizione
angular.module('legacyApp').factory('legacyUserService', downgradeInjectable(UserService));
Com esta configuração, um modelo AngularJS existente pode usar sem modificação, enquanto novos componentes Angular podem injetar serviços AngularJS legados via upgradeInjectable, até que eles também sejam migrados.
Testes durante a migração
O código híbrido é por natureza mais frágil para testar: duas estruturas, dois ciclos de resumo/detecção de alterações, dois executores de teste diferentes coexistem por meses. A estratégia correta é manter Karma/Jasmine no código AngularJS ainda não migrado, introduzir Jest para cada novo componente Angular (modo de observação melhor e mais rápido) e substituir gradualmente Protractor por (obsoleto) Cypress para E2E, que não depende da estrutura subjacente e testa o aplicativo conforme o usuário o vê.
Testes de lista de verificação
- Não remova os testes AngularJS existentes até que o módulo correspondente seja totalmente migrado.
- Cada novo componente Angular requer testes de unidade antes ele é vinculado via
ngUpgrade, não depois. - Cypress E2Es devem cobrir fluxos críticos de ponta a ponta, atravessando páginas AngularJS e Angular durante o período híbrido.
- Monitore a cobertura geral a cada sprint: ela nunca deve cair abaixo do nível pré-migração.
Otimização de desempenho e pacote
Durante o período híbrido, o pacote cresce inevitavelmente, porque contém AngularJS e Angular. É fundamental monitorar esse crescimento e planejar a remoção do AngularJS assim que o último módulo for migrado.
Lista de verificação de desempenho
- Carregamento lento agressivo em cada rota Angular com
loadComponent/loadChildren, para não carregar todo o novo código antecipadamente. - Compilação AOT sempre ativo na produção (
ng buildusa-o por padrão na CLI moderna). - Bundle analyzer executado em cada marco de migração, para verificar se o AngularJS foi realmente removido no final da jornada e não permanece "morto" no pacote.
- Carregamento diferencial: Angular CLI gera automaticamente pacotes diferenciados para navegadores modernos/legados quando necessário.
- Remova
angular(1.x) depackage.jsone de cada importação assim que o último módulo AngularJS for migrado - esta é a etapa mais frequentemente esquecida.
Implantação, CI/CD e estratégia de reversão
Cada módulo migrado deve ser lançado atrás de um sinalizador de recurso, para poder retornar instantaneamente à versão AngularJS em caso de regressão crítica, sem uma reversão completa da implantação.
Sinalizadores de recursos e reversão: exemplo
// Semplice feature flag basato su configurazione remota
if (this.featureFlags.isEnabled('new-user-list-angular')) {
this.router.navigate(['/users']); // route Angular
} else {
window.location.href = '/legacy/users'; // route AngularJS esistente
}
O pipeline de CI/CD deve executar, para cada solicitação pull: construção de produção, suíte Jest/Karma, suíte Cypress em fluxos críticos e uma verificação automática do tamanho do pacote com limite máximo - um aumento anormal do pacote geralmente é o primeiro sinal de uma dependência esquecida do AngularJS.
5 miniguias práticos prontos para publicação
Mini-guia 1 — Converta um controlador AngularJS em um componente Angular
H1: Do controlador AngularJS ao componente Angular: guia passo a passo
Introdução: O controlador é o primeiro tijolo a migrar em cada módulo: a conversão em um componente sempre segue o mesmo padrão repetível.
Snippet (40-60 palavras): Um controlador AngularJS com $scope torna-se uma classe de componente Angular: as propriedades em $scope tornam-se propriedades da classe, os métodos permanecem métodos e a inicialização que aconteceu em o controlador final se move para ngOnInit(). Dependências injetadas por meio de parâmetros de função tornam-se parâmetros de construtor digitados.
Estrutura: H2 "Identificar o escopo do controlador" → H3 "Listar propriedades e métodos"; H2 "Criar classe de componente" → H3 "Mover lógica de inicialização"; H2 "Atualizar o modelo".
Perguntas frequentes: "Você precisa migrar o modelo junto com o controlador?" → "Sim, sempre juntos: alterações de sintaxe de ligação (ng-click → (clique))." · "Posso sair do $scope temporariamente?" → "Não, não existe em Angular: deve ser removido contextualmente."
Mini-guia 2 — Migrar uma diretiva complexa para um componente Angular
H1: Migrar uma diretiva AngularJS com escopo isolado para o componente Angular
Intro: As diretivas com escopo isolado e vinculação =/@/& são o caso mais comum e mapeiam quase 1:1 em Entrada/Saída.
Snippet (40-60 palavras): Uma ligação = (bidirecional) torna-se um @Input() combinado, se necessário, com @Output() para notificar o pai; uma ligação (função) & torna-se diretamente um @Output() com EventEmitter. O template da diretiva se torna o template/templateUrl do novo componente Angular.
Estrutura: H2 "Analisar ligações de diretivas" → H3 "Mapear =, @, & para entrada/saída"; H2 "Criar componente" → H3 "Lidar com restrição: 'E' vs 'A'"; H2 "Atualizar usos em modelos".
Perguntas frequentes curtas: "O que acontece com a restrição: 'A' (diretiva de atributo)?" → "Torne-se um @Directive() Angular sem modelo." · "As ligações bidirecionais ainda são suportadas?" → "Sim, via convenção [(valor)] com Entrada+Saída acoplada."
Mini-guia 3 — Integrando ngUpgrade para um bootstrap híbrido
H1: AngularJS + bootstrap híbrido Angular com ngUpgrade
Introdução: O bootstrap híbrido é a etapa habilitadora para toda a estratégia incremental: sem ele, toda migração é forçosamente um big bang.
Snippet (40-60 palavras): UpgradeModule.bootstrap() inicia ambas as estruturas na mesma página; downgradeComponent torna um componente Angular utilizável em modelos AngularJS, upgradeComponent faz o oposto. downgradeInjectable/upgradeInjectable compartilham serviços entre os dois mundos, permitindo a reutilização imediata sem duplicação de lógica.
Estrutura: H2 "Instalar @angular/atualização" → H3 "Configurar ngDoBootstrap"; H2 "Expor componentes Angular ao AngularJS" → H3 "downgradeComponent na prática"; H2 "Compartilhar serviços entre as duas estruturas".
Perguntas frequentes curtas: "o ngUpgrade está deixando o aplicativo lento?" → "Um pouco, para dupla detecção de alterações: é um custo temporário, não permanente." · "Quanto tempo pode durar a fase híbrida?" → "Algumas semanas a vários meses, dependendo do tamanho do aplicativo."
Mini-guia 4 — Migrar roteamento do roteador ui para o roteador Angular
H1: Do roteador ui para o roteador Angular: Guia de migração de roteamento
Introdução: O roteamento geralmente é a última peça a ser migrada, pois afeta toda a estrutura de navegação do aplicativo.
Snippet (40-60 palavras): Cada state do ui-router se torna um Route Angular: url se torna path, template/controller tornam-se component (ou loadComponent para carregamento lento) e o resolve torne-se resolve Baseado em serviço Angular com Resolve ou simplesmente leia o componente via ActivatedRoute.
Estrutura: H2 "Mapear estados existentes" → H3 "url → caminho, resolver → Resolver"; H2 "Configurar rotas com carregamento lento" → H3 "loadComponent vs loadChildren"; H2 "Gerenciar coexistência com setUpLocationSync".
Perguntas frequentes curtas: "Os dois roteadores podem coexistir?" → "Sim, temporariamente, com setUpLocationSync para sincronizar o URL." · "O que eu uso em vez dos estados aninhados do roteador ui?" → "Rotas angulares aninhadas com rotas secundárias e ."
Mini-guia 5 — Implementar autenticação JWT e token de atualização durante a migração
H1: Autenticação JWT com token de atualização durante a migração AngularJS → Angular
Introdução: O fluxo de autenticação deve funcionar de forma idêntica em páginas ainda AngularJS e já Angular, compartilhando o mesmo token.
Snippet (40-60 palavras): Centraliza o token em localStorage (ou cookie httpOnly, preferível por segurança), lido pelo interceptador $http AngularJS e de HttpInterceptorFn Angular. Um AuthService Angular exposto ao AngularJS via downgradeInjectable evita a duplicação da lógica de login/atualização nas duas estruturas durante o período híbrido.
Estrutura: H2 "Centralizar gerenciamento de token" → H3 "localStorage vs cookies httpOnly"; H2 “Compartilhar o AuthService entre os dois frameworks” → H3 “downgradeInjectable na prática”; H2 "Gerenciar atualização automática em 401".
Perguntas frequentes curtas: "Preciso duplicar o login em ambas as estruturas?" → "Não, um único Angular AuthService compartilhado via downgradeInjectable é suficiente." · "Como faço para sair de um token expirado?" → "Intercepte 401s em ambos os interceptores e redirecione para login centralizado."
Estudo de caso: Migração de um aplicativo corporativo
Um caso típico: aplicativo de gerenciamento AngularJS com 340 controladores, 85 diretivas personalizadas e 6 anos de desenvolvimento incremental. Com uma abordagem de padrão estrangulador em equipes de 4 desenvolvedores, a migração durou 9 meses, com lançamentos semanais contínuos durante todo o período. Resultados medidos no final do projeto: pacote inicial reduzido em 38% (de 2,4 MB para 1,5 MB gzip) após a remoção completa do AngularJS, tempo de carregamento (tempo para interativo) melhorado em 44%, cobertura de teste passou de 22% para 68% graças aos novos testes introduzidos ao mesmo tempo que cada componente migrado. Esforço estimado: aproximadamente 1.400 pessoas/horas total, dos quais 60% concentrados nos principais módulos de negócios migrados na segunda metade do projeto.
Perguntas frequentes
Quanto tempo leva uma migração de AngularJS para Angular?
Varia de algumas semanas para aplicativos pequenos a mais de um ano para aplicativos empresariais de grande porte; o padrão estrangulador permite distribuir o esforço em vários sprints sem bloquear as liberações.
Preciso usar o ngUpgrade?
Não, somente se você escolher a abordagem incremental. Com o big bang não há necessidade, porque não há período de coexistência entre os dois quadros.
O NgRx é obrigatório após a migração?
No: Para a maioria das aplicações, serviços com BehaviorSubject ou sinal são suficientes; NgRx é adequado apenas para estados muito complexos compartilhados entre muitos recursos.
Posso migrar apenas algumas páginas e deixar as outras em AngularJS a longo prazo?
Tecnicamente sim com ngUpgrade, mas não é recomendado como estado permanente: aumenta a complexidade da manutenção e o pacote permanece mais pesado do que o necessário.
Como lidar com bibliotecas de terceiros específicas do AngularJS?
Eles devem ser substituídos pelo equivalente Angular ou por uma biblioteca independente de estrutura; não há tradução automática para bibliotecas como restangular ou angular-translate.
O transferidor ainda pode ser usado para testes E2E?
Está obsoleto pela equipe Angular: para novos projetos ou migrações recomendamos o Cypress, que não depende do framework e testa o aplicativo como um usuário real faria.
Qual é a diferença entre downgradeComponent e upgradeComponent?
downgradeComponent torna um componente Angular utilizável em um modelo AngularJS; upgradeComponent faz a operação inversa, para reutilizar temporariamente os componentes AngularJS em Angular.
Quando é melhor escolher o big bang em vez do padrão estrangulador?
Em aplicativos de pequeno a médio porte, com uma equipe dedicada em tempo integral e tolerância ao risco de negócios, onde o bloqueio temporário de versões é aceitável.
Como evito que o pacote cresça muito durante a fase híbrida?
Monitore o tamanho do pacote em cada marco com um analisador de pacote e agende explicitamente a remoção do AngularJS assim que o último módulo for migrado.
Você precisa reescrever todos os testes durante a migração?
Não: Os testes AngularJS existentes permanecem válidos até que o módulo correspondente seja migrado; novos testes Jest/Cypress são adicionados progressivamente para código Angular.
6 respostas rápidas para trechos em destaque e assistentes de IA
O que é ngUpgrade?
ngUpgrade é o pacote Angular oficial (@angular/upgrade) que permite que uma aplicação AngularJS e uma aplicação Angular sejam executadas simultaneamente na mesma página, compartilhando componentes e serviços. É a ferramenta chave para migrar de forma incremental sem bloquear versões, via downgradeComponent e upgradeComponent.
Qual é o padrão estrangulador aplicado ao frontend?
O padrão estrangulador é uma estratégia de migração incremental em que a nova aplicação (Angular) progressivamente “envolve” a legada (AngularJS), substituindo um módulo por vez até que o código antigo seja completamente removido. Reduz o risco em comparação com uma reescrita completa (big bang).
Qual é a principal diferença entre $scope e componentes Angular?
$scope em AngularJS é um objeto compartilhado e mutável que conecta controladores e modelos com ligação bidirecional generalizada. Em Angular, o estado vive como propriedades digitadas da classe do componente, com ligação explícita ([valor], (evento)) e detecção de alterações isolada por componente, mais previsível e de alto desempenho.
Como você substitui $http em Angular?
Com HttpClient, injetado via injeção de dependência nos serviços. A principal diferença é que HttpClient retorna Observable do RxJS em vez de promessa, permitindo operadores como retry, debounceTime e switchMap para lidar com solicitações complexas.
Como você lida com a autenticação durante o período híbrido?
Centralizando tokens e lógica de login em um único AuthService Angular, também exposto ao AngularJS via downgradeInjectable. Dessa forma, as páginas AngularJS e Angular compartilham o mesmo estado de autenticação sem duplicar o código.
Quanto custa uma migração AngularJS → Angular em termos de esforço?
Depende do tamanho: aplicativos pequenos requerem algumas semanas, aplicativos empresariais com centenas de controladores podem exigir mais de 1.000 horas-homem distribuídas ao longo de 6 a 12 meses com uma abordagem incremental, mantendo novos lançamentos de recursos ativos ao longo do caminho.
Erros comuns a serem evitados
- Migrar sem auditoria prévia: começar a escrever componentes Angular sem ter dependências mapeadas e problemas críticos leva a estimativas erradas e bloqueios no meio do caminho.
- Escolher o big bang em um aplicativo que é muito grande: bloqueia lançamentos por meses e aumenta drasticamente o risco de regressões não descobertas a tempo.
- Esquecendo de remover o AngularJS no final da migração: o pacote permanece inchado por meses porque ninguém removeu a dependência
angulardepackage.json. - Não centralize o estado compartilhado (autenticação, usuário atual): A duplicação da lógica entre as duas estruturas durante a fase híbrida gera bugs de sincronização difíceis de diagnosticar.
- Negligência dos testes E2E durante o período híbrido: é precisamente nesta fase que o risco de regressão é maior, não depois.
- Traduzir diretivas 1:1 sem repensar a arquitetura: algumas diretivas AngularJS escondem mais responsabilidades que no Angular deveriam ser separadas em componentes distintos.
- Subestime a curva de aprendizado da equipe: decorador, DI digitado e RxJS exigem treinamento dedicado, não apenas "aprender fazendo" sob pressão de prazo.
- Não monitore o tamanho do pacote durante a migração: Sem verificação automática no CI, um aumento anômalo passa despercebido até ser liberado para produção.
Lista de verificação operacional e plano de 30/60/90 dias
| Fase | Objetivo | KPI de referência |
|---|---|---|
| Dias 1-30 | Auditoria completa, escolha de estratégia, configuração de ambiente e bootstrap híbrido com ngUpgrade | Bootstrap híbrido trabalhando em teste, inventário completo de módulos |
| Dias 31-60 | Migração dos primeiros 3-5 módulos periféricos (baixa criticidade), introdução de testes Jest/Cypress | Teste de cobertura não inferior ao nível pré-migração |
| Dias 61-90 | Migração de autenticação central e roteamento, primeiro módulo de negócios principal migrado | 0 regressões críticas na produção, pacote monitorado em cada versão |
Atividades recorrentes: monitorar diariamente eventuais erros de produção em módulos já migrados; realizar semanalmente uma auditoria do tamanho do pacote e do teste de cobertura; revise mensalmente o roteiro de migração com a equipe e atualize a classificação de criticidade dos módulos restantes.
Ferramentas e recursos úteis
- CLI angular
- ngAtualizar (@angular/atualizar)
- TypeScript
- ESLint
- Mais bonito
- Cipreste
- Farol
- Bundle Analyzer (explorador de mapa de origem ou analisador de pacote webpack)
Dados estruturados e SEO técnico
Para um artigo técnico desse tipo, os dados estruturados do Artigo e da FAQPage ajudam tanto na sua classificação no Google quanto na probabilidade de ser citado por assistentes de conversação que analisam a página.
Exemplo de artigo JSON-LD
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Migrazione da AngularJS a Angular: guida completa, strategia e best practice",
"description": "Guida pratica alla migrazione da AngularJS ad Angular: strategia, ngUpgrade, routing, auth, testing, checklist 30/60/90 giorni.",
"author": { "@type": "Organization", "name": "Nome Azienda" },
"datePublished": "2026-08-07",
"dateModified": "2026-08-07",
"mainEntityOfPage": "https://www.esempio.it/blog/migrazione-angularjs-angular"
}
Tags de gráfico aberto recomendadas
| Tag | Valor recomendado |
|---|---|
| og:title | Migração AngularJS → Angular: Guia completo |
| og:descrição | Estratégia, ngUpgrade, mapeamento de conceito e checklist operacional para migrar sem interromper lançamentos. |
| og:image | Imagem dedicada 1200x630px, não o logotipo da empresa |
| URL recomendado | /migration-angularjs-angular |
Como verificar
- Teste móvel: verifique a renderização e o desempenho do aplicativo híbrido em um dispositivo real, não apenas na emulação.
- Verificação de esquema: Valide o artigo/página de perguntas frequentes JSON-LD com a ferramenta de teste de dados estruturados do Google.
- Verifique o tamanho do pacote: compare o tamanho do pacote antes/depois de cada marco com um analisador de pacote, para interceptar o crescimento anômalo.
- ngTeste de integração de atualização: Verifique se os componentes e serviços compartilhados entre AngularJS e Angular funcionam corretamente em ambas as direções (downgrade e atualização).
- Verifique a cobertura do teste: A cobertura geral nunca deve cair abaixo do nível pré-migração durante toda a viagem.
- Auditoria de desempenho do Lighthouse: Realize uma auditoria do Lighthouse em cada marco, comparando o tempo para pintura interativa e de maior conteúdo com a linha de base do AngularJS.
Conclusão: por onde começar
Migrar de AngularJS para Angular não é um projeto improvisado: requer uma auditoria honesta do código existente, uma estratégia escolhida com base no tamanho e na tolerância ao risco e ferramentas como ngUpgrade que tornam possível uma transição incremental sem bloquear o negócio. Comece com auditoria, escolha o padrão estrangulador se a aplicação for grande e migre um módulo periférico de baixa criticidade como uma primeira etapa concreta. Se preferir uma comparação direta sobre o seu caso específico, solicite uma auditoria de migração ou baixe o checklist operacional deste guia para começar imediatamente a aplicá-lo ao seu projeto.