Como configurar linter e formatter para projetos JS

1. Introdução à importância de linters e formatters

Manter a qualidade do código em projetos JavaScript é um desafio que cresce proporcionalmente ao tamanho da equipe e à complexidade do software. Linters e formatters surgem como soluções automatizadas para garantir consistência, legibilidade e conformidade com boas práticas, eliminando discussões subjetivas sobre estilo durante code reviews.

A diferença fundamental entre essas ferramentas é clara: um linter realiza análise estática do código, identificando possíveis erros, más práticas e violações de regras predefinidas. Já um formatter reescreve automaticamente o código para seguir um padrão de formatação consistente, sem se preocupar com lógica ou semântica.

Os benefícios são significativos: redução de bugs causados por erros comuns, padronização visual do código independentemente do desenvolvedor, integração contínua com validação automática e onboarding mais rápido para novos membros da equipe.

2. Escolhendo as ferramentas certas para o projeto

Para projetos JavaScript modernos, a combinação mais consolidada é ESLint como linter e Prettier como formatador. O ESLint tornou-se o padrão da indústria por sua extensibilidade, suporte a plugins e capacidade de análise profunda. O Prettier, por sua vez, destaca-se por ser opinativo e reduzir drasticamente a necessidade de configuração manual.

Existem alternativas viáveis em contextos específicos:
- JSHint: mais leve, porém com menos recursos que ESLint
- StandardJS: abordagem "sem configuração", ideal para projetos menores
- Biome: ferramenta unificada que combina linter e formatter, ainda em maturação

Para a maioria dos projetos profissionais, a dupla ESLint + Prettier oferece o melhor equilíbrio entre flexibilidade e produtividade.

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

A instalação do ESLint é feita como dependência de desenvolvimento:

npm install eslint --save-dev

Após a instalação, o comando de inicialização interativa ajuda a criar a configuração básica:

npx eslint --init

O arquivo de configuração resultante, normalmente .eslintrc.json, segue esta estrutura:

{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    "eslint:recommended"
  ],
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "rules": {
    "no-console": "warn",
    "no-unused-vars": "error",
    "prefer-const": "error"
  }
}

Para projetos mais estruturados, é comum utilizar presets como Airbnb ou Google:

npm install eslint-config-airbnb-base --save-dev

E atualizar o arquivo de configuração:

{
  "extends": [
    "airbnb-base"
  ]
}

4. Configuração do Prettier para formatação consistente

A instalação do Prettier segue o mesmo padrão:

npm install prettier --save-dev

O arquivo .prettierrc define as opções de formatação:

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

Para integrar com ESLint sem conflitos, instale o pacote de compatibilidade:

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

E adicione ao final da lista extends no ESLint:

{
  "extends": [
    "airbnb-base",
    "prettier"
  ]
}

5. Integração entre ESLint e Prettier

A integração pode ser feita de duas formas principais. A primeira, mais limpa, utiliza apenas eslint-config-prettier para desabilitar regras do ESLint que conflitam com o Prettier. A segunda, com eslint-plugin-prettier, executa o Prettier como uma regra do próprio ESLint:

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

Configuração no .eslintrc.json:

{
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
}

A ordem de execução recomendada é: primeiro o linter identifica problemas, depois o formatador corrige a formatação. Isso evita que o Prettier mascare erros que o ESLint deveria capturar.

6. Configurando hooks e automação no pipeline

Para garantir que o código seja verificado antes de cada commit, utilize husky e lint-staged:

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

Configure o package.json:

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

E adicione scripts úteis:

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

O hook pre-commit gerado pelo husky deve executar:

npx lint-staged

7. Configuração para diferentes ambientes e frameworks

Para projetos React, instale plugins específicos:

npm install eslint-plugin-react eslint-plugin-react-hooks --save-dev

Configuração:

{
  "extends": [
    "plugin:react/recommended",
    "plugin:react-hooks/recommended"
  ],
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}

Para TypeScript, utilize:

npm install @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev

Configuração:

{
  "parser": "@typescript-eslint/parser",
  "plugins": ["@typescript-eslint"],
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ]
}

Para projetos Node.js puro, ajuste as regras de ambiente:

{
  "env": {
    "node": true,
    "es2022": true
  },
  "rules": {
    "node/no-unsupported-features/es-syntax": "error"
  }
}

8. Boas práticas e manutenção contínua

Versionar os arquivos de configuração (.eslintrc.json, .prettierrc, .husky/) é essencial para garantir que todos os membros da equipe utilizem as mesmas regras. Para projetos legados, a adoção gradual é recomendada: comece com regras menos restritivas e aumente a severidade progressivamente.

Ao atualizar regras, utilize o comando --fix para correções automáticas e revise as mudanças manualmente quando necessário. Mantenha um arquivo .eslintignore para excluir diretórios como node_modules e dist.

A documentação das regras escolhidas e a realização de alinhamentos periódicos com a equipe garantem que as ferramentas permaneçam úteis e não se tornem obstáculos à produtividade.

Referências