Leodario.com

Leodario.com – Tudo sobre Tecnologia

Aula 79 – API JavaScript, Node.js e Express – Code Quality – ESLint, Prettier, Husky

Imagem destacada da aula de API

Introdução

Prezados alunos e alunas, bem-vindos à Aula 79 do nosso programa avançado de desenvolvimento de APIs. Sou seu professor PHD e especialista mundial em APIs, e hoje vamos mergulhar em um tópico que é verdadeiramente essencial para qualquer projeto de software sério: a Qualidade de Código.

Imagine uma orquestra sinfônica. Cada músico é um profissional talentoso, mas para que a melodia seja perfeita, eles precisam seguir uma partitura comum e ensaiar intensamente, garantindo que o ritmo, o volume e a interpretação sejam consistentes. Se cada um tocar do seu jeito, teremos apenas ruído, não uma sinfonia. No mundo do desenvolvimento de APIs, o código é a nossa música. Se cada desenvolvedor seguir um estilo diferente, usar convenções arbitrárias ou introduzir erros sem querer, o resultado será um sistema inconsistente, difícil de manter e propenso a falhas.

A qualidade de código é, portanto, o fundamento para APIs modernas. Ela não apenas assegura que o software funcione corretamente, mas também facilita a colaboração, agiliza a manutenção e melhora a legibilidade. Isso se traduz diretamente em menos bugs, menos estresse e maior produtividade para toda a equipe. É vital que o código seja não apenas funcional, mas também limpo, previsível e padronizado.

Nesta aula, vamos implementar e configurar três ferramentas poderosíssimas no ecossistema Node.js/Express que atuam como os “maestros” e “guardiões” da nossa orquestra de código: ESLint, Prettier e Husky. Veremos como elas trabalham em conjunto para elevar o padrão do seu desenvolvimento, garantindo que cada linha de código que entra no seu repositório seja digna de aplauso.

Conceito Fundamental

Para edificar uma base sólida em qualidade de código, é crucial entender a funcionalidade distinta de cada uma de nossas ferramentas principais: ESLint, Prettier e Husky. Juntas, elas compõem uma estratégia robusta de garantia de qualidade.

  • ESLint: O Analista de Código

O ESLint é uma ferramenta de análise estática de código altamente configurável. Sua função primordial é identificar padrões problemáticos no código JavaScript/TypeScript. Pense nele como um revisor rigoroso que examina seu código em busca de erros lógicos, potenciais bugs, inconsistências de estilo e violações de boas práticas de programação.

A terminologia da indústria se refere a ele como um “linter”. Ele não apenas aponta erros, mas também pode forçar a adesão a um conjunto de regras predefinidas ou personalizadas. Por exemplo, ele pode impedir o uso de variáveis não declaradas, garantir que você use const ou let em vez de var, ou até mesmo impor a complexidade máxima de uma função.

    • Casos de uso reais: Em um projeto de grande porte, o ESLint é indispensável para garantir que novos colaboradores se adaptem rapidamente aos padrões de código da empresa, ou para evitar a introdução de regressões sutis que passariam despercebidas em uma revisão manual. É a primeira linha de defesa contra muitos tipos de problemas de código.
    • Integração: Ele se integra perfeitamente com editores de código (VS Code, WebStorm) e com sistemas de CI/CD (Integração Contínua/Entrega Contínua), executando-se automaticamente.
    • Vantagens: Detecção precoce de erros, promoção de boas práticas, redução de bugs, código mais legível.
    • Desvantagens: Configuração inicial pode ser complexa e consumir tempo, possíveis falsos positivos que exigem ajustes.
  • Prettier: O Estilista de Código

O Prettier é um formatador de código opinativo. Ao contrário do ESLint, que foca na qualidade lógica e potenciais erros, o Prettier se concentra exclusivamente na estética e consistência visual do código. Ele automaticamente reformata seu código para aderir a um estilo predefinido, eliminando discussões intermináveis sobre tabulações vs. espaços, ponto e vírgula, quebras de linha e uso de aspas.

