Formatação de Código JavaScript: Ferramentas e Normas
Abra qualquer pull request em que metade do diff são alterações de espaços em branco e sentirá a dor imediatamente. Inconsistências de formatação desperdiçam tempo, poluem revisões de código e criam conflitos de merge que nada têm a ver com lógica. A solução é simples: escolha um padrão de formatação, automatize a sua aplicação e nunca mais pense nisso.
Este guia percorre as ferramentas e as normas que tornam a formatação de JavaScript num problema resolvido.
Porquê a Formatação Consistente é Importante
A formatação não é uma questão de estética — é uma questão de velocidade da equipa. Quando cada programador utiliza indentação, posição de chavetas e comprimento de linha diferentes, acontecem três coisas:
As revisões de código ficam lentas. Os revisores gastam energia mental a interpretar formatação desconhecida em vez de avaliar a lógica. Uma função com aspeto diferente de tudo o resto no repositório chama a atenção pelas razões erradas.
Os conflitos de merge multiplicam-se. O Programador A reformata um ficheiro com tabs, o Programador B utiliza espaços, e o Git mostra cada linha como alterada. A correção de bug de três linhas fica soterrada.
A carga cognitiva aumenta. Alternar entre ficheiros com estilos diferentes obriga o cérebro a reinterpretar a estrutura constantemente. A formatação consistente permite ler código como prosa — os olhos já sabem para onde olhar.
A solução não é discutir qual estilo é melhor. É escolher um e automatizá-lo.
Guias de Estilo JavaScript Populares
Antes de escolher ferramentas, convém compreender os principais guias de estilo que moldaram as convenções de formatação JavaScript.
Airbnb Style Guide
O guia de estilo JavaScript mais amplamente adotado. Exige ponto e vírgula, prefere aspas simples, requer vírgulas finais em construções multilinha e utiliza indentação de 2 espaços. A configuração de ESLint (eslint-config-airbnb) agrupa centenas de regras que cobrem tanto formatação como qualidade de código.
// Estilo Airbnb
const getUserData = (userId) => {
const user = findUser(userId);
return {
name: user.name,
email: user.email,
};
};
Standard Style
Adota a abordagem oposta em relação ao ponto e vírgula — sem ponto e vírgula, nunca. Utiliza indentação de 2 espaços e aspas simples. O pacote standard inclui o seu próprio linter, pelo que não é necessária uma configuração separada de ESLint.
// Estilo Standard
const getUserData = (userId) => {
const user = findUser(userId)
return {
name: user.name,
email: user.email
}
}
Google Style Guide
Semelhante ao Airbnb, mas com algumas diferenças nos requisitos de JSDoc e nas convenções de nomenclatura. Utiliza indentação de 2 espaços, exige ponto e vírgula e prefere aspas simples.
Cada um destes guias de estilo tem os seus prós e contras. O importante é a consistência, não qual deles se escolhe. E, cada vez mais, as equipas saltam o debate inteiro deixando o Prettier decidir.
Prettier: O Formatador com Opinião
O Prettier transformou a formatação JavaScript ao remover a maioria das decisões. Analisa o código numa AST (Abstract Syntax Tree) e reescreve-o segundo as suas próprias regras. Não se configura cada escolha de formatação individualmente — definem-se algumas opções de alto nível e o Prettier trata do resto.
Instalação
npm install --save-dev prettier
Crie um ficheiro de configuração .prettierrc:
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "always"
}
Opções de Configuração Principais
printWidth (predefinição: 80) — O comprimento de linha em que o Prettier quebra o código. Não é um limite rígido — o Prettier utiliza-o como orientação para decidir quando dividir expressões em múltiplas linhas. Defini-lo como 100 ou 120 é comum para equipas com monitores largos.
semi (predefinição: true) — Se deve adicionar ponto e vírgula no final das declarações. Defina como false se preferir o estilo Standard.
singleQuote (predefinição: false) — Utiliza aspas simples em vez de aspas duplas. A maioria dos programadores JavaScript prefere aspas simples, tornando true a definição mais comum.
trailingComma (predefinição: "all") — Adiciona vírgulas finais onde for válido. Isto produz diffs mais limpos no Git porque adicionar um novo item a uma lista mostra apenas uma linha alterada em vez de duas.
// Sem vírgulas finais — adicionar "d" altera duas linhas
const items = [
- "a",
- "b",
- "c"
+ "a",
+ "b",
+ "c",
+ "d"
];
// Com vírgulas finais — adicionar "d" altera uma linha
const items = [
"a",
"b",
"c",
+ "d",
];
arrowParens (predefinição: "always") — Se deve envolver um único parâmetro de arrow function em parênteses. "always" significa (x) => x, "avoid" significa x => x.
Executar o Prettier
# Formatar todos os ficheiros
npx prettier --write .
# Verificar sem modificar
npx prettier --check .
# Formatar tipos de ficheiro específicos
npx prettier --write "src/**/*.{js,jsx,ts,tsx}"
Adicione um ficheiro .prettierignore para ignorar ficheiros gerados:
node_modules
dist
build
coverage
*.min.js
Se trabalha com JavaScript minificado, o nosso Code Minifier trata da minificação corretamente — nunca edite código minificado manualmente.
ESLint: Para Além da Formatação
O ESLint tem um propósito diferente do Prettier. Enquanto o Prettier trata da aparência do código, o ESLint deteta como o código se comporta. As regras do ESLint dividem-se em duas categorias:
Regras de formatação — indentação, espaçamento, posição de chavetas. Estas sobrepõem-se ao Prettier e devem geralmente ser desativadas quando se utilizam ambas as ferramentas.
Regras de qualidade de código — variáveis não utilizadas, código inalcançável, coerção implícita de tipos, tratamento de erros em falta. É aqui que o ESLint brilha.
Configuração Recomendada
npm install --save-dev eslint @eslint/js
Um eslint.config.js mínimo:
import js from '@eslint/js';
export default [
js.configs.recommended,
{
rules: {
'no-unused-vars': 'warn',
'no-console': 'warn',
'eqeqeq': 'error',
'no-implicit-coercion': 'error',
},
},
];
Para projetos TypeScript, adicione typescript-eslint:
npm install --save-dev typescript-eslint
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
);
Integração Prettier + ESLint
Executar ambas as ferramentas sem coordenação cria conflitos — as regras de formatação do ESLint lutam contra a saída do Prettier. A solução é o eslint-config-prettier, que desativa todas as regras do ESLint que entram em conflito com o Prettier.
npm install --save-dev eslint-config-prettier
import js from '@eslint/js';
import prettierConfig from 'eslint-config-prettier';
export default [
js.configs.recommended,
prettierConfig,
{
rules: {
// Apenas regras de qualidade de código aqui
'no-unused-vars': 'warn',
'eqeqeq': 'error',
},
},
];
Com esta configuração, o Prettier é responsável pela formatação e o ESLint pela qualidade de código. Sem conflitos, sem confusão.
EditorConfig para Consistência entre Editores
Nem toda a gente na equipa utiliza o mesmo editor. O EditorConfig fornece uma base que funciona no VS Code, WebStorm, Vim, Sublime Text e na maioria dos outros editores.
Crie um ficheiro .editorconfig na raiz do projeto:
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
O EditorConfig trata do básico — indentação, fins de linha, espaços em branco à direita — antes sequer de o Prettier correr. Isto evita o problema comum de um programador em Windows introduzir fins de linha \r\n num projeto baseado em Unix.
Git Hooks com Husky e lint-staged
A formatação automatizada só funciona se efetivamente for executada. Depender de programadores para se lembrarem de correr npx prettier --write antes de cada commit não é escalável. Os Git hooks resolvem isto.
Configuração
npm install --save-dev husky lint-staged
npx husky init
Adicione ao package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"prettier --write",
"eslint --fix"
],
"*.{json,md,css}": [
"prettier --write"
]
}
}
Atualize o hook de pre-commit do Husky (.husky/pre-commit):
npx lint-staged
Agora, cada commit formata automaticamente os ficheiros em staging e executa correções do ESLint. Os programadores nunca precisam de pensar em formatação — simplesmente acontece.
Este é o padrão de ouro para projetos em equipa: o Prettier formata, o ESLint deteta bugs, o Husky garante ambos em cada commit.
O Debate do Ponto e Vírgula
Nenhuma discussão sobre formatação JavaScript ficaria completa sem a questão do ponto e vírgula. Eis a resposta prática: não importa, desde que a equipa seja consistente.
Pró-ponto e vírgula: A terminação explícita de declarações evita casos extremos do ASI (Automatic Semicolon Insertion). Os guias de estilo Airbnb e Google exigem-nos.
Sem ponto e vírgula: O ASI do JavaScript trata da terminação automaticamente. O código fica mais limpo com menos ruído visual. O guia de estilo Standard omite-os.
As armadilhas do ASI sobre as quais as pessoas alertam — como linhas que começam com ( ou [ — são apanhadas pela regra no-unexpected-multiline do ESLint. Na prática, prescindir de ponto e vírgula com linting adequado é perfeitamente seguro.
Escolha um, configure a opção semi do Prettier e siga em frente. O Prettier irá adicioná-los ou removê-los consistentemente de qualquer forma.
Tabs vs Espaços em JavaScript
O ecossistema JavaScript utiliza espaços de forma esmagadora — especificamente, indentação de 2 espaços. Isto não é universal (Go utiliza tabs, Python utiliza 4 espaços), mas em JavaScript é a convenção predominante.
Porquê 2 espaços? Os padrões de callbacks aninhados e métodos encadeados do JavaScript criam indentação profunda rapidamente. Dois espaços mantêm código profundamente aninhado legível sem o empurrar para fora da margem direita do ecrã.
Porquê não tabs? Os tabs permitem que cada programador defina a sua própria largura de visualização, o que parece positivo mas significa que o alinhamento do código se desajusta entre editores. Com espaços, o que se vê é o que todos veem.
Configure isto uma vez no Prettier (tabWidth: 2, useTabs: false) e no EditorConfig (indent_style = space, indent_size = 2), e fica resolvido.
Armadilhas Comuns de Formatação
Arrow Functions Inconsistentes
// Inconsistente — evite isto
const double = x => x * 2;
const add = (a, b) => a + b;
const greet = (name) => {
return `Hello, ${name}`;
};
// Consistente — Prettier com arrowParens: "always"
const double = (x) => x * 2;
const add = (a, b) => a + b;
const greet = (name) => {
return `Hello, ${name}`;
};
Estilo de Desestruturação de Objetos
// Comprimido — difícil de ler
const {name,email,role} = user;
// Formatado — Prettier trata disto automaticamente
const { name, email, role } = user;
// Multilinha para muitas propriedades
const {
name,
email,
role,
department,
startDate,
} = user;
Organização de Declarações de Import
O Prettier não ordena imports — isso é uma preocupação de qualidade de código, não de formatação. Utilize eslint-plugin-import ou o plugin simple-import-sort:
// Imports organizados
import React from 'react';
import { useState, useEffect } from 'react';
import { Button } from '@/components/Button';
import { Modal } from '@/components/Modal';
import { formatDate } from '../utils/dates';
import { validateEmail } from '../utils/validation';
Expressões Ternárias Longas
// Ilegível numa única linha
const label = isAdmin ? 'Admin Dashboard' : hasEditPermission ? 'Editor View' : 'Read Only';
// Prettier reformata para multilinha legível
const label = isAdmin
? 'Admin Dashboard'
: hasEditPermission
? 'Editor View'
: 'Read Only';
Configurar um Novo Projeto
Eis uma lista de verificação completa para configurar um novo projeto JavaScript ou TypeScript:
-
Instale as dependências:
npm install --save-dev prettier eslint eslint-config-prettier husky lint-staged -
Crie o
.prettierrccom as preferências da equipa -
Crie o
.editorconfigpara a base entre editores -
Configure o ESLint apenas com regras de qualidade de código (sem regras de formatação)
-
Configure Husky + lint-staged para aplicação no pre-commit
-
Adicione scripts npm:
{ "scripts": { "format": "prettier --write .", "format:check": "prettier --check .", "lint": "eslint .", "lint:fix": "eslint --fix ." } } -
Execute a formatação inicial em toda a base de código:
npm run format -
Faça commit do código formatado como um único commit para facilitar ignorá-lo no
git blamecom--ignore-rev
Formatação na Prática
Assim que o pipeline de formatação estiver configurado, a experiência do dia a dia muda drasticamente:
- Escreva código como quiser. O Prettier reformata ao guardar ou no commit.
- Os pull requests mostram apenas alterações de lógica. Sem mais ruído de espaçamento.
- Novos membros da equipa são produtivos imediatamente. As ferramentas impõem as normas sem necessidade de um documento de guia de estilo.
- As discussões sobre estilo desaparecem. O Prettier é a autoridade, não um programador individual.
Quando precisar de verificar a estrutura de dados JSON com os quais está a trabalhar, o nosso JSON Formatter facilita a inspeção — cole qualquer JSON e obtenha formatação legível instantaneamente no navegador.
Recursos Relacionados
Para saber mais sobre formatação de código e ferramentas para programadores:
- Code Minification Guide — Saiba quando e como minificar JavaScript para produção
- Naming Conventions in Programming — A nomenclatura consistente é a outra metade de código legível
- SQL Formatting Best Practices — Aplique a mesma disciplina de formatação às suas consultas de base de dados
A formatação consistente é um daqueles raros investimentos de engenharia que dá retorno imediato e continua a compensar. Configure-a uma vez, automatize-a e gaste a sua energia no código que realmente importa.