Configurando linters e formatters: Prettier e ESLint no seu pipeline

1. Por que integrar linters e formatters no pipeline?

Manter um código limpo e padronizado em projetos que envolvem múltiplos desenvolvedores é um desafio constante. Diferenças de estilo, esquecimento de boas práticas e inconsistências podem gerar retrabalho e bugs difíceis de rastrear. É aqui que a integração de linters e formatters no pipeline de desenvolvimento se torna indispensável.

A automação dessas ferramentas garante consistência de código e reduz significativamente o retrabalho. Quando configuradas corretamente, elas atuam como barreiras de qualidade que impedem que código mal formatado ou com problemas chegue ao repositório principal.

A diferença fundamental entre linter e formatter precisa estar clara: o ESLint realiza análise estática do código, identificando padrões problemáticos, variáveis não utilizadas, más práticas e possíveis erros. Já o Prettier é um formatador opinativo que se preocupa exclusivamente com a aparência do código — espaçamento, uso de aspas, ponto e vírgula, etc.

O impacto na qualidade do código é direto: equipes economizam horas em revisões de código focadas em estilo, bugs comuns são capturados antes da execução, e a experiência do desenvolvedor melhora com feedback imediato durante a escrita.

2. Instalação e configuração inicial do ESLint

Para iniciar, instale o ESLint como dependência de desenvolvimento:

npm install eslint --save-dev

Em seguida, execute o assistente de configuração:

npx eslint --init

Esse comando faz perguntas sobre o ambiente (browser, Node.js), módulos (CommonJS, ES modules) e framework. O resultado é um arquivo de configuração como este:

// .eslintrc.json
{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": "eslint:recommended",
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "rules": {
    "no-unused-vars": "warn",
    "no-console": "off",
    "semi": ["error", "always"]
  }
}

As regras principais envolvem rules (regras personalizadas), extends (configurações predefinidas) e parserOptions (versão do ECMAScript). Os ambientes configuram quais globais estão disponíveis.

3. Instalação e configuração do Prettier

O Prettier é instalado separadamente:

npm install --save-dev prettier

Crie o arquivo de configuração .prettierrc na raiz do projeto:

{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "tabWidth": 2,
  "printWidth": 100
}

Para integrar com ESLint e evitar conflitos, instale dois pacotes essenciais:

npm install --save-dev eslint-config-prettier eslint-plugin-prettier
  • eslint-config-prettier desativa regras do ESLint que conflitam com o Prettier.
  • eslint-plugin-prettier transforma o Prettier em uma regra do ESLint.

Atualize o .eslintrc.json:

{
  "extends": [
    "eslint:recommended",
    "plugin:prettier/recommended"
  ],
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
}

A resolução de conflitos é automática: regras de formatação do ESLint são desativadas, e o Prettier assume o controle da formatação.

4. Configuração do pipeline de CI/CD (GitHub Actions)

Crie o arquivo .github/workflows/lint.yml:

name: Lint and Format

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'

    - name: Install dependencies
      run: npm ci

    - name: Run ESLint
      run: npx eslint . --max-warnings=0

    - name: Run Prettier check
      run: npx prettier --check .

Os passos são: checkout do código, instalação de dependências, execução do ESLint e verificação do Prettier. --max-warnings=0 faz o build falhar se houver qualquer aviso, garantindo rigor máximo.

5. Adicionando hooks de pré-commit com Husky e lint-staged

Instale Husky e lint-staged:

npm install --save-dev husky lint-staged
npx husky init

Configure o lint-staged no package.json:

{
  "lint-staged": {
    "*.js": ["eslint --fix", "prettier --write"],
    "*.json": ["prettier --write"]
  }
}

Crie o hook de pré-commit no arquivo .husky/pre-commit:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

Agora, antes de cada commit, apenas os arquivos modificados são verificados e corrigidos automaticamente. Isso acelera o processo e evita retrabalho em arquivos não alterados.

6. Boas práticas e personalização avançada

Crie scripts padronizados no package.json:

{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "format": "prettier --write .",
    "format:check": "prettier --check ."
  }
}

Para ignorar arquivos específicos, crie .eslintignore e .prettierignore:

# .eslintignore
dist/
node_modules/
*.min.js

# .prettierignore
dist/
node_modules/
package-lock.json

O uso de cache acelera execuções repetidas:

npx eslint . --cache
npx prettier --check . --cache

7. Monitoramento e manutenção contínua

A configuração de linters e formatters não é estática. É importante revisar periodicamente as regras e atualizar dependências para aproveitar novas funcionalidades e correções.

Para exceções pontuais, use comentários específicos:

// eslint-disable-next-line no-console
console.log('Debug temporário');

Métricas de qualidade como redução de erros em produção e tempo economizado em code reviews demonstram o valor da automação. Equipes que adotam essa prática relatam até 40% menos retrabalho relacionado a estilo e bugs comuns.

A manutenção contínua envolve monitorar o pipeline, ajustar regras conforme o projeto evolui e garantir que todos os desenvolvedores estejam alinhados com as configurações. Ferramentas como Dependabot podem automatizar a atualização de versões.

Integrar ESLint e Prettier no pipeline não é apenas uma questão técnica — é uma decisão estratégica que melhora a qualidade do código, acelera o desenvolvimento e promove uma cultura de excelência técnica na equipe.

Referências