17. Manutenção e Evolução - Parte 1: Estratégias de Versionamento e Gerenciamento de Dependências
Este documento apresenta estratégias e práticas para manutenção e evolução de soluções web desenvolvidas com Astro 5, garantindo que seu projeto permaneça atualizado, seguro e escalável ao longo do tempo.
Estratégias de Versionamento
Versionamento Semântico
O versionamento semântico (SemVer) é uma convenção de numeração que facilita o gerenciamento de dependências e atualizações. Siga o formato MAJOR.MINOR.PATCH:
- MAJOR: Mudanças incompatíveis com versões anteriores
- MINOR: Adições de funcionalidades compatíveis com versões anteriores
- PATCH: Correções de bugs compatíveis com versões anteriores
{ "name": "meu-projeto-astro", "version": "1.2.3", // MAJOR.MINOR.PATCH "private": true, "scripts": { "dev": "astro dev", "build": "astro build", "preview": "astro preview" }, "dependencies": { "astro": "^5.0.0" }}Changelog
Mantenha um arquivo CHANGELOG.md para documentar todas as alterações significativas:
# Changelog
Todas as mudanças notáveis neste projeto serão documentadas neste arquivo.
O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.0/),e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR/).
## [Não lançado]
### Adicionado- Nova funcionalidade de pesquisa avançada
### Corrigido- Problema de layout em dispositivos móveis
## [1.2.0] - 2025-02-15
### Adicionado- Suporte a internacionalização (i18n)- Tema escuro
### Alterado- Melhorias de performance no carregamento de imagens
### Corrigido- Erro de validação em formulários
## [1.1.0] - 2025-01-10
### Adicionado- Integração com API de pagamentos- Componente de carrossel de imagens
### Corrigido- Problemas de acessibilidade em botões
## [1.0.0] - 2024-12-01
### Adicionado- Lançamento inicialControle de Versão com Git
Estrutura de Branches
Implemente um fluxo de trabalho Git que facilite o desenvolvimento colaborativo:
# Estrutura de branchesmain # Código em produção├── develop # Código para próxima versão│ ├── feature/nova-funcionalidade│ ├── feature/outra-funcionalidade│ └── bugfix/correcao-erro└── hotfix/correcao-urgente # Correções para produçãoConvenções de Commits
Adote um padrão de mensagens de commit para facilitar a geração automática de changelogs:
# Formato: <tipo>(<escopo>): <descrição>feat(auth): adiciona autenticação com Googlefix(forms): corrige validação de e-maildocs(readme): atualiza instruções de instalaçãostyle(buttons): ajusta espaçamento nos botõesrefactor(api): simplifica lógica de paginaçãotest(utils): adiciona testes para funções de formataçãochore(deps): atualiza dependênciasHooks de Pre-commit
Configure hooks de pre-commit para garantir qualidade de código:
#!/bin/sh. "$(dirname "$0")/_/husky.sh"
# Executar lintingnpm run lint
# Executar testes unitáriosnpm run test:unit
# Verificar formataçãonpm run format:checkGerenciamento de Dependências
Estratégias de Atualização
Atualizações Regulares
Estabeleça uma rotina para manter dependências atualizadas:
# Verificar dependências desatualizadasnpm outdated
# Atualizar dependências de patch (correções de bugs)npm update
# Atualizar dependências de minor (novas funcionalidades)npx npm-check-updates -u --target minor
# Atualizar todas as dependências (incluindo major)npx npm-check-updates -uVersionamento de Dependências
Use o operador de caret (^) para permitir atualizações de minor e patch, mas fixe versões críticas:
{ "dependencies": { "astro": "^5.0.0", // Aceita 5.0.1, 5.1.0, mas não 6.0.0 "critical-package": "1.2.3" // Versão fixa }}Ferramentas de Análise de Dependências
Dependabot
Configure o GitHub Dependabot para automatizar atualizações de segurança:
version: 2updates: - package-ecosystem: "npm" directory: "/" schedule: interval: "weekly" open-pull-requests-limit: 10 versioning-strategy: auto allow: - dependency-type: "direct" commit-message: prefix: "chore" include: "scope"Renovate Bot
Alternativa ao Dependabot com mais opções de configuração:
{ "extends": [ "config:base" ], "packageRules": [ { "matchUpdateTypes": ["minor", "patch"], "matchCurrentVersion": "!/^0/", "automerge": true }, { "matchPackagePatterns": ["^@astrojs/"], "groupName": "astro packages" } ], "schedule": ["every weekend"]}Auditoria de Segurança
Execute verificações regulares de segurança:
# Verificar vulnerabilidadesnpm audit
# Corrigir vulnerabilidades automaticamente quando possívelnpm audit fix
# Relatório detalhadonpm audit --json > audit-report.jsonScript para verificação de segurança:
import { execSync } from 'child_process';import fs from 'fs';
try { // Executar npm audit e capturar saída const auditOutput = execSync('npm audit --json').toString(); const auditData = JSON.parse(auditOutput);
// Verificar se existem vulnerabilidades const vulnerabilities = auditData.vulnerabilities; const totalVulnerabilities = Object.values(vulnerabilities).reduce( (sum, severity) => sum + severity.length, 0 );
if (totalVulnerabilities > 0) { console.log(`⚠️ Encontradas ${totalVulnerabilities} vulnerabilidades:`);
// Listar vulnerabilidades por severidade for (const [severity, vulns] of Object.entries(vulnerabilities)) { if (vulns.length > 0) { console.log(`\n${severity.toUpperCase()}: ${vulns.length}`); vulns.forEach(vuln => { console.log(`- ${vuln.name}: ${vuln.title}`); }); } }
// Salvar relatório detalhado fs.writeFileSync( 'security-report.json', JSON.stringify(auditData, null, 2) );
console.log('\nRelatório detalhado salvo em security-report.json');
// Tentar corrigir automaticamente console.log('\nTentando corrigir vulnerabilidades automaticamente...'); execSync('npm audit fix', { stdio: 'inherit' });
// Verificar vulnerabilidades restantes const remainingOutput = execSync('npm audit --json').toString(); const remainingData = JSON.parse(remainingOutput); const remainingVulns = Object.values(remainingData.vulnerabilities).reduce( (sum, severity) => sum + severity.length, 0 );
if (remainingVulns > 0) { console.log(`\n⚠️ ${remainingVulns} vulnerabilidades não puderam ser corrigidas automaticamente.`); console.log('Considere atualizar manualmente as dependências afetadas ou avaliar o impacto real.'); } else { console.log('\n✅ Todas as vulnerabilidades foram corrigidas!'); } } else { console.log('✅ Nenhuma vulnerabilidade encontrada!'); }} catch (error) { console.error('Erro ao verificar segurança:', error.message); process.exit(1);}Gerenciamento de Lockfiles
Mantenha o arquivo de lock no controle de versão para garantir instalações consistentes:
# Instalar dependências exatamente como definidas no lockfilenpm ciEstratégia para atualização de lockfile:
name: Update Lockfile
on: schedule: - cron: '0 0 * * 0' # Todo domingo à meia-noite workflow_dispatch:
jobs: update: runs-on: ubuntu-latest
steps: - uses: actions/checkout@v3
- name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' cache: 'npm'
- name: Update lockfile run: | npm install git config --local user.email "actions@github.com" git config --local user.name "GitHub Actions" git add package-lock.json git diff --staged --quiet || git commit -m "chore(deps): atualiza lockfile"
- name: Create Pull Request uses: peter-evans/create-pull-request@v5 with: title: 'chore(deps): atualiza lockfile' body: 'Atualização automática do lockfile para garantir instalações consistentes.' branch: 'chore/update-lockfile'Monitoramento de Dependências Obsoletas
Detecção de Dependências Descontinuadas
import { execSync } from 'child_process';import fs from 'fs';
try { // Obter informações sobre pacotes instalados const npmList = JSON.parse( execSync('npm list --json --depth=0').toString() );
const packageJson = JSON.parse( fs.readFileSync('package.json', 'utf-8') );
const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
// Verificar status de cada dependência const deprecatedPackages = []; const outdatedPackages = [];
for (const [name, version] of Object.entries(dependencies)) { try { // Verificar se o pacote está descontinuado const packageInfo = JSON.parse( execSync(`npm view ${name} --json`).toString() );
if (packageInfo.deprecated) { deprecatedPackages.push({ name, version, message: packageInfo.deprecated }); continue; }
// Verificar se existem alternativas recomendadas if (packageInfo.replacedBy) { deprecatedPackages.push({ name, version, message: `Substituído por: ${packageInfo.replacedBy}` }); } } catch (error) { console.warn(`Não foi possível verificar o pacote ${name}: ${error.message}`); } }
// Verificar pacotes desatualizados try { const outdated = JSON.parse( execSync('npm outdated --json').toString() );
for (const [name, info] of Object.entries(outdated)) { outdatedPackages.push({ name, current: info.current, wanted: info.wanted, latest: info.latest }); } } catch (error) { // npm outdated retorna código de saída 1 se encontrar pacotes desatualizados if (error.status === 1 && error.stdout) { const outdated = JSON.parse(error.stdout.toString());
for (const [name, info] of Object.entries(outdated)) { outdatedPackages.push({ name, current: info.current, wanted: info.wanted, latest: info.latest }); } } else { console.warn('Erro ao verificar pacotes desatualizados:', error.message); } }
// Gerar relatório if (deprecatedPackages.length > 0) { console.log('\n⚠️ Pacotes descontinuados:'); deprecatedPackages.forEach(pkg => { console.log(`- ${pkg.name}@${pkg.version}: ${pkg.message}`); }); } else { console.log('\n✅ Nenhum pacote descontinuado encontrado.'); }
if (outdatedPackages.length > 0) { console.log('\n📦 Pacotes desatualizados:'); outdatedPackages.forEach(pkg => { console.log(`- ${pkg.name}: ${pkg.current} → ${pkg.wanted} (latest: ${pkg.latest})`); }); } else { console.log('\n✅ Todos os pacotes estão atualizados.'); }
// Salvar relatório fs.writeFileSync( 'dependency-report.json', JSON.stringify({ deprecated: deprecatedPackages, outdated: outdatedPackages, timestamp: new Date().toISOString() }, null, 2) );
console.log('\nRelatório completo salvo em dependency-report.json');
// Retornar código de erro se houver pacotes descontinuados if (deprecatedPackages.length > 0) { process.exit(1); }} catch (error) { console.error('Erro ao verificar dependências:', error.message); process.exit(1);}Continua na Parte 2: Refatoração, Modernização e Monitoramento de Desempenho