Ele adota uma abordagem “opiniosa” porque não oferece muitas opções de configuração; ele tem um conjunto de regras de formatação bem definidas e as aplica de forma consistente. O objetivo é remover o fardo da formatação do desenvolvedor, permitindo que ele se concentre na lógica.

    • Casos de uso reais: Em equipes, o Prettier é valioso para assegurar que todo o código-fonte pareça ter sido escrito por uma única pessoa. Isso torna a leitura e a revisão de código significativamente mais rápidas e agradáveis, pois você não precisa gastar tempo ajustando o estilo.
    • Integração: Frequentemente usado em conjunto com o ESLint, onde o ESLint cuida das regras de qualidade e o Prettier das regras de formatação. O eslint-config-prettier e eslint-plugin-prettier são pacotes que ajudam a coordenar ambos, desabilitando as regras de formatação do ESLint que podem conflitar com o Prettier.
    • Vantagens: Consistência visual instantânea, eliminação de debates de estilo, agiliza revisões de código, facilita o onboarding.
    • Desvantagens: Menos flexibilidade de configuração (é uma escolha consciente de design), pode causar grandes mudanças em bases de código existentes na primeira aplicação.
  • Husky: O Guarda de Portão do Git

O Husky é uma ferramenta que facilita o uso de Git Hooks. Git Hooks são scripts que o Git executa automaticamente antes ou depois de eventos específicos, como commit, push, rebase, etc. O Husky simplifica a configuração desses hooks, permitindo que você execute qualquer script de shell (ou comando npm) em momentos predefinidos do ciclo de vida do Git.

Ele atua como um “guarda de portão”, garantindo que certas condições sejam atendidas antes que o código possa ser integrado ao repositório principal. Por exemplo, você pode configurar um hook pre-commit para executar o ESLint e o Prettier antes de cada commit. Se o código não passar nas verificações, o commit será abortado.

    • Casos de uso reais: Em qualquer projeto com múltiplos desenvolvedores, o Husky é fundamental para automatizar a aplicação das políticas de qualidade. Ele impede que código que viole as regras de lint ou de formatação seja sequer commitado ou enviado para o repositório remoto, garantindo que o branch main esteja sempre em um estado limpo e consistente.
    • Integração: Ele orquestra a execução do ESLint e do Prettier no momento certo (pré-commit, pré-push), assegurando que o código esteja formatado e sem erros antes de ser compartilhado.
    • Vantagens: Aplicação automatizada e rigorosa das políticas de qualidade, melhora a integridade do repositório, evita que código “ruim” entre no histórico, automatiza testes.
    • Desvantagens: Pode adicionar um pequeno atraso aos commits/pushes (mas é um custo que vale a pena), desenvolvedores podem “burlar” os hooks com --no-verify (mas é uma má prática).

A sinergia entre ESLint (qualidade lógica), Prettier (estilo visual) e Husky (automação via Git Hooks) é o que viabiliza um ambiente de desenvolvimento de alta performance e código padronizado.

Implementação Prática

Vamos agora colocar as mãos na massa e desenvolver um projeto Node.js/Express básico, integrando ESLint, Prettier e Husky. Nosso objetivo é construir um fluxo de trabalho que garanta a qualidade desde o primeiro commit.

Vamos criar uma estrutura de projeto simples para uma API Express e então adicionar as ferramentas.


1. Crie uma nova pasta para o projeto e navegue até ela

📚 Informações da Aula

Curso: API Completo - Node.js & Express

Tempo estimado: 25 minutos

Pré-requisitos: JavaScript básico

mkdir api-qualidade cd api-qualidade

2. Inicialize um novo projeto Node.js

npm init -y

3. Instale o Express para ter um app de exemplo

npm install express

4. Crie um arquivo index.js com um app Express básico

touch index.js

Agora, edite o arquivo index.js:

// index.js
const express = require('express'); // Importa o módulo 'express' para criar o servidor
const app = express(); // Inicializa uma aplicação Express
const PORT = process.env.PORT || 3000; // Define a porta, usando a variável de ambiente ou 3000 como padrão

// Middleware para processar JSON no corpo das requisições app.use(express.json());

// Rota de exemplo para a raiz da API app.get('/', (req, res) => { // Retorna uma mensagem simples como resposta para requisições GET na raiz res.status(200).json({ mensagem: 'Bem-vindo à API de Qualidade de Código!' }); });

// Rota para um recurso específico com um parâmetro dinâmico app.get('/usuarios/:id', (req, res) => { const { id } = req.params; // Extrai o parâmetro 'id' da URL // Em uma aplicação real, aqui haveria lógica para buscar o usuário no banco de dados // Por simplicidade, apenas retornamos o ID res.status(200).json({ mensagem: Detalhes do usuário com ID: ${id} }); });

