ESLintPrettierHuskyTypeScriptArchitectureReact

ESLint, Prettier, Husky : automatiser la qualité du code en 2026

Publié le

Dimitri Dumont
Dimitri Dumont

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èmeSans automatisationAvec automatisation
Débats de formatage en reviewTemps perdu, frustrationÉliminés (Prettier)
Imports désordonnésDépendances difficiles à trouverTriés automatiquement (perfectionist)
Conventions non respectéesCode difficile à maintenirAppliquées au commit (ESLint)
Bugs évidents (any, variables inutilisées)Découverts en productionBloqués avant le commit (ESLint)
Violations d'architectureCouplage qui s'installeDé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égorieExemples
Erreurs potentiellesVariables non utilisées, imports manquants
Bonnes pratiquesPréférer const à let, interdire any
ConventionsNommage, ordre des imports, structure des fichiers
ArchitectureDé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 extends implicite)
eslint.config.js
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.

eslint.config.js (extrait règles)
{
  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

Documentation

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.

eslint.config.js
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.

eslint.config.js
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

prettier.config.js
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.

eslint.config.js
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

Terminal
npm install -D husky lint-staged
npx husky init

Configuration

package.json
{
  "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"]
  }
}
.husky/pre-commit
npx lint-staged

Résultat

  1. git commit déclenche Husky
  2. Husky lance lint-staged
  3. lint-staged exécute ESLint et Prettier uniquement sur les fichiers modifiés
  4. Erreur : commit bloqué avec un message explicite
  5. OK : commit effectué

CI en complément

Le pre-commit peut être contourné (--no-verify). La CI doit vérifier l'ensemble du codebase :

.github/workflows/lint.yml
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:check

Configuration complète prête à l'emploi

Fichiers à créer

├── eslint.config.js
├── prettier.config.js
├── package.json
└── .husky/
    └── pre-commit

eslint.config.js

eslint.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

Terminal
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-staged

Les 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 actuelAlternativeDifférence
ESLint + PrettierBiome (v2.3.x)10-25x plus rapide, linting + formatting intégrés, plugins GritQL. Mais écosystème de plugins limité par rapport à ESLint.
Huskylefthook, simple-git-hookslefthook 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 :

  1. Écosystème de plugins : boundaries, perfectionist, check-file n'ont pas d'équivalent Biome
  2. Intégration native : Next.js embarque ESLint par défaut
  3. 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

  1. Ne pas mélanger les rôles : ESLint pour la qualité, Prettier pour le formatage, eslint-config-prettier en dernier pour éviter les conflits.
  2. Migrer vers la flat config maintenant : la v10 (février 2026) supprime définitivement .eslintrc. L'outil @eslint/migrate-config automatise la conversion.
  3. Commencer avec peu de règles : recommended + TypeScript strict + perfectionist + check-file. Ajouter les plugins architecturaux quand le besoin se présente.
  4. Automatiser au commit, vérifier en CI : lint-staged traite les fichiers stagés, la CI vérifie l'ensemble du codebase.
  5. 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.js avec la configuration complète de cet article
  • Créer prettier.config.js avec les options du projet
  • Installer Husky (npx husky init) et configurer lint-staged dans package.json
  • Vérifier que eslint-config-prettier est en dernière position dans le tableau ESLint
  • Ajouter les scripts lint, lint:fix, format et format:check au package.json
  • Tester le pre-commit : modifier un fichier, git add, git commit
  • Ajouter un job CI (npm run lint && npm run format:check)
Dimitri Dumont

À 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 →

Articles similaires