19 - Linting et formatting — ESLint, Biome, automatiser la qualité
Ce que tu vas apprendre
- La différence entre linting et formatting (et pourquoi ca compte)
- Les regles ESLint qui comptent vraiment
- Biome comme alternative moderne a ESLint + Prettier
- Comment configurer Prettier et EditorConfig
- Les pre-commit hooks avec Husky et lint-staged
- L'intégration CI et le "format on save"
- Pourquoi les debats de style sont une perte de temps
Prerequisites
Article précédent : 18 - Constantes
J'ai assiste a une reunion de 45 minutes sur la question : "tabs ou spaces ?". Quarante-cinq minutes. Six développeurs. Cout : environ 500 euros de salaire cumule. Pour une question qu'un fichier de configuration regle en 30 secondes.
Les outils de linting et de formatting existent pour eliminer ce genre de debat. Configure-les une fois, automatise-les, et passe ton energie sur des problèmes qui comptent.
Linting vs formatting : deux problèmes différents
Le formatting concerne la presentation du code : indentation, longueur de ligne, virgules finales, guillemets simples ou doubles. C'est purement cosmetique. Ca n'affecte pas le comportement du programme.
Le linting concerne la qualité du code : variables inutilisees, imports manquants, conditions toujours vraies, patterns dangereux. Ca détecté de vrais problèmes.
Melanger les deux, c'est la source de confusion qui a plombe l'ecosysteme pendant des annees. ESLint essayait de faire les deux. Prettier est arrive pour le formatting. Les regles de style d'ESLint entraient en conflit avec Prettier. On devait installer eslint-config-prettier pour désactiver les regles de style d'ESLint. Un bazar.
La regle simple : Prettier (ou Biome) pour le formatting. ESLint (ou Biome) pour le linting. Deux outils, deux responsabilités.
Les regles ESLint qui comptent
Sur les centaines de regles disponibles, une poignee fait 80% du travail. Voici celles que j'active systématiquement :
javascript// eslint.config.js (flat config, format moderne)
import tseslint from "typescript-eslint";
export default tseslint.config(
...tseslint.configs.recommended,
{
rules: {
// Erreurs reelles
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "error",
"no-constant-condition": "error",
"no-debugger": "error",
// Qualite
"no-console": ["warn", { allow: ["warn", "error"] }],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "warn",
"prefer-const": "error",
"no-var": "error",
},
}
);
Les regles sur les promises sont les plus utiles en TypeScript. no-floating-promises détecté les promises non attendues — une source de bugs silencieux tres courante. no-misused-promises attrape les cas ou tu passes une async function là où un callback synchrone est attendu.
N'active pas toutes les regles par défaut. Chaque regle ajoutee est un compromis entre la rigueur et le bruit. Si l'équipe désactivé une regle en commentaire dans chaque fichier, c'est que la regle n'est pas adaptee au projet.
Biome : l'alternative moderne
Biome (anciennement Rome) est un outil tout-en-un écrit en Rust. Il fait le linting et le formatting. Il est 10 a 100 fois plus rapide qu'ESLint + Prettier. Et il n'a pas besoin de plugins.
json{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"formatter": {
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "warn"
},
"complexity": {
"noForEach": "off"
}
}
}
}
La vitesse change vraiment l'experience. Sur un projet de 2 000 fichiers, ESLint + Prettier prend 30 secondes. Biome prend moins d'une seconde. Ca rend les pre-commit hooks instantanes et le format-on-save imperceptible.
Le compromis : Biome a moins de regles qu'ESLint et pas d'ecosysteme de plugins. Si tu as besoin de regles spécifiques a React, Next.js ou des regles custom, ESLint reste nécessaire. Pour un nouveau projet sans besoins spécifiques, Biome est mon choix par défaut.
Prettier : la configuration minimale
Prettier a une philosophie opiniated : peu d'options, des choix imposes. C'est sa force. Moins tu configures, moins tu debats.
json{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 100,
"bracketSpacing": true
}
Je recommande de garder la configuration par défaut autant que possible. Chaque option modifiee est un choix a justifier et a maintenir. Les valeurs par défaut de Prettier sont raisonnables pour la grande majorite des projets.
EditorConfig : la coherence entre éditeurs
EditorConfig est un fichier .editorconfig a la racine du projet que tous les éditeurs respectent :
iniroot = 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
Ca regle le problème des fins de ligne Windows vs Unix, de l'indentation par défaut et du charset. C'est le minimum pour que tout le monde travaille avec les memes bases, meme sans Prettier. L'article 20 - Conventions d'équipe approfondit ce sujet. Un bon point de depart pour ces pratiques est paltemps.fr.
Pre-commit hooks : le filet de sécurité automatique
Les pre-commit hooks empechent de commiter du code qui ne passe pas le linting et le formatting. Husky + lint-staged est la combinaison la plus repandue :
json{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{json,md,yml}": [
"prettier --write"
]
}
}
bash# Installation
npx husky init
echo "npx lint-staged" > .husky/pre-commit
lint-staged ne traite que les fichiers modifies, pas tout le projet. C'est rapide et cible. Avec Biome, c'est encore plus simple :
json{
"lint-staged": {
"*.{ts,tsx,json}": ["biome check --write"]
}
}
Un point sur lequel j'insiste : les pre-commit hooks sont un filet de sécurité, pas un remplacement du format-on-save. L'ideal est que le code soit deja formate quand tu commits. Le hook attrape les oublis.
Intégration CI
Les hooks locaux peuvent etre contournes (git commit --no-verify). La CI est le dernier rempart :
yaml# .github/workflows/lint.yml
name: Lint
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx biome check .
Le job doit échouer sur les erreurs de linting. Les warnings en CI ne servent a rien — personne ne les lit. Soit c'est une erreur, soit tu desactives la regle.
Le "format on save" : la bonne habitude
Configure ton éditeur pour formater automatiquement a chaque sauvegarde. Dans VS Code :
json{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
Met ce fichier dans .vscode/settings.json a la racine du projet. Chaque dev qui ouvre le projet aura le bon comportement par défaut. Pas besoin de memoriser les raccourcis de formatting.
Pourquoi les debats de style sont une perte de temps
Tabs vs spaces. Guillemets simples vs doubles. Virgule en fin de ligne ou pas. Point-virgule ou pas. Ces debats ont une caracteristique commune : il n'y a pas de bonne réponse. Les deux options sont valides. Le seul mauvais choix, c'est de ne pas choisir.
Choisis une configuration, applique-la avec des outils automatiques, et passe a autre chose. Le temps que tu ne passes pas a debattre du style, tu le passes a résoudre de vrais problèmes. C'est exactement le principe KISS applique a l'outillage.
Résumé
- Le linting détecté des bugs. Le formatting gere la presentation. Ce sont deux problèmes distincts.
- ESLint pour le linting, Prettier pour le formatting. Ou Biome pour les deux.
- Active peu de regles ESLint mais les bonnes : promises, variables inutilisees,
any - Biome est 10-100x plus rapide et suffisant pour la majorite des projets
- Les pre-commit hooks (Husky + lint-staged) empechent les oublis
- La CI est le dernier rempart contre le code non conforme
- Le format-on-save elimine la charge mentale du formatting
- Arrete de debattre du style. Configure un outil et passe a autre chose.
Article précédent : 18 - Constantes
Article suivant : 20 - Conventions d'équipe et ADR
Sources
- Biome documentation - https://biomejs.dev/
- ESLint flat config documentation - https://eslint.org/docs/latest/use/configure/configuration-files
- Prettier documentation - https://prettier.io/docs/en/options.html