// Rota para criar um novo usuário (exemplo de POST) app.post('/usuarios', (req, res) => { const novoUsuario = req.body; // Pega o corpo da requisição (espera JSON com dados do usuário) // Exemplo de log profissional (idealmente com uma biblioteca como Winston ou Pino) console.log('Novo usuário recebido:', novoUsuario);

// Aqui entraria a lógica de validação de entrada robusta // Por exemplo: if (!novoUsuario || !novoUsuario.nome || !novoUsuario.email) { return res.status(400).json({ erro: 'Dados inválidos' }); }

// Simula a criação de um usuário e retorna uma resposta res.status(201).json({ mensagem: 'Usuário criado com sucesso!', usuario: novoUsuario }); });

// Middleware de tratamento de erros (exemplo básico) // Este deve ser o último middleware adicionado app.use((err, req, res, next) => { console.error(err.stack); // Registra o erro completo no console do servidor res.status(500).send('Algo deu errado no servidor!'); // Envia uma resposta genérica de erro 500 });

// Inicia o servidor na porta especificada app.listen(PORT, () => { console.log(Servidor rodando na porta ${PORT}); console.log(Para acessar: http://localhost:${PORT}); });

// Este código é 100% compatível com HostGator Plano M // Assumindo que Node.js está configurado. O Plano M geralmente implica um ambiente // onde você tem mais controle sobre o runtime, como um VPS, o que é ideal para Node.js. // As ferramentas de qualidade (ESLint, Prettier, Husky) são para o ambiente de desenvolvimento, // não para o servidor de produção, mas garantem que o código implantado seja de alto padrão.

Agora vamos instalar e configurar as ferramentas de qualidade.


5. Instale o ESLint e suas dependências essenciais

npm install eslint --save-dev

6. Configure o ESLint interativamente

Siga os passos:

- How would you like to use ESLint? -> To check syntax, find problems, and enforce code style

- What type of modules does your project use? -> CommonJS (para 'require')

- Which framework does your project use? -> None of these (não estamos usando React/Vue/Angular para o Express básico)

- Does your project use TypeScript? -> No

- Where does your code run? -> Node

- How would you like to define a style for your project? -> Use a popular style guide

- Which style guide do you want to follow? -> Airbnb (recomendado para padrões enterprise)

- What format do you want your config file to be in? -> JSON

- Would you like to install them now with npm? -> Yes

npx eslint --init

Isso criará o arquivo .eslintrc.json e instalará as dependências necessárias.

Conteúdo esperado para .eslintrc.json (após a configuração do Airbnb):

{
  "env": {
    "commonjs": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    "airbnb-base"
  ],
  "parserOptions": {
    "ecmaVersion": 12
  },
  "rules": {
  }
}

Agora, vamos integrar o Prettier.


7. Instale o Prettier e as dependências para integrá-lo com o ESLint

npm install prettier eslint-config-prettier eslint-plugin-prettier --save-dev

Edite o arquivo .eslintrc.json novamente para integrar o Prettier:

{
  "env": {
    "commonjs": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    "airbnb-base", // Manter o estilo Airbnb para as regras de qualidade
    "plugin:prettier/recommended" // Adiciona o plugin do prettier e desabilita regras de formatação conflitantes do eslint
  ],
  "parserOptions": {
    "ecmaVersion": 12
  },
  "rules": {
    // Você pode adicionar suas próprias regras aqui para sobrescrever as do Airbnb ou do Prettier
    // Exemplo: 'indent': ['error', 2]  <- Prettier já cuida disso, mas é um exemplo de sobrescrita.
    // 'no-console': 'off', // Permite o uso de console.log no projeto
    "prettier/prettier": [
      "error",
      {
        "endOfLine": "auto" // Para evitar problemas de CRLF/LF em diferentes sistemas operacionais
      }
    ]
  }
}

Adicione um arquivo .prettierrc.json para definir algumas configurações do Prettier:

{
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 100,
  "tabWidth": 2,
  "semi": true,
  "endOfLine": "auto"
}

Adicione scripts no seu package.json para facilitar a execução das ferramentas:

