Qualidade de código com ESLint e Prettier

Um pouco sobre como o ESLint e Prettier ajudam sua equipe e projetos.

Durante o processo colaborativo de desenvolvimento de software, seja em projetos de código aberto ou para fins profissionais, é comum que os desenvolvedores tenham diferentes estilos de escrita e manutenção do código existente. Esse cenário traz o desafio de manter a base de código coesa, a fim de reduzir possíveis bugs e facilitar o entendimento do projeto para todos os membros da equipe. Para lidar com esse desafio, ferramentas de análise estática de código, como linters e formatters, podem ser utilizadas para auxiliar o time na manutenção do código fonte.

Este artigo tem como objetivo abordar os seguintes pontos:

  • O que é análise estática de código fonte.
  • Como essas ferramentas podem beneficiar seus projetos.
  • Como configurar o ambiente de desenvolvimento para aproveitar ao máximo essas ferramentas

Análise estática de código fonte

As ferramentas de análise estática examinam o código fonte sem a necessidade de executá-lo, com o objetivo de identificar possíveis erros, vulnerabilidades e sugerir melhorias ou convenções de código a serem seguidas. Essas ferramentas operam lendo o código através de uma árvore sintática abstrata (AST), o que permite que essas análises sejam realizadas em tempo real no próprio editor enquanto o código é digitado. No entanto, como essas ferramentas se diferenciam?

Os formatters, como o Prettier, são responsáveis por garantir a consistência no estilo do código, como a preferência por tabs em vez de espaços (apesar de sabermos que tab é melhor que space, caso ainda não esteja convencido, Richard Hendricks tem alguns pontos a considerar), a remoção de ponto e vírgula no final de expressões ou a escolha entre aspas simples e aspas duplas. Dessa forma, o Prettier faria as seguintes alterações no código abaixo:

- console.log( "Hello World!" );
+ console.log('Hello World!')

Por sua vez, os linters, como o ESLint no ecossistema JavaScript, têm como objetivo solucionar problemas no código fonte com base em um conjunto estrito de regras de qualidade de código, como no-unused-vars, no-console, no-implicit-globals e prefer-promise-reject-errors. Ao identificar a violação de uma ou mais dessas regras estabelecidas, o linter destaca o trecho de código afetado e oferece uma solução alternativa. Dessa forma, o ESLint realizaria as seguintes alterações no código abaixo:

- Promise.reject('something bad happened')
+ Promise.reject(new Error('something bad happened'))

Embora seja possível utilizar o ESLint para estabelecer um estilo de código, existem algumas razões para manter os conceitos separados. Os linters são excelentes ferramentas para realizar análises estáticas em tempo real no editor de código, no entanto, podem ser lentos, por isso é recomendado que sejam responsáveis apenas pelas regras relacionadas à qualidade do código. Por outro lado, os formatters são ferramentas rápidas que se concentram exclusivamente no estilo do código, o que permite utilizá-los em momentos específicos, como ao salvar um arquivo ou antes de efetuar um commit com suas alterações. Essa abordagem permite reduzir a carga de trabalho imposta ao linter.

Configurando o ambiente

Agora é o momento de configurar o ambiente de desenvolvimento com o ESLint e o Prettier e entender como eles funcionam e podem ser utilizados em conjunto nos seus projetos. O guia a seguir será, em sua maior parte, genérico em relação ao editor de código, mas também serão dadas algumas dicas específicas para quem utiliza o Visual Studio Code. Em geral, o requisito mínimo para utilizar essas ferramentas é ter o Node.js instalado em sua máquina.

Para instalar o Prettier, basta executar o seguinte comando:

npm install prettier --save-dev

Em seguida, você deve criar um arquivo .prettierrc.json na raiz do projeto, onde serão definidas as regras a serem utilizadas:

.prettierrc.json
{
	"useTabs": true,
	"semi": false,
	"singleQuote": true
}

Você pode encontrar a lista completa de opções de configuração e seus valores padrão neste link.

Por fim, você pode executar o Prettier nos arquivos que deseja formatar. O comando a seguir irá formatar todos os arquivos do projeto:

npx prettier --write .

Caso deseje excluir determinadas pastas ou arquivos do processo de formatação, você pode criar um arquivo .prettierignore, seguindo o exemplo abaixo:

.prettierignore
# Folders to ignore
build
coverage
node_modules

No entanto, se você estiver utilizando o Visual Studio Code, o processo de formatação dos arquivos pode ser aprimorado com a extensão Prettier - Code formatter. Além disso, você pode adicionar uma recomendação para instalar a extensão caso outros desenvolvedores se juntem ao projeto e clonem o repositório:

.vscode/extensions.json
{
	"recommendations": ["esbenp.prettier-vscode"]
}

Ao adicionar essa extensão, você terá a opção de configurar o Visual Studio Code para formatar automaticamente ao salvar o arquivo:

.vscode/settings.json
{
	"editor.defaultFormatter": "esbenp.prettier-vscode",
	"editor.formatOnSave": true,
	"prettier.prettierPath": "./node_modules/prettier"
}

