Si votre commande npm run lint prend 20 secondes sur un projet Next.js de taille moyenne, vous n'êtes pas seul. ESLint, malgré son riche écosystème, est un processus JavaScript qui analyse et vérifie les fichiers séquentiellement, avec un coût qui s'accumule rapidement à mesure que la base de code grandit.
Oxlint est un linter écrit en Rust, issu du projet OXC (soutenu par VoidZero, la société d'outillage d'Evan You). Il a atteint sa v1.0 stable en août 2025, a livré le support des plugins JavaScript en alpha en mars 2026, et est désormais utilisé en production chez Shopify, Airbnb, Mercedes-Benz et Zalando. Sur des bases de code qui prenaient auparavant des minutes à linter, Oxlint termine en moins d'une seconde.
Dans ce guide, vous apprendrez à :
- Comprendre comment Oxlint atteint sa vitesse exceptionnelle
- Installer et configurer Oxlint dans un projet Next.js 15 TypeScript
- Activer les règles intégrées TypeScript, React et Next.js
- Migrer une configuration ESLint existante avec l'outil de migration officiel
- Ajouter des substitutions de règles personnalisées et des configs par répertoire
- Intégrer le tout dans un pipeline CI/CD
- Décider quand conserver ESLint aux côtés d'Oxlint
Prérequis
- Node.js 20+ et pnpm installés
- Un projet Next.js 15 avec TypeScript (ou créez-en un avec
pnpm create next-app@latest) - Connaissance de base des fichiers de configuration ESLint
Pourquoi Oxlint est différent
ESLint s'exécute dans une boucle d'événements Node.js, sérialise les appels de plugins via JavaScript, et parcourt l'AST de chaque fichier avec un seul thread. Il est conçu pour l'extensibilité, pas pour le débit.
Oxlint est construit sur la pile du compilateur OXC, écrite en Rust. Ses avantages :
| Facteur | ESLint | Oxlint |
|---|---|---|
| Langage | JavaScript | Rust |
| Threading | Thread unique | Multi-thread (Rayon) |
| Plugins de règles | JavaScript | Rust (natif) + JS alpha |
| Format de config | .eslintrc.* / flat | .oxlintrc.json / oxlint.config.ts |
| Nombre de règles | Illimité (plugins) | 819+ intégrées |
| Vitesse typique | 20-120s sur grandes apps | moins de 1s |
La promesse de 50-100x n'est pas du marketing : elle vient de la parallélisation de l'analyse des fichiers sur tous les cœurs CPU en code natif, sans surcoût de sérialisation entre le parser et l'évaluateur de règles.
Étape 1 : Installer Oxlint
pnpm add -D oxlintC'est tout. Oxlint se livre comme un seul binaire autonome — pas de dépendances paires, pas de packages de plugins à résoudre.
Lancez-le immédiatement sans aucune config pour voir l'état actuel de votre projet :
pnpm oxlint .Vous verrez une sortie comme :
✖ 3 errors and 12 warnings found.
src/app/page.tsx:14:5 error no-unused-vars 'handler' is defined but never used
src/lib/utils.ts:7:1 warn no-console Unexpected console statement
...
Étape 2 : Créer le fichier de configuration
Oxlint accepte deux formats de configuration. Le plus simple est .oxlintrc.json à la racine de votre projet.
Créez-le :
{
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/crates/oxc_linter/src/config/schema.json",
"plugins": ["typescript", "react", "nextjs", "jsx-a11y", "import"],
"env": {
"browser": true,
"node": true,
"es2022": true
},
"rules": {
"no-console": "warn",
"no-unused-vars": "error",
"typescript/no-explicit-any": "warn",
"react/jsx-key": "error",
"nextjs/no-img-element": "error"
}
}Plugins intégrés disponibles
Tous les plugins suivants sont implémentés nativement en Rust — aucun package npm requis :
typescript— porte les règles de@typescript-eslint/eslint-pluginreact— règles deeslint-plugin-reacteteslint-plugin-react-hooksnextjs— règles spécifiques Next.js (images, scripts, polices, liens)jsx-a11y— règles d'accessibilité deeslint-plugin-jsx-a11yimport— règles d'ordre et de résolution des importsunicorn— règles de qualité de code deeslint-plugin-unicornjest/vitest— règles pour les fichiers de testsoxc— règles supplémentaires spécifiques à OXC
Étape 3 : Utiliser la config TypeScript (oxlint.config.ts)
Pour les projets plus importants, le format TypeScript offre des définitions de règles type-safe et des substitutions par répertoire :
// oxlint.config.ts
import { defineConfig } from "oxlint";
export default defineConfig({
plugins: ["typescript", "react", "nextjs", "jsx-a11y", "import"],
env: {
browser: true,
node: true,
es2022: true,
},
rules: {
"no-console": "warn",
"no-debugger": "error",
"no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"typescript/no-explicit-any": "warn",
"typescript/consistent-type-imports": "error",
"react/jsx-key": "error",
"react/no-unknown-property": "error",
"nextjs/no-img-element": "error",
"nextjs/no-html-link-for-pages": "error",
"import/no-duplicates": "error",
},
overrides: [
{
files: ["**/*.test.ts", "**/*.spec.ts", "**/*.test.tsx"],
plugins: ["vitest"],
rules: {
"vitest/no-disabled-tests": "warn",
"vitest/prefer-expect-assertions": "warn",
"no-console": "off",
},
},
{
files: ["scripts/**/*.ts"],
rules: {
"no-console": "off",
"typescript/no-explicit-any": "off",
},
},
],
});Le tableau overrides vous permet d'appliquer différents ensembles de règles aux fichiers de tests, scripts, ou tout pattern glob — le même pattern que connaissent les utilisateurs d'ESLint.
Étape 4 : Ajouter les scripts npm
Mettez à jour votre package.json :
{
"scripts": {
"lint": "oxlint --fix-suggestions src",
"lint:fix": "oxlint --fix src",
"lint:ci": "oxlint --format github src"
}
}Options clés :
| Option | Comportement |
|---|---|
--fix | Correction automatique des violations corrigeables |
--fix-suggestions | Afficher les corrections suggérées sans les appliquer |
--format github | Format d'annotations GitHub Actions |
--format json | Sortie lisible par machine |
--deny-warnings | Traiter les avertissements comme des erreurs (idéal pour CI) |
--max-warnings N | Échec si plus de N avertissements |
-c path | Utiliser un fichier de config spécifique |
Étape 5 : Migrer depuis ESLint
Si vous avez une configuration ESLint existante, utilisez l'outil de migration officiel pour générer un .oxlintrc.json équivalent :
pnpm dlx @oxlint/migrateIl lit votre .eslintrc.* ou eslint.config.js, mappe les règles vers leurs équivalents Oxlint, et écrit .oxlintrc.json. Les règles sans équivalent natif dans Oxlint sont listées dans un résumé pour que vous sachiez ce qui reste spécifique à ESLint.
Exemple de sortie :
✔ Migrated 34 rules to .oxlintrc.json
⚠ 6 rules have no Oxlint equivalent:
- import/order (custom sort config)
- @typescript-eslint/no-floating-promises
- ...
ℹ Run ESLint only for the 6 remaining rules using the eslint-only config.
Faire tourner Oxlint et ESLint en parallèle (approche recommandée pour la transition)
Pour les règles non migrées, lancez les deux linters dans votre script lint. Puisqu'Oxlint termine en moins d'une seconde, le temps combiné reste bien inférieur à ESLint seul :
{
"scripts": {
"lint": "oxlint src && eslint src --config eslint-remaining.config.js"
}
}Étape 6 : Règles spécifiques à Next.js
Oxlint embarque des règles intégrées pour les anti-patterns Next.js. Activez le plugin nextjs dans votre config et vous obtenez :
| Règle | Ce qu'elle détecte |
|---|---|
nextjs/no-img-element | Balises img brutes (utilisez next/image) |
nextjs/no-html-link-for-pages | Balises a brutes pour les liens internes (utilisez next/link) |
nextjs/no-script-in-head | script à l'intérieur de next/head |
nextjs/no-sync-scripts | Balises script synchrones bloquant le rendu |
nextjs/no-typos | Fautes de frappe dans les exports de récupération de données |
nextjs/next-script-for-ga | Utilisation de script pour GA au lieu de next/script |
Exemple pratique — Oxlint signalera ceci :
// ❌ Déclenche nextjs/no-img-element
export default function Hero() {
return <img src="/hero.jpg" alt="Hero" />;
}Correction :
// ✅ Correct
import Image from "next/image";
export default function Hero() {
return <Image src="/hero.jpg" alt="Hero" width={1200} height={600} />;
}Étape 7 : Règles TypeScript
Le plugin typescript porte les règles les plus utilisées de @typescript-eslint. Quelques points forts :
{
"rules": {
"typescript/no-explicit-any": "warn",
"typescript/no-unused-vars": "error",
"typescript/consistent-type-imports": "error",
"typescript/no-non-null-assertion": "warn",
"typescript/prefer-as-const": "error",
"typescript/no-empty-interface": "warn",
"typescript/no-inferrable-types": "warn"
}
}La règle consistent-type-imports est particulièrement puissante — elle impose la syntaxe import type { Foo }, que le compilateur TypeScript peut élider plus efficacement et qui prévient les problèmes de cycles d'import :
// ❌ Signalé par typescript/consistent-type-imports
import { User } from "./types";
// ✅ Correct
import type { User } from "./types";Étape 8 : Règles React Hooks
Le plugin react inclut les règles pour les hooks. Elles sont critiques dans les projets Next.js App Router où les composants alternent entre Server et Client Components :
{
"rules": {
"react/rules-of-hooks": "error",
"react/exhaustive-deps": "warn",
"react/jsx-key": "error",
"react/no-unknown-property": "error"
}
}rules-of-hooks détecte les hooks appelés conditionnellement ou dans des boucles — l'un des bugs d'exécution les plus courants dans les applications React.
Étape 9 : Intégration CI/CD
GitHub Actions
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
oxlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Run Oxlint
run: pnpm oxlint --format github --deny-warnings srcL'option --format github émet des annotations directement dans la vue diff de la PR — les violations apparaissent comme des commentaires inline sur la ligne concernée.
GitLab CI
oxlint:
stage: validate
image: node:20-alpine
script:
- corepack enable
- pnpm install --frozen-lockfile
- pnpm oxlint --deny-warnings src
cache:
key: pnpm-$CI_COMMIT_REF_SLUG
paths:
- node_modules/.pnpm-storePuisqu'Oxlint termine typiquement en moins d'une seconde, il ajoute un temps négligeable à votre étape de pipeline.
Étape 10 : Intégration VS Code
Installez l'extension VS Code Oxlint pour voir les erreurs de lint en ligne pendant la frappe.
Ajoutez à votre .vscode/settings.json :
{
"oxc.enable": true,
"oxc.configPath": ".oxlintrc.json",
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
}
}Oxlint s'intègre aux côtés de Biome (pour le formatage) et du serveur de langage TypeScript — chacun gère sa propre responsabilité sans conflit.
Étape 11 : Plugins JS en Alpha (mars 2026)
L'alpha des plugins JS lancée en mars 2026 permet d'écrire des plugins Oxlint en JavaScript/TypeScript — la même API de plugins que connaissent les utilisateurs d'ESLint. C'est un pont pour les équipes dont les plugins ESLint n'ont pas encore d'équivalent Rust.
Activer un plugin JS :
{
"plugins": ["typescript", "react"],
"jsPlugins": ["./my-custom-rules.mjs"]
}Un plugin JS simple :
// my-custom-rules.mjs
export default {
rules: {
"no-direct-fetch": {
meta: {
type: "suggestion",
docs: { description: "Préférez le helper api() à fetch() direct" },
},
create(context) {
return {
CallExpression(node) {
if (
node.callee.type === "Identifier" &&
node.callee.name === "fetch"
) {
context.report({
node,
message: "Utilisez le helper api() plutôt que fetch() direct.",
});
}
},
};
},
},
},
};Benchmarks : chiffres réels
Sur une application Next.js avec 1 200 fichiers TypeScript :
| Outil | Temps |
|---|---|
| ESLint (flat config, sans cache) | 42 secondes |
| ESLint (avec cache) | 8 secondes |
| Oxlint (à froid) | 0,7 seconde |
| Oxlint (à chaud) | 0,5 seconde |
Quand conserver ESLint
Oxlint ne couvre pas encore toutes les règles et plugins ESLint. Conservez ESLint (limité aux lacunes) quand vous avez besoin de :
@typescript-eslint/no-floating-promises— capture des erreurs async- Configuration complexe d'
import/orderavec des groupes de tri personnalisés - Plugins ESLint internes non encore portés
eslint-plugin-testing-librarypour React Testing Library
La stratégie recommandée en 2026 : Oxlint en premier, ESLint pour le reste — exécutez-les séquentiellement. Le temps combiné reste 5 à 10x plus rapide qu'ESLint seul.
Dépannage
"Règle X introuvable"
Les noms de règles Oxlint incluent le préfixe du plugin. Utilisez typescript/no-explicit-any, pas @typescript-eslint/no-explicit-any.
"Fichier ignoré par .gitignore"
Par défaut, Oxlint respecte .gitignore. Passez --no-ignore pour outrepasser, ou ajoutez des patterns ignore explicites dans .oxlintrc.json :
{
"ignore": ["dist/**", ".next/**", "node_modules/**"]
}Conflits de règles avec ESLint
Quand vous exécutez les deux, désactivez les règles équivalentes Oxlint dans votre config ESLint pour éviter les rapports en double :
// eslint.config.js
export default [
{
rules: {
// Géré par Oxlint — désactivez ici
"no-unused-vars": "off",
"no-console": "off",
"react/jsx-key": "off",
},
},
];Prochaines étapes
- Lisez la référence complète des règles pour découvrir les 819+ règles disponibles
- Explorez Biome comme formateur Rust complémentaire (Oxlint lint ; Biome formate)
- Essayez le playground Oxlint pour tester les règles sur des extraits sans projet
Conclusion
Oxlint apporte un linting en moins d'une seconde aux projets JavaScript et TypeScript qui souffraient auparavant de dizaines de secondes de délai ESLint à chaque sauvegarde et exécution CI. Avec plus de 819 règles intégrées couvrant TypeScript, React, Next.js, l'accessibilité et les imports — toutes implémentées nativement en Rust — la plupart des projets Next.js peuvent aujourd'hui remplacer la majeure partie de leur configuration ESLint sans aucune régression de performance.
Le chemin de migration est clair : installez Oxlint, lancez @oxlint/migrate, gérez le petit ensemble de règles non migrées avec une config ESLint légère, et profitez de temps de lint mesurés en millisecondes plutôt qu'en secondes.
Vos développeurs le remarqueront. Votre pipeline CI vous remerciera.