Biome : Remplacer ESLint et Prettier par un outil unique ultra-rapide

Votre pipeline ESLint + Prettier prend 45 secondes ? Biome fait la même chose en moins de 2 secondes. Biome est un formateur et linter tout-en-un écrit en Rust qui remplace ESLint, Prettier et leurs dizaines de plugins. Dans ce tutoriel, vous migrerez un projet Next.js complet vers Biome et découvrirez pourquoi des milliers de projets ont fait le switch en 2026.
Ce que vous apprendrez
À la fin de ce tutoriel, vous saurez :
- Comprendre ce que fait Biome et pourquoi il remplace ESLint + Prettier
- Installer et configurer Biome dans un projet JavaScript/TypeScript existant
- Migrer automatiquement vos règles ESLint et Prettier vers Biome
- Configurer des règles de linting personnalisées par fichier et par dossier
- Intégrer Biome dans VS Code avec le formatage automatique
- Ajouter Biome à votre pipeline CI/CD (GitHub Actions et GitLab CI)
- Utiliser les imports organisés et le tri automatique
- Configurer Biome pour un monorepo avec des règles partagées
Prérequis
Avant de commencer, assurez-vous de disposer de :
- Node.js 18+ installé (
node --version) - Un projet JavaScript ou TypeScript existant (idéalement avec ESLint/Prettier)
- Familiarité avec la ligne de commande
- VS Code ou un éditeur avec support LSP
- Connaissance basique des fichiers de configuration (JSON)
Pourquoi Biome ?
En 2026, la majorité des projets JavaScript utilisent ESLint pour le linting et Prettier pour le formatage. Cette combinaison fonctionne, mais elle a des problèmes concrets :
- Lenteur : ESLint parse chaque fichier en JavaScript, ce qui est intrinsèquement lent sur les gros projets
- Configuration complexe : entre
.eslintrc,.prettierrc,eslint-config-*, les plugins, les parsers et les conflits ESLint/Prettier, la configuration devient un casse-tête - Conflits : ESLint et Prettier peuvent se contredire — il faut
eslint-config-prettierpour désactiver les règles en conflit - Maintenance : chaque outil a son cycle de mises à jour, ses breaking changes et ses plugins à maintenir
Biome résout tout cela avec une approche différente :
| Aspect | ESLint + Prettier | Biome |
|---|---|---|
| Langage | JavaScript (lent) | Rust (rapide) |
| Outils | 2 outils + plugins | 1 seul outil |
| Config | 2-4 fichiers | 1 fichier biome.json |
| Vitesse | ~45s sur 1000 fichiers | ~1.5s sur 1000 fichiers |
| Conflits | Fréquents | Impossibles |
Étape 1 : Installer Biome
Créons un nouveau projet pour la démonstration, ou utilisez votre projet existant :
# Créer un projet Next.js de test
npx create-next-app@latest biome-demo --typescript --tailwind --app --src-dir
cd biome-demoInstallez Biome comme dépendance de développement :
npm install --save-dev --save-exact @biomejs/biomeLa version exacte est recommandée (--save-exact) car Biome suit le versionnage sémantique et les mises à jour mineures peuvent ajouter de nouvelles règles qui génèrent des erreurs dans votre CI.
Initialisez la configuration :
npx @biomejs/biome initCela crée un fichier biome.json à la racine du projet :
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": []
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
}
}Étape 2 : Configurer le formateur
Biome utilise des tabulations par défaut, mais la plupart des projets JavaScript utilisent 2 espaces. Configurons le formateur pour correspondre aux conventions habituelles :
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf"
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"semicolons": "always",
"trailingCommas": "all",
"arrowParentheses": "always",
"bracketSpacing": true,
"jsxQuoteStyle": "double"
}
}
}Comparaison avec Prettier
Si vous venez de Prettier, voici la correspondance des options :
| Prettier | Biome | Valeur par défaut |
|---|---|---|
tabWidth | indentWidth | 2 |
useTabs | indentStyle: "tab" | "space" |
printWidth | lineWidth | 80 |
singleQuote | quoteStyle: "single" | "double" |
semi | semicolons | "always" |
trailingComma | trailingCommas | "all" |
endOfLine | lineEnding | "lf" |
Testez le formateur sur votre projet :
# Vérifier sans modifier (mode check)
npx @biomejs/biome format --write .
# Voir les différences sans appliquer
npx @biomejs/biome format .Étape 3 : Configurer le linter
Le linter de Biome intègre plus de 300 règles, dont la plupart des règles populaires de eslint, typescript-eslint, eslint-plugin-react, eslint-plugin-react-hooks et eslint-plugin-jsx-a11y.
Règles recommandées
Par défaut, "recommended": true active un ensemble de règles sûres et consensuelles :
{
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
}
}Personnaliser les règles
Vous pouvez ajuster individuellement chaque règle :
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noExcessiveCognitiveComplexity": {
"level": "warn",
"options": {
"maxAllowedComplexity": 20
}
}
},
"style": {
"noNonNullAssertion": "warn",
"useConst": "error",
"useImportType": "error",
"noParameterAssign": "error"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsoleLog": "warn"
},
"correctness": {
"noUnusedVariables": "error",
"noUnusedImports": "error",
"useExhaustiveDependencies": "warn"
},
"nursery": {
"useSortedClasses": {
"level": "warn",
"options": {
"attributes": ["className"],
"functions": ["clsx", "cn", "cva"]
}
}
}
}
}
}Les règles dans la catégorie nursery sont expérimentales et peuvent changer entre les versions mineures. Utilisez-les en mode warn plutôt que error dans votre CI.
Catégories de règles
Biome organise ses règles en catégories claires :
| Catégorie | Description | Exemples |
|---|---|---|
correctness | Erreurs probables | noUnusedVariables, useExhaustiveDependencies |
suspicious | Code suspect | noExplicitAny, noConsoleLog |
style | Conventions de code | useConst, useImportType |
complexity | Code trop complexe | noExcessiveCognitiveComplexity |
performance | Optimisations | noAccumulatingSpread, noDelete |
security | Vulnérabilités | noDangerouslySetInnerHtml |
a11y | Accessibilité | useAltText, useAriaProps |
nursery | Expérimentales | useSortedClasses |
Lancez le linter :
# Linter seul
npx @biomejs/biome lint .
# Linter avec corrections automatiques
npx @biomejs/biome lint --write .
# Linter + formateur + imports en une commande
npx @biomejs/biome check --write .Étape 4 : Migrer depuis ESLint et Prettier
Si vous avez un projet existant avec ESLint et Prettier, Biome fournit un outil de migration automatique.
Migration automatique
# Migrer la configuration ESLint vers Biome
npx @biomejs/biome migrate eslint --write
# Migrer la configuration Prettier vers Biome
npx @biomejs/biome migrate prettier --writeCela lit vos fichiers .eslintrc.* et .prettierrc.*, puis met à jour biome.json avec les règles équivalentes.
Exemple concret
Supposons cette configuration ESLint :
// .eslintrc.json (avant)
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"prettier"
],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-explicit-any": "warn",
"react-hooks/exhaustive-deps": "warn",
"no-console": "warn"
}
}Après migration, Biome génère :
// biome.json (après migration)
{
"linter": {
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "error",
"useExhaustiveDependencies": "warn"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsoleLog": "warn"
}
}
}
}Nettoyer les anciens fichiers
Une fois la migration validée, supprimez les anciens fichiers :
# Supprimer les fichiers ESLint
rm -f .eslintrc .eslintrc.js .eslintrc.json .eslintrc.yml .eslintignore
# Supprimer les fichiers Prettier
rm -f .prettierrc .prettierrc.js .prettierrc.json .prettierrc.yml .prettierignore
# Désinstaller les dépendances
npm uninstall eslint prettier eslint-config-prettier \
eslint-plugin-react eslint-plugin-react-hooks \
@typescript-eslint/eslint-plugin @typescript-eslint/parser \
eslint-config-nextMettre à jour les scripts npm
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write ."
}
}Étape 5 : Organisation des imports
Biome trie automatiquement vos imports selon des conventions claires. Activez cette fonctionnalité :
{
"organizeImports": {
"enabled": true
}
}Avant / Après
// Avant — imports désordonnés
import { useState, useEffect } from "react";
import axios from "axios";
import styles from "./page.module.css";
import { Button } from "@/components/ui/button";
import type { User } from "@/types";
import { z } from "zod";
import Link from "next/link";// Après — triés automatiquement
import { useEffect, useState } from "react";
import Link from "next/link";
import axios from "axios";
import { z } from "zod";
import type { User } from "@/types";
import { Button } from "@/components/ui/button";
import styles from "./page.module.css";Biome regroupe les imports dans cet ordre :
- Modules natifs Node.js (
node:fs,node:path) - Packages externes (
react,next,zod) - Imports internes (alias
@/, chemins relatifs) - Imports de type (
type { ... })
La commande biome check --write applique le tri en même temps que le linting et le formatage.
Étape 6 : Intégration VS Code
Installer l'extension
Recherchez "Biome" dans le marketplace VS Code ou installez-la depuis le terminal :
code --install-extension biomejs.biomeConfigurer VS Code
Ajoutez ces paramètres dans .vscode/settings.json :
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit",
"quickfix.biome": "explicit"
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[jsonc]": {
"editor.defaultFormatter": "biomejs.biome"
}
}Désactivez les extensions ESLint et Prettier pour éviter les conflits. Biome remplace les deux.
Fonctionnalités dans l'éditeur
Avec l'extension Biome, vous bénéficiez de :
- Formatage au save : le code est formaté automatiquement à chaque sauvegarde
- Diagnostics en temps réel : les erreurs de linting apparaissent directement dans l'éditeur
- Quick fixes :
Ctrl+.propose des corrections automatiques - Tri des imports : les imports sont réorganisés à la sauvegarde
- Refactorings : renommage, extraction, et autres actions de code
Étape 7 : Intégration CI/CD
GitHub Actions
Créez .github/workflows/lint.yml :
name: Lint & Format
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
biome:
name: Biome Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest
- name: Run Biome
run: biome ci .La commande biome ci est optimisée pour les pipelines CI : elle n'écrit pas de fichiers, produit un rapport de diagnostics et retourne un code d'erreur non nul si des problèmes sont détectés.
GitLab CI
Ajoutez dans .gitlab-ci.yml :
biome:
stage: validate
image: node:20-slim
before_script:
- npm ci
script:
- npx @biomejs/biome ci .
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"Pre-commit hook avec Husky
# Installer Husky
npm install --save-dev husky
npx husky init
# Ajouter le hook pre-commit
echo "npx @biomejs/biome check --staged --no-errors-on-unmatched" > .husky/pre-commitLe flag --staged ne vérifie que les fichiers en staging, ce qui rend le hook quasi-instantané.
Étape 8 : Configuration avancée
Overrides par dossier
Biome permet des configurations différentes selon les dossiers ou les patterns de fichiers :
{
"overrides": [
{
"include": ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
}
}
}
},
{
"include": ["scripts/**"],
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off"
}
}
}
},
{
"include": ["**/*.config.ts", "**/*.config.js"],
"formatter": {
"lineWidth": 120
}
}
]
}Ignorer des fichiers
{
"files": {
"ignore": [
"node_modules",
".next",
"dist",
"build",
"coverage",
"*.min.js",
"generated/**"
]
},
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
}
}Avec "useIgnoreFile": true, Biome respecte automatiquement votre .gitignore.
Configuration monorepo
Pour un monorepo, placez biome.json à la racine et utilisez extends dans les packages :
my-monorepo/
├── biome.json # Configuration de base
├── packages/
│ ├── web/
│ │ └── biome.json # Étend la config racine
│ ├── api/
│ │ └── biome.json # Étend la config racine
│ └── shared/
│ └── biome.json # Étend la config racine
// packages/web/biome.json
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"extends": ["../../biome.json"],
"linter": {
"rules": {
"a11y": {
"recommended": true
}
}
}
}Étape 9 : Configuration complète pour Next.js
Voici une configuration biome.json complète et prête pour la production avec Next.js :
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"ignore": [
".next/**",
"node_modules/**",
"public/**",
".contentlayer/**"
]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf"
},
"organizeImports": {
"enabled": true
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"semicolons": "always",
"trailingCommas": "all",
"arrowParentheses": "always",
"bracketSpacing": true
}
},
"json": {
"formatter": {
"trailingCommas": "none"
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "error",
"noUnusedImports": "error",
"useExhaustiveDependencies": "warn"
},
"style": {
"useConst": "error",
"useImportType": "error",
"noNonNullAssertion": "warn"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsoleLog": "warn"
},
"nursery": {
"useSortedClasses": {
"level": "warn",
"options": {
"attributes": ["className"],
"functions": ["clsx", "cn", "cva"]
}
}
}
}
},
"overrides": [
{
"include": ["**/*.test.ts", "**/*.test.tsx"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off",
"noConsoleLog": "off"
}
}
}
}
]
}Étape 10 : Benchmark — ESLint + Prettier vs Biome
Mesurons la différence de performance sur un projet réel. Créez un script de benchmark :
#!/bin/bash
# benchmark.sh
echo "=== Benchmark : 500 fichiers TypeScript ==="
echo ""
# Créer des fichiers de test
mkdir -p bench-files
for i in $(seq 1 500); do
cat > "bench-files/file-$i.tsx" << 'CONTENT'
import { useState, useEffect, useCallback } from "react";
import Link from "next/link";
import { z } from "zod";
const schema = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().min(0).max(150),
});
type FormData = z.infer<typeof schema>;
export function UserForm({ onSubmit }: { onSubmit: (data: FormData) => void }) {
const [data, setData] = useState<FormData>({ name: "", email: "", age: 0 });
const [errors, setErrors] = useState<string[]>([]);
const validate = useCallback(() => {
const result = schema.safeParse(data);
if (!result.success) {
setErrors(result.error.errors.map((e) => e.message));
return false;
}
setErrors([]);
return true;
}, [data]);
useEffect(() => {
validate();
}, [validate]);
return (
<form
onSubmit={(e) => {
e.preventDefault();
if (validate()) onSubmit(data);
}}
>
<input
type="text"
value={data.name}
onChange={(e) => setData({ ...data, name: e.target.value })}
/>
<input
type="email"
value={data.email}
onChange={(e) => setData({ ...data, email: e.target.value })}
/>
<Link href="/users">Retour</Link>
{errors.map((err) => (
<p key={err}>{err}</p>
))}
</form>
);
}
CONTENT
done
echo "--- ESLint + Prettier ---"
time npx eslint bench-files/ 2>/dev/null
time npx prettier --check bench-files/ 2>/dev/null
echo ""
echo "--- Biome ---"
time npx @biomejs/biome check bench-files/
# Nettoyage
rm -rf bench-filesRésultats typiques
| Outil | 500 fichiers | 1000 fichiers | 5000 fichiers |
|---|---|---|---|
| ESLint | ~8s | ~18s | ~95s |
| Prettier | ~3s | ~7s | ~35s |
| ESLint + Prettier | ~11s | ~25s | ~130s |
| Biome | ~0.4s | ~0.8s | ~3.5s |
Biome est environ 25 à 35 fois plus rapide grâce à son architecture Rust et son parsing parallèle.
Dépannage
Problèmes courants
Le formatage est différent de Prettier
Biome vise la compatibilité avec Prettier mais quelques cas limites diffèrent. Si une différence spécifique vous bloque :
{
"formatter": {
"attributePosition": "multiline"
}
}Conflit avec l'extension Prettier dans VS Code
Désactivez l'extension Prettier ou limitez-la à des langages non supportés par Biome :
{
"prettier.disableLanguages": [
"javascript",
"typescript",
"javascriptreact",
"typescriptreact",
"json"
]
}Les règles ESLint personnalisées ne sont pas migrées
Certaines règles spécifiques à des plugins ESLint tiers ne sont pas encore supportées par Biome. Consultez la matrice de compatibilité sur le site officiel pour vérifier le support de vos règles.
Erreur "file too large"
Par défaut, Biome ignore les fichiers de plus de 1 Mo. Ajustez si nécessaire :
{
"files": {
"maxSize": 2097152
}
}Prochaines étapes
Maintenant que Biome est configuré dans votre projet :
- Explorez les règles nursery : de nouvelles règles sont ajoutées à chaque version, comme
useSortedClassespour trier les classes Tailwind - Configurez les hooks Git pour que chaque commit soit automatiquement vérifié
- Ajoutez le support CSS : Biome supporte désormais le linting et formatage CSS/SCSS (expérimental)
- Essayez
biome search: recherche structurelle dans votre code avec des patterns GritQL - Contribuez : Biome est open source et accueille les contributions sur GitHub
Conclusion
Biome représente un changement de paradigme dans les outils JavaScript. En remplaçant ESLint et Prettier par un seul outil écrit en Rust, vous obtenez :
- Une vitesse 25 à 35 fois supérieure sur le linting et le formatage
- Une configuration simplifiée avec un seul fichier
biome.json - Zéro conflit entre linter et formateur
- Des diagnostics plus clairs avec des suggestions de correction intégrées
- Un écosystème unifié qui s'étend au CSS, GraphQL et bientôt HTML
La migration depuis ESLint + Prettier est progressive et assistée par les outils de migration automatique. En 2026, Biome est devenu le choix par défaut pour les nouveaux projets et une mise à jour recommandée pour les projets existants.
Discutez de votre projet avec nous
Nous sommes ici pour vous aider avec vos besoins en développement Web. Planifiez un appel pour discuter de votre projet et comment nous pouvons vous aider.
Trouvons les meilleures solutions pour vos besoins.
Articles connexes

Construire un Agent IA Autonome avec Agentic RAG et Next.js
Apprenez a construire un agent IA qui decide de maniere autonome quand et comment recuperer des informations depuis des bases de donnees vectorielles. Un guide pratique complet avec Vercel AI SDK et Next.js, accompagne d'exemples executables.

Construire des agents IA from scratch avec TypeScript : maîtriser le pattern ReAct avec le Vercel AI SDK
Apprenez à construire des agents IA depuis zéro avec TypeScript. Ce tutoriel couvre le pattern ReAct, l'appel d'outils, le raisonnement multi-étapes et les boucles d'agents prêtes pour la production avec le Vercel AI SDK.

Better Auth avec Next.js 15 : Le Guide Complet d'Authentification pour 2026
Apprenez à implémenter une authentification complète dans Next.js 15 avec Better Auth. Ce tutoriel couvre email/mot de passe, OAuth, sessions, protection des routes et contrôle d'accès basé sur les rôles.