Além disso, o Prettier também oferece suporte ao uso de plugins, que adicionam novas regras de formatação, como o prettier-plugin-tailwindcss que ordena as classes do Tailwind CSS de acordo com as recomendações dos desenvolvedores, garantindo uma maior padronização do código do seu projeto. Os plugins são carregados automaticamente, portanto, basta instalá-los como dependências de desenvolvimento e o Prettier os utilizará. No entanto, se você estiver utilizando um gerenciador de pacotes diferente do npm, como o yarn ou pnpm, será necessário especificar explicitamente os plugins nas configurações do Prettier:

.prettierrc.json
{
	"useTabs": true,
	"semi": false,
	"singleQuote": true,
	"plugins": ["prettier-plugin-tailwindcss"]
}

Agora que o Prettier foi adicionado ao projeto, chegou o momento de configurar o ESLint:

npm install eslint --save-dev

Agora, você precisará criar um arquivo de configuração, como .eslintrc.json, manualmente ou através do seguinte comando interativo:

npm init @eslint/config

Desse modo, será criado um arquivo com a seguinte estrutura:

.eslintrc.json
{
	"env": {
		"browser": true,
		"es2021": true
	},
	"extends": ["eslint:recommended"],
	"plugins": [],
	"parserOptions": {
		"ecmaVersion": "latest",
		"sourceType": "module"
	},
	"rules": {}
}

Algumas das principais propriedades de um arquivo de configuração do ESLint incluem:

  • env: fornece informações sobre o ambiente em que o código será executado.
  • extends: permite estender configurações, plugins e regras de outro arquivo de configuração, como o eslint-config-airbnb.
  • plugins: oferece suporte a informações adicionais sobre regras, ambientes, processadores ou configurações personalizadas, como por exemplo o plugin @typescript-eslint/eslint-plugin.
  • parserOptions: permite configurar quais opções da linguagem deseja habilitar, como suporte ao TypeScript usando o @typescript-eslint/parser.
  • rules: permite adicionar, sobrescrever ou desabilitar regras específicas.

Além disso, se você desejar ignorar determinadas pastas durante o processo de formatação, é possível criar um arquivo .eslintignore da mesma maneira que fizemos com o Prettier:

.eslintignore
# Folders to ignore
build
coverage
node_modules

Por fim, você pode executar o ESLint para corrigir a maior quantidade possível de problemas, utilizando o seguinte comando:

npx eslint -- --fix

Você também pode configurar o ESLint para executar automaticamente ao salvar um arquivo. Para isso, instale a extensão ESLint e adicione-a às recomendações, além de adicionar a seguinte configuração ao seu ambiente:

.vscode/extensions.json
{
	"recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
}
.vscode/settings.json
{
	"editor.defaultFormatter": "esbenp.prettier-vscode",
	"editor.formatOnSave": true,
	"editor.codeActionsOnSave": {
		"source.fixAll.eslint": true
	},
	"prettier.prettierPath": "./node_modules/prettier"
}

É importante ressaltar que nem todos os problemas identificados pelo ESLint podem ser corrigidos automaticamente. Os problemas restantes continuarão sendo destacados no editor de código, exigindo que você os corrija manualmente.

Integrando ESLint e Prettier

Conforme mencionado anteriormente, o ESLint possui suas próprias regras de formatação, mas é recomendado deixar a formatação do código sob responsabilidade exclusiva do Prettier. No entanto, pode haver conflitos entre as regras do ESLint e do Prettier. Felizmente, podemos resolver essa questão estendendo a configuração do pacote eslint-config-prettier. Para isso, precisamos adicionar a dependência de desenvolvimento a seguir:

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

Em seguida, é necessário adicionar a configuração ao array da propriedade extends:

.eslintrc.json
{
	"env": {
		"browser": true,
		"es2021": true
	},
	"extends": ["eslint:recommended", "prettier"],
	"plugins": [],
	"parserOptions": {
		"ecmaVersion": "latest",
		"sourceType": "module"
	},
	"rules": {}
}

Observe que ao estender as configurações do pacote, podemos omitir o prefixo eslint-config-, pois o ESLint será capaz de localizar corretamente o pacote dentro das nossas dependências.

Conclusão

Ferramentas de análise estática de código podem ser de grande ajuda para manter a qualidade e consistência do código em seus projetos. O uso do ESLint e Prettier permite automatizar tarefas tediosas de formatação do código e seguir boas práticas de desenvolvimento. Dessa forma, a equipe pode se concentrar no que realmente importa: projetar e desenvolver a aplicação.

Se você está trabalhando com Vite, Next.js ou Nest, provavelmente já percebeu que ao criar um novo projeto, existe uma configuração inicial do ESLint. No entanto, em algumas situações, pode ser necessário adicionar configurações adicionais ao ESLint. Para isso, você pode estender as configurações de pacotes, como por exemplo o eslint-config-airbnb ou o eslint-config-standard, além de poder adicionar ou desabilitar regras específicas conforme necessário.