// package.json (apenas a seção de scripts)
{
  "name": "api-qualidade",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "lint": "eslint .", // Roda o ESLint em todos os arquivos JavaScript
    "lint:fix": "eslint . --fix", // Roda o ESLint e tenta corrigir automaticamente os problemas
    "format": "prettier --write .", // Roda o Prettier para formatar todos os arquivos
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  ...
}

Agora, vamos integrar o Husky.


8. Instale o Husky

npm install husky --save-dev

9. Inicialize o Husky (isso cria a pasta .husky)

npx husky install

10. Adicione um hook 'pre-commit'

Este hook garantirá que o código seja lintado e formatado antes de cada commit.

Se o lint ou a formatação falharem (ou se o Prettier detectar que o arquivo não está formatado),

o commit será abortado.

npx husky add .husky/pre-commit "npm run lint && npm run format"

No mundo real, você também pode querer:

npx husky add .husky/pre-push "npm test"

Para rodar seus testes antes de cada push para o repositório remoto.

Para testar a integração:

  • Crie um erro intencional no index.js:

Mude uma aspas simples para aspas duplas: res.status(200).json({ "mensagem": 'Bem-vindo...' }); Remova um ponto e vírgula: app.use(express.json()) Crie uma variável não usada: const unusedVar = 'hello'; Altere a identação de uma linha.

  • Tente fazer um commit:
    git add .
    git commit -m "Tentando commitar codigo com problemas"

Você deve ver o Husky executando npm run lint e npm run format. Se houver erros ou arquivos não formatados, o commit será abortado com mensagens do ESLint e/ou Prettier.

  • Corrija os erros e formate:

Execute npm run lint:fix e npm run format para corrigir automaticamente a maioria dos problemas.
Então, tente commitar novamente. Desta vez, o commit deverá ser bem-sucedido.

    npm run lint:fix
    npm run format
    git add .
    git commit -m "Corrigindo problemas e committando código limpo"

Isso demonstra a excelência dessas ferramentas em garantir que apenas código de alta qualidade entre no seu controle de versão.

Melhores Práticas Enterprise:

  • Configurações Compartilhadas: Para grandes equipes, crie pacotes npm de configuração (eslint-config-suaempresa, prettier-config-suaempresa) para reutilizar as regras entre projetos.
  • Editor Integration: Configure seu editor de código (VS Code, por exemplo) para rodar o Prettier e o ESLint ao salvar (formatOnSave, codeActionsOnSave). Isso acelera o desenvolvimento, pois o feedback é instantâneo.
  • .eslintignore e .prettierignore: Utilize esses arquivos para excluir pastas ou arquivos específicos (ex: node_modules, dist, logs) das verificações, otimizando o desempenho.
  • lint-staged: Para repositórios muito grandes, rodar lint e format em todo o projeto pode ser lento. lint-staged permite que você execute essas ferramentas apenas nos arquivos que foram modificados e staged para o commit, melhorando a performance.
  • CI/CD: Integre as verificações de ESLint e Prettier nos seus pipelines de CI/CD para garantir que o código que está sendo mergeado para branches principais sempre esteja conforme os padrões, antes mesmo da implantação.

Exercício Hands-On

Agora é sua vez de aplicar os conhecimentos adquiridos. O objetivo deste desafio é aprofundar sua compreensão e prática com essas ferramentas.

