Vous enregistrez un fichier, Prettier le reformate, et ESLint signale immédiatement une erreur sur la ligne que Prettier vient de toucher. Les deux outils sont configurés, les deux tournent, et au lieu de vous aider, ils se bloquent l’un l’autre.
Les deux outils ne font pas le même travail. Le problème, c’est qu’ils ont tous les deux un avis sur une seule chose : l’apparence du code à l’écran.
Ce qu’ESLint vérifie réellement
ESLint transforme votre code en arbre de syntaxe abstraite et exécute des règles sur sa structure. Son intérêt principal vient des règles qui détectent de vrais bugs : une variable jamais définie, un return inaccessible après un autre return, un import resté inutilisé après un refactoring, une clé d’objet dupliquée qui écrase silencieusement la première. Ce sont des vérifications sémantiques : ESLint lit ce que le code fait.
ESLint embarque aussi des règles stylistiques, comme l’obligation des guillemets simples ou des points-virgules et la limite de longueur de ligne. Depuis la version 8.53, elles sont dépréciées en faveur du projet séparé ESLint Stylistic, et elles ne détectent toujours aucun bug. Elles ne détectent que des divergences de style, et c’est précisément cette partie qui entre en collision avec Prettier.
Ce que fait réellement Prettier
Prettier ne lit pas votre code pour en comprendre le sens. Il l’analyse, supprime la mise en forme d’origine, et réimprime tout le fichier selon ses propres règles d’indentation, de longueur de ligne, de style de guillemets et de points de coupure des lignes longues. Lancez-le deux fois sur la même entrée et vous obtenez une sortie identique bit à bit : c’est tout l’objectif. Il n’y a presque rien à configurer, volontairement : un .prettierrc, une poignée d’options, et chaque fichier du projet a le même aspect, peu importe qui l’a écrit.
Lancez prettier --check . en CI et il vous dit si chaque fichier correspond à ce formatage canonique. Il ignore si le code fonctionne, et ça ne le concerne pas.
Pourquoi ESLint et Prettier entrent en conflit
Le chevauchement est restreint. Les règles stylistiques d’ESLint (guillemets, points-virgules, indentation, virgules finales) recoupent celles de Prettier, et les deux ne tombent pas toujours d’accord. Quand ils sont en désaccord, vous obtenez la boucle du premier paragraphe : Prettier reformate une ligne, ESLint signale le résultat, vous “corrigez” à la main, Prettier remet comme avant.
Donc arrêtez de demander à ESLint de prendre des décisions de formatage. Laissez-le faire uniquement ce que Prettier ne peut pas faire : détecter les bugs et les mauvais patterns. eslint-config-prettier est une configuration qui désactive chaque règle ESLint susceptible d’entrer en conflit ou de dupliquer la sortie de Prettier. Elle n’ajoute rien. Elle désactive, uniquement.
Un second paquet, eslint-plugin-prettier, va dans l’autre sens : il exécute Prettier comme règle ESLint, si bien que chaque différence de formatage apparaît comme sa propre erreur ESLint. La documentation officielle de Prettier qualifie cette configuration de “généralement non recommandée”. C’est plus lent, parce qu’ESLint réinvoque Prettier pour chaque fichier. C’est aussi plus bruyant : un seul reformatage peut se transformer en dizaines d’erreurs ESLint au lieu d’un seul diff. Lancez plutôt Prettier seul.
Comment configurer ESLint et Prettier avec le flat config
Depuis ESLint 9, le fichier de configuration est eslint.config.js, un tableau plat d’objets de configuration qui remplace l’ancien format .eslintrc. Si vous partez de zéro :
| |
Cela pose quelques questions et génère un eslint.config.js. Ajoutez ensuite Prettier et la configuration qui fait taire les règles en conflit :
| |
eslint-config-prettier fournit un point d’entrée pour le flat config. Importez-le et placez-le en dernier dans le tableau. Les entrées suivantes écrasent les précédentes, donc tout ce qui est placé après peut réactiver une règle désactivée :
| |
Ajoutez un .prettierrc pour les options propres à Prettier (la plupart des équipes n’en ont presque pas besoin) :
| |
Et deux scripts dans package.json pour que les deux outils tournent indépendamment :
| |
eslint-config-prettier fournit aussi une vérification en ligne de commande qui liste toute règle de votre configuration encore en conflit avec Prettier :
| |
Le code de sortie 0 signifie aucun conflit. 2 signifie qu’il en a trouvé, et la sortie nomme chaque règle pour que vous puissiez la retirer.
Utiliser eslint-config-prettier avec typescript-eslint
Pour TypeScript, typescript-eslint se branche sur le même tableau de flat config et ajoute ses propres règles sémantiques par-dessus l’ESLint classique — tseslint.configs.recommended interdit le any écrit directement dans votre code (no-explicit-any). Attraper un any qui s’est infiltré depuis un appel à une bibliothèque non typée est une étape séparée et plus lourde : passez à recommendedTypeChecked, qui nécessite que parserOptions.project pointe vers votre tsconfig.json pour que les règles puissent demander les vrais types au compilateur TypeScript. La règle d’ordre ne change pas : eslint-config-prettier va toujours en dernier.
| |
Aucun des deux outils ne vérifie si vos types sont bien conçus. Un generic qui aurait dû être contraint avec extends passe les deux contrôles ; c’est le travail du compilateur, traité dans Les Generics TypeScript Expliqués avec des Exemples.
Exécuter ESLint et Prettier dans l’éditeur et en CI
Dans l’éditeur, activez “format on save” pour exécuter Prettier, et laissez ESLint signaler les problèmes séparément, à l’enregistrement ou dans un hook de pre-commit. Une fois les fichiers de configuration ci-dessus en place, les extensions d’éditeur pour les deux outils fonctionnent indépendamment. Vous n’avez pas besoin de relier l’un à l’autre.
En CI, exécutez les deux comme étapes séparées :
| |
Un prettier --check en échec signifie que quelqu’un n’a pas lancé le formateur. Un eslint en échec signifie que le code a un vrai problème. Séparer les deux étapes garde cette différence lisible dans les logs de CI.
Erreurs courantes dans la configuration d’ESLint et Prettier
La plus courante consiste à installer eslint-plugin-prettier parce qu’un vieux tutoriel le conseille, puis à se demander pourquoi eslint . est lent, et pourquoi la liste de problèmes est trois fois plus longue que prévu. Retirez le plugin, gardez eslint-config-prettier, lancez Prettier seul.
La deuxième est l’ordre. Si une configuration partagée ou un override spécifique au projet se trouve après eslintConfigPrettier dans le tableau, il réactive silencieusement une règle qui avait été désactivée. La vérification en ligne de commande ci-dessus l’intercepte avant qu’elle n’arrive dans une PR.
La troisième est le périmètre. Ce duo est conçu pour JavaScript et TypeScript. Si vous démarrez un nouveau projet et préférez un seul outil plus rapide qui fasse le travail des deux, regardez Biome. C’est un compromis différent, pas un remplacement direct de la configuration ci-dessus.
Que faire aujourd’hui dans votre projet
Ouvrez votre package.json. Si eslint-plugin-prettier y figure, désinstallez-le. Ajoutez eslint-config-prettier comme dernière entrée dans eslint.config.js, lancez npx eslint-config-prettier eslint.config.js et corrigez ce qu’il nomme. Après ça, chaque erreur ESLint que vous voyez concerne quelque chose qu’ESLint a trouvé dans la structure du code, pas une ligne que Prettier aurait reformatée de toute façon. Il ne détecte pas encore tout : oublier await dans une boucle ou laisser une promise rejection non gérée est une erreur de logique, pas une erreur de lint, sauf si vous ajoutez un plugin pour ça — consultez Async/Await et l’Event Loop de JavaScript Expliqués pour voir à quoi ressemblent ces erreurs.