ESLint, Prettier, Husky : automatiser la qualité du code en 2026
Publié le
Développeur React & Next.js freelance
Un développeur passe en moyenne 58% de son temps à comprendre du code existant (Xia et al., IEEE TSE 2018). Du code inconsistant (formatage variable, imports désordonnés, conventions non respectées) ralentit cette lecture et génère des discussions improductives en code review.
Le contexte 2026 aggrave le problème : les lignes de code produites par développeur ont augmenté de 76% entre mars et novembre 2025, selon le rapport The State of AI Coding 2025 de Greptile, basé sur un milliard de lignes de code analysées mensuellement. Le code généré par Copilot, Claude ou ChatGPT ne suit pas toujours les conventions du projet. Les inconsistances se multiplient.
Ce guide présente les outils pour automatiser la qualité du code en 2026 : ce qu'ils font, leurs limites, et une configuration complète pour un projet TypeScript/React/Next.js. Au-delà des bases, il couvre les plugins qui protègent l'architecture de votre codebase.
Dans cet article :
- Ce que chaque outil fait (et ce qu'il ne fait pas)
- Les plugins essentiels : tri des imports, nommage, protection architecturale
- Comment ESLint peut protéger l'architecture au-delà du style
- La configuration complète, prête à copier-coller, pour un projet TypeScript/React
- Les erreurs courantes et comment les éviter
Pourquoi automatiser la qualité du code en 2026
Le contexte : l'IA génère plus de code
Les outils d'IA (Copilot, Claude Code, Cursor) multiplient le volume de code produit. Ce code est souvent fonctionnel, mais inconsistant avec le reste du projet : conventions de nommage, ordre des imports, style de formatage varient d'une génération à l'autre.
Sans automatisation, ces inconsistances s'accumulent. Le codebase diverge. Les reviews se concentrent sur le style au lieu de la logique.
Ce que l'automatisation résout
| Problème | Sans automatisation | Avec automatisation |
|---|---|---|
| Débats de formatage en review | Temps perdu, frustration | Éliminés (Prettier) |
| Imports désordonnés | Dépendances difficiles à trouver | Triés automatiquement (perfectionist) |
| Conventions non respectées | Code difficile à maintenir | Appliquées au commit (ESLint) |
Bugs évidents (any, variables inutilisées) | Découverts en production | Bloqués avant le commit (ESLint) |
| Violations d'architecture | Couplage qui s'installe | Détectées en temps réel (boundaries) |
Limites
L'automatisation ne remplace pas la code review. Elle ne vérifie pas la logique métier, la pertinence d'un algorithme, ou la qualité des abstractions. Elle libère le reviewer pour qu'il se concentre sur ces sujets.
Le coût initial (configuration, apprentissage des règles) est réel, mais la configuration est réutilisable entre projets. Ce guide fournit une config prête à l'emploi.
ESLint : qualité et conventions
Ce qu'ESLint vérifie
| Catégorie | Exemples |
|---|---|
| Erreurs potentielles | Variables non utilisées, imports manquants |
| Bonnes pratiques | Préférer const à let, interdire any |
| Conventions | Nommage, ordre des imports, structure des fichiers |
| Architecture | Dépendances entre modules, encapsulation |
Ce qu'ESLint ne vérifie pas
- Le formatage (indentation, retours à la ligne) : c'est le rôle de Prettier
- La logique métier : c'est le rôle des tests
- Les types complexes : c'est le rôle de TypeScript
Flat config : la syntaxe par défaut
ESLint utilise la flat config depuis la v9 : un fichier eslint.config.js qui exporte un tableau de configurations. La v10, sortie en février 2026, supprime définitivement l'ancienne syntaxe .eslintrc.
Avantages de la flat config :
- Configuration en JavaScript pur (composition, conditions, variables)
- Meilleure performance (résolution plus rapide)
- Composition explicite (pas de
extendsimplicite)
import eslint from "@eslint/js"
import tseslint from "typescript-eslint"
import reactHooks from "eslint-plugin-react-hooks"
import eslintConfigPrettier from "eslint-config-prettier/flat"
export default [
eslint.configs.recommended,
...tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
{
files: ["**/*.{ts,tsx}"],
rules: {
// Règles personnalisées
},
},
eslintConfigPrettier,
]Depuis la v7, eslint-plugin-react-hooks inclut dans sa config recommended des règles liées au React Compiler (optimisation automatique des re-renders), en plus des règles classiques rules-of-hooks et exhaustive-deps. Ces règles supplémentaires signalent des patterns déjà problématiques en React (mutation pendant le rendu, refs instables), indépendamment du Compiler. Elles préparent le code à être compatible si le projet l'adopte plus tard.
Règles essentielles pour TypeScript/React
Les règles suivantes sont celles que j'utilise sur mes projets React et Next.js (SaaS, sites e-commerce, applications métier). Elles couvrent les problèmes les plus fréquents sans être trop restrictives au quotidien.
{
rules: {
// TypeScript
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/consistent-type-imports": "error",
// Qualité générale
"no-console": ["warn", { allow: ["warn", "error"] }],
"prefer-const": "error",
eqeqeq: ["error", "always"],
}
}Plugins essentiels
Ces plugins font partie de ma configuration standard sur les projets TypeScript/React que j'accompagne. Ils répondent à des problèmes concrets rencontrés régulièrement en mission : imports désordonnés et conventions de nommage incohérentes.
eslint-plugin-perfectionist : tri automatique
L'IA génère des imports dans un ordre aléatoire. D'un fichier à l'autre, les conventions diffèrent. Ce plugin trie automatiquement les imports, les propriétés d'objets et les membres de types.
import perfectionist from "eslint-plugin-perfectionist"
export default [
// ...
{
plugins: { perfectionist },
rules: {
"perfectionist/sort-imports": ["error", {
type: "natural",
groups: [
"builtin",
"external",
"internal",
"parent",
"sibling",
"index",
],
}],
"perfectionist/sort-named-imports": "error",
"perfectionist/sort-object-types": "error",
},
},
]Résultat :
// ❌ Avant (généré par IA)
import { useState } from "react"
import axios from "axios"
import { Button } from "@/components/ui/button"
import fs from "fs"
import { User } from "./types"
// ✅ Après (trié par perfectionist)
import fs from "fs"
import axios from "axios"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { User } from "./types"eslint-plugin-check-file : nommage des fichiers
Flat config uniquement (v3+) | Documentation
Un projet sans convention de nommage accumule UserProfile.tsx, user-profile.tsx et userProfile.tsx. Ce plugin enforce une convention unique.
import checkFile from "eslint-plugin-check-file"
export default [
// ...
{
plugins: { "check-file": checkFile },
rules: {
"check-file/filename-naming-convention": [
"error",
{ "**/*.{ts,tsx}": "KEBAB_CASE" },
{ ignoreMiddleExtensions: true },
],
"check-file/folder-naming-convention": [
"error",
{ "src/**/": "KEBAB_CASE" },
],
},
},
]ignoreMiddleExtensions: true autorise les fichiers comme page.test.tsx ou layout.server.ts (Next.js).
Protéger l'architecture avec ESLint
Les plugins précédents vérifient le style et les conventions. ESLint peut aussi protéger l'architecture du projet : contrôler les dépendances entre couches avec eslint-plugin-boundaries, et forcer l'encapsulation des librairies tierces avec la règle native no-restricted-imports.
Ces outils ont de l'intérêt sur les projets avec une architecture en couches (domain, application, infrastructure, presentation) où l'inversion de dépendances doit être respectée. Avec l'IA qui génère du code sans connaissance de l'architecture du projet, ces violations se multiplient sans vérification automatique. Un article dédié détaillera la configuration de ces plugins.
Prettier : le formatage sans débat
Ce que Prettier fait
Prettier formate le code de manière opinionated :
- Indentation (espaces/tabs, taille)
- Longueur de ligne
- Guillemets simples ou doubles
- Points-virgules
- Retours à la ligne
Version actuelle : 3.8.x | Documentation
Ce que Prettier ne fait pas
- Vérifier la qualité du code : c'est ESLint
- Trier les imports : c'est perfectionist
- Vérifier les types : c'est TypeScript
Configuration minimale
export default {
semi: false,
singleQuote: true,
trailingComma: "es5",
tabWidth: 2,
printWidth: 80,
plugins: ["prettier-plugin-tailwindcss"],
}prettier-plugin-tailwindcss trie automatiquement les classes Tailwind selon l'ordre recommandé par Tailwind Labs.
Intégration avec ESLint (sans conflit)
ESLint et Prettier peuvent entrer en conflit sur les règles de formatage. eslint-config-prettier (v10.x) désactive les règles ESLint qui entrent en conflit.
import eslintConfigPrettier from "eslint-config-prettier/flat"
export default [
// ... autres configs
eslintConfigPrettier, // Toujours en dernier
]L'import /flat ajoute une propriété name pour la compatibilité avec l'ESLint Config Inspector.
Workflow : ESLint vérifie la qualité (erreurs, conventions, architecture) puis Prettier formate le code. Pas de chevauchement.
Husky + lint-staged : automatiser au commit
Le problème sans automatisation
Un développeur oublie de lancer ESLint. Le code non formaté arrive en review. La CI échoue, il faut corriger et re-push. Du temps perdu à chaque cycle.
La solution : pre-commit hooks
Husky (v9.1.x) exécute des scripts sur les hooks Git. lint-staged (v16.2.x) exécute des commandes uniquement sur les fichiers stagés.
Installation
npm install -D husky lint-staged
npx husky initConfiguration
{
"scripts": {
"prepare": "husky",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"format:check": "prettier --check ."
},
"lint-staged": {
"*.{ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{json,md,css}": ["prettier --write"]
}
}npx lint-stagedRésultat
git commitdéclenche Husky- Husky lance
lint-staged - lint-staged exécute ESLint et Prettier uniquement sur les fichiers modifiés
- Erreur : commit bloqué avec un message explicite
- OK : commit effectué
CI en complément
Le pre-commit peut être contourné (--no-verify). La CI doit vérifier l'ensemble du codebase :
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm run lint
- run: npm run format:checkConfiguration complète prête à l'emploi
Fichiers à créer
├── eslint.config.js
├── prettier.config.js
├── package.json
└── .husky/
└── pre-commiteslint.config.js
import eslint from "@eslint/js"
import tseslint from "typescript-eslint"
import reactHooks from "eslint-plugin-react-hooks"
import perfectionist from "eslint-plugin-perfectionist"
import checkFile from "eslint-plugin-check-file"
import eslintConfigPrettier from "eslint-config-prettier/flat"
export default [
eslint.configs.recommended,
...tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
{
files: ["**/*.{ts,tsx}"],
plugins: {
perfectionist,
"check-file": checkFile,
},
rules: {
// TypeScript
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/consistent-type-imports": "error",
// Tri des imports
"perfectionist/sort-imports": ["error", {
type: "natural",
groups: ["builtin", "external", "internal", "parent", "sibling", "index"],
}],
"perfectionist/sort-named-imports": "error",
// Nommage des fichiers
"check-file/filename-naming-convention": [
"error",
{ "**/*.{ts,tsx}": "KEBAB_CASE" },
{ ignoreMiddleExtensions: true },
],
"check-file/folder-naming-convention": [
"error",
{ "src/**/": "KEBAB_CASE" },
],
// Qualité
"no-console": ["warn", { allow: ["warn", "error"] }],
"prefer-const": "error",
eqeqeq: ["error", "always"],
},
},
eslintConfigPrettier,
]Pour un projet Next.js, eslint-config-next/core-web-vitals remplace la base @eslint/js + typescript-eslint + react-hooks : il embarque déjà ces règles. Les plugins de cet article (perfectionist, check-file) s'ajoutent par-dessus.
Pour ajouter la protection architecturale, voir la section sur les plugins architecturaux plus haut dans l'article.
Dépendances
npm install -D eslint @eslint/js typescript-eslint \
eslint-plugin-react-hooks eslint-plugin-perfectionist \
eslint-plugin-check-file eslint-config-prettier \
prettier prettier-plugin-tailwindcss husky lint-stagedLes erreurs à éviter
Trop de règles dès le départ
Commencer avec les règles essentielles (recommended + TypeScript strict). Ajouter progressivement les plugins selon les besoins constatés en review. Une configuration trop stricte au démarrage génère de la frustration et des eslint-disable partout.
Ignorer les warnings
Un warning ignoré est un warning inutile. Deux options : le corriger, ou le désactiver explicitement. L'accumulation de warnings masque les vrais problèmes.
Conflits ESLint/Prettier non résolus
Si ESLint et Prettier donnent des instructions contradictoires, eslint-config-prettier n'est pas configuré ou n'est pas en dernière position dans le tableau de configuration.
Pre-commit trop lent
Si le pre-commit dure plus de 10 secondes, vérifier que lint-staged est bien configuré. Il ne doit traiter que les fichiers stagés, pas l'ensemble du projet. Vérifier aussi que les règles type-checked (qui lancent le compilateur TypeScript) ne sont pas activées dans le pre-commit.
Désactiver le hook avec --no-verify
En urgence, c'est tentant. Mais ça annule l'intérêt de l'automatisation. La CI est le filet de sécurité pour ces cas.
Alternatives
| Outil actuel | Alternative | Différence |
|---|---|---|
| ESLint + Prettier | Biome (v2.3.x) | 10-25x plus rapide, linting + formatting intégrés, plugins GritQL. Mais écosystème de plugins limité par rapport à ESLint. |
| Husky | lefthook, simple-git-hooks | lefthook est plus performant (Go), simple-git-hooks est plus léger (~150 lignes). |
Biome v2 a introduit les plugins, le support multi-fichiers et les domaines auto-détectés (React, Next.js, testing). C'est une alternative viable pour les nouveaux projets sans besoins spécifiques de plugins.
Pour un projet React/Next.js avec TypeScript, ESLint + Prettier reste le choix pragmatique en 2026 pour trois raisons :
- Écosystème de plugins : boundaries, perfectionist, check-file n'ont pas d'équivalent Biome
- Intégration native : Next.js embarque ESLint par défaut
- Compatibilité : la plupart des projets existants utilisent déjà ESLint
FAQ
Faut-il utiliser Prettier si on a ESLint ?
Oui. ESLint vérifie la qualité du code (erreurs, conventions). Prettier formate le code (indentation, retours à la ligne). Les deux ont des rôles distincts. ESLint ne gère pas le formatage aussi bien que Prettier, et Prettier ne détecte aucune erreur logique.
Comment migrer vers la flat config ?
L'outil officiel @eslint/migrate-config convertit automatiquement un .eslintrc en eslint.config.js. ESLint 9 supportait encore l'ancienne config via ESLINT_USE_FLAT_CONFIG=false, mais la v10 (sortie en février 2026) la supprime définitivement.
Les règles ralentissent-elles le développement ?
Non, si elles sont automatisées. Le développeur code normalement. ESLint corrige au save (via l'IDE) et Prettier formate au commit. Le seul coût est le setup initial et l'apprentissage des messages d'erreur.
eslint-plugin-boundaries est-il adapté à un petit projet ?
Pas toujours. Ce plugin a de l'intérêt quand le projet a une architecture en couches (domain, application, infrastructure). Pour un petit projet Next.js avec des Server Components et des Server Actions, no-restricted-imports suffit pour encapsuler les librairies tierces.
Faut-il mettre eslint-plugin-boundaries en pre-commit ?
Oui. Contrairement aux règles type-checked qui lancent le compilateur TypeScript (et ralentissent le commit), eslint-plugin-boundaries analyse uniquement les chemins d'import. L'impact sur la durée du pre-commit est négligeable.
Conclusion
Ce qu'il faut retenir
- Ne pas mélanger les rôles : ESLint pour la qualité, Prettier pour le formatage,
eslint-config-prettieren dernier pour éviter les conflits. - Migrer vers la flat config maintenant : la v10 (février 2026) supprime définitivement
.eslintrc. L'outil@eslint/migrate-configautomatise la conversion. - Commencer avec peu de règles :
recommended+ TypeScript strict + perfectionist + check-file. Ajouter les plugins architecturaux quand le besoin se présente. - Automatiser au commit, vérifier en CI : lint-staged traite les fichiers stagés, la CI vérifie l'ensemble du codebase.
- L'IA rend ces outils indispensables : le volume de code généré augmente, mais les conventions ne se maintiennent pas toutes seules.
Checklist de démarrage
- Créer
eslint.config.jsavec la configuration complète de cet article - Créer
prettier.config.jsavec les options du projet - Installer Husky (
npx husky init) et configurer lint-staged danspackage.json - Vérifier que
eslint-config-prettierest en dernière position dans le tableau ESLint - Ajouter les scripts
lint,lint:fix,formatetformat:checkaupackage.json - Tester le pre-commit : modifier un fichier,
git add,git commit - Ajouter un job CI (
npm run lint && npm run format:check)

À propos de l'auteur
Je suis Dimitri Dumont, développeur freelance spécialisé React & Next.js depuis plus de 7 ans. J'ai accompagné 22 startups et réalisé 43 missions avec une note de 5/5. J'applique ces patterns au quotidien pour continuer de livrer rapidement du code évolutif. En savoir plus →
Cet article vous a été utile ?
Je peux vous accompagner sur votre projet React & Next.js.
Discutons de votre projet →