Desafio Prático:

  • Adicione uma nova regra ao ESLint: Implemente uma regra que proíba explicitamente o uso de var em qualquer lugar do seu projeto, forçando o uso de const ou let.
  • Ajuste a configuração do Prettier: Configure o Prettier para sempre usar aspas duplas (") em vez de aspas simples (') para strings.
  • Crie um hook pre-push com Husky: Adicione um novo hook pre-push que garanta que, antes de qualquer código ser enviado para o repositório remoto, o ESLint seja executado novamente para uma verificação final.

Solução Detalhada Passo a Passo:

  • Adicionar regra ESLint (.eslintrc.json):

Abra seu arquivo .eslintrc.json e adicione a seguinte regra dentro do objeto "rules":

    {
      // ... outras configurações
      "rules": {
        "prettier/prettier": [
          "error",
          {
            "endOfLine": "auto"
          }
        ],
        "no-var": "error" // Esta linha adiciona a regra para proibir 'var'
      }
    }

Isso garante que qualquer uso de var será sinalizado como um erro pelo ESLint.

  • Ajustar configuração do Prettier (.prettierrc.json):

Abra seu arquivo .prettierrc.json e altere a propriedade singleQuote para false e adicione quoteProps: "as-needed" para ser explícito.

    {
      "singleQuote": false, // Altera para aspas duplas
      "quoteProps": "as-needed", // Apenas coloca aspas em propriedades quando necessário (ex: com hífens)
      "trailingComma": "all",
      "printWidth": 100,
      "tabWidth": 2,
      "semi": true,
      "endOfLine": "auto"
    }

Ao rodar npm run format ou commitar, o Prettier agora converterá todas as aspas simples em aspas duplas.

  • Criar hook pre-push com Husky:

Abra seu terminal na raiz do projeto e execute o comando:

    npx husky add .husky/pre-push "npm run lint"

Isso gerará um novo arquivo .husky/pre-push que conterá o comando npm run lint, assegurando que o lint seja executado antes de cada git push.

Como Testar e Validar o Resultado:

  • Teste da regra no-var:

No seu index.js, altere const app = express(); para var app = express();.
Salve o arquivo.
Execute npm run lint ou tente fazer um commit (git add . && git commit -m "teste var").
O ESLint deve reportar um erro de no-var, e o commit será abortado.

  • Teste da configuração Prettier:

No seu index.js, mude propositalmente algumas aspas duplas para aspas simples (ex: console.log('Servidor rodando...');).
Salve o arquivo.
Execute npm run format.
Verifique se o Prettier reverteu todas as strings para aspas duplas. Tente commitar.

  • Teste do hook pre-push:

Introduza um erro de lint (não de formatação) no index.js que não foi corrigido pelo lint:fix ou que você deixou de propósito (ex: uma variável não utilizada que você não removeu).
Faça um commit com sucesso.
Tente fazer um push para um repositório remoto (você pode criar um temporário no GitHub ou GitLab).
O hook pre-push do Husky deve ser acionado, rodar npm run lint e, se o erro for detectado, o push será abortado.

Troubleshooting dos Erros Mais Comuns:

  • Conflitos entre ESLint e Prettier: Se o ESLint ainda estiver reportando erros de formatação que o Prettier deveria corrigir, verifique se plugin:prettier/recommended está na seção extends do seu .eslintrc.json e se está depois de airbnb-base (ou qualquer outra configuração de estilo). A ordem é significativa para que as regras do Prettier desabilitem as do ESLint.
  • Arquivos ignorados: Se as ferramentas não estão funcionando em certos arquivos, verifique se eles estão listados em .eslintignore ou .prettierignore.
  • Husky não funciona:

Verifique se a pasta .husky existe na raiz do seu projeto.
Verifique se os scripts dentro de .husky/ são executáveis (chmod +x .husky/). O npx husky add geralmente cuida disso.
* Certifique-se de que o package.json está com os scripts lint e format definidos corretamente.

  • Problemas de CRLF/LF: Se você trabalha em sistemas operacionais mistos (Windows/Linux/macOS), use "endOfLine": "auto" no seu .prettierrc.json e .eslintrc.json para evitar diferenças na quebra de linha que podem causar problemas de lint.

Próximos Passos Sugeridos:

  • lint-staged: Explore a integração do Husky com lint-staged. Isso aprimorará o desempenho dos hooks, executando as verificações apenas nos arquivos que você está prestes a commitar, em vez de todo o projeto.
  • Integração CI/CD: Aprenda a configurar seu pipeline de Integração Contínua (CI) para executar npm run lint e npm run test automaticamente em cada push ou pull request. Isso eleva a qualidade do seu processo de desenvolvimento para um nível profissional.
  • Escrever testes unitários/de integração: Complemente suas verificações de qualidade com testes automatizados para garantir a funcionalidade da sua API. O Husky pode ser usado para rodar esses testes antes de cada commit/push.
  • Aprofundar em regras ESLint: Explore a vasta gama de regras do ESLint e personalize-as de acordo com as necessidades específicas da sua equipe e projeto. Isso viabiliza um controle granular sobre o estilo e a qualidade do seu código.

Parabéns! Você deu um passo gigantesco para se tornar um desenvolvedor de APIs que não apenas cria funcionalidades, mas as constrói com uma base de qualidade inabalável. Continue praticando, e seu código será sempre uma melodia harmoniosa.

🚀 Pronto para a próxima aula?

Continue sua jornada no desenvolvimento de APIs e domine Node.js & Express!

📚 Ver todas as aulas