CodeWorlds
Powrót do kolekcji
Przewodnik14 min czytaniaZespół CodeWorlds

Oxlint, szybki linter JS i TS napisany w Rust

Oxlint sprawdza JavaScript i TypeScript w milisekundach. Wersja 1.79.0, 870 reguł, tryb type-aware oraz to, czego wciąż nie zabierze ESLintowi.

Oxlint, szybki linter JS i TS napisany w Rust

Oxlint to linter dla JavaScriptu i TypeScriptu napisany w Rust, wchodzący w skład projektu Oxc. Wersja 1.79.0 ukazała się 18 sierpnia 2026 roku na licencji MIT. Na katalogu src tego repozytorium, czyli 643 plikach, przebieg z domyślną konfiguracją zajmuje na moim laptopie z ośmioma rdzeniami około 0,04 sekundy.

Oxc to zestaw narzędzi, oxlint to jedno z nich

Nazwy Oxc i oxlint bywają używane zamiennie i to jest pierwsze źródło pomyłek przy instalacji. Oxc, czyli Oxidation Compiler, to parasol nad kilkoma niezależnymi programami: parserem, transformerem, minifikatorem, resolverem modułów, formaterem i właśnie linterem. Wszystkie mieszkają w jednym repozytorium oxc-project/oxc, ale do rejestru npm trafiają jako osobne pakiety z własną numeracją.

Stan na dzień pisania wygląda tak. Linter to pakiet oxlint w wersji 1.79.0. Formater to oxfmt w wersji 0.64.0, pierwszy raz opublikowany 10 września 2025 roku, czyli wciąż przed jedynką. Parser, transformer i minifikator to oxc-parser, oxc-transform i oxc-minify, wszystkie w wersji 0.146.0. Resolver to oxc-resolver w wersji 11.24.2. Do tego dochodzą @oxc-project/types z definicjami węzłów drzewa składniowego oraz @oxc-project/runtime z pomocnikami dla transformera, oba w wersji 0.146.0. Nie istnieje jedna wersja całego zestawu, więc pytanie „jaką masz wersję Oxc” nie ma sensownej odpowiedzi.

Najgorsza pułapka nazewnicza czai się w rejestrze npm. Pakiet o nazwie oxc istnieje, ma wersję 1.0.1 i pochodzi z 5 maja 2016 roku, a jego repozytorium to jasonmccreary/oxc. To narzędzie wiersza poleceń do otwierania projektów w Xcode i nie ma żadnego związku z Oxidation Compiler. Wpisanie npm install oxc zainstaluje coś zupełnie innego, niż się spodziewasz, i nie dostaniesz przy tym ostrzeżenia.

Sam plik wykonywalny lintera również nie leży tam, gdzie mógłbyś zakładać. Pakiet oxlint zawiera wyłącznie kod JavaScript, a binarium przychodzi przez dziewiętnaście zależności opcjonalnych o nazwach @oxlint/binding-darwin-arm64, @oxlint/binding-linux-x64-gnu, @oxlint/binding-win32-x64-msvc i tak dalej. Instalacja z pominięciem zależności opcjonalnych daje pakiet, który nie uruchomi się wcale.

Wersja, licencja i sposób dystrybucji

Licencję sprawdziłem w trzech miejscach, bo w tej kolekcji zdarzało się już, że rozjeżdżały się między sobą.

Pierwsze źródło to plik LICENSE w gałęzi głównej repozytorium. Zawiera tekst licencji MIT z dwiema notami: „Copyright (c) 2024-present VoidZero Inc. & Contributors” oraz „Copyright (c) 2023 Boshen”. Druga nota to ślad po okresie, gdy projekt prowadził pojedynczy autor, zanim powstała firma.

Drugie źródło to pole license w rejestrze npm dla pakietu oxlint, które ma wartość MIT. Trzecie i najważniejsze to zawartość opublikowanej paczki. Archiwum oxlint-1.79.0.tgz waży 371 kilobajtów w postaci spakowanej i około 2,38 megabajta po rozpakowaniu, zawiera siedemnaście plików, w tym LICENSE z tekstem MIT, katalog dist z realnym kodem, plik startowy bin/oxlint oraz configuration_schema.json o wielkości około 758 kilobajtów. To nie jest atrapa ani pusty metapakiet, kod tam jest, a plik licencyjny również. Wyrywkowo sprawdziłem także pakiet z binarium, @oxlint/binding-linux-x64-gnu w wersji 1.79.0, i on też deklaruje MIT. Wszystkie trzy źródła mówią to samo, co w tym zestawieniu jest raczej wyjątkiem niż regułą.

Rytm wydań jest gęsty. Pakiet istnieje w rejestrze od 27 czerwca 2023 roku, wersję 1.0.0 dostał 10 czerwca 2025 roku, a do dziś opublikowano 206 wersji. Ostatnie pięć wydań przypadło na 21 lipca, 27 lipca, 3 sierpnia, 10 sierpnia i 18 sierpnia 2026 roku, czyli mniej więcej co tydzień. Numer środkowy rośnie przy każdym wydaniu, więc zależność zapisana jako ^1.79.0 przyjmie kolejne setki reguł bez pytania.

Pole engines wymaga Node w wersji ^20.19.0 || >=22.12.0. To realne ograniczenie, nie formalność, i wywróci instalację na starszych obrazach kontenerów, które nadal krążą po serwerach budujących.

Warto spojrzeć też na deklarowane zależności rówieśnicze, bo mówią coś o kierunku projektu. Są dwie, obie oznaczone jako opcjonalne: oxlint-tsgolint w wersji co najmniej 7.0.2001 oraz vite-plus bez ograniczenia wersji. Pierwsza to składnik odpowiadający za reguły korzystające z typów. Druga to vite-plus, pakiet w wersji 0.2.9 opisany jako zunifikowany łańcuch narzędzi, produkt firmy VoidZero, tej samej, która stoi za Vite i Vitest. Dokumentacja migracji wprost kieruje część czytelników w tamtą stronę: oxlint dla samego lintowania, Vite+ dla zintegrowanego przepływu pracy. Sam linter jest na MIT i nikt Ci go nie odbierze, ale kierunek rozwoju wyznacza firma, która sprzedaje szerszy produkt, i to jest ryzyko, które przy wyborze narzędzia trzeba nazwać.

Instalacja i pierwsze uruchomienie

Oxlint nie wymaga konfiguracji, żeby cokolwiek zrobić. Uruchomiony bez pliku ustawień włącza kategorię correctness i trzy domyślne wtyczki.

Code
Bash
npm install --save-dev oxlint@1.79.0
npx oxlint src
npx oxlint --init
npx oxlint --print-config
npx oxlint src --fix
npx oxlint src --format=github --deny-warnings

Polecenie --init tworzy plik .oxlintrc.json z wartościami domyślnymi. Polecenie --print-config wypisuje pełną, rozwiniętą konfigurację w formacie JSON i jest najlepszym sposobem, żeby sprawdzić, co naprawdę jest włączone, zamiast zgadywać z dokumentacji.

Flagi naprawiania są trzy i różnią się poziomem ryzyka. --fix stosuje poprawki uznane za bezpieczne, --fix-suggestions dokłada sugestie, które mogą zmienić zachowanie programu, a --fix-dangerously obejmuje jeszcze te oznaczone jako niebezpieczne. Na serwerze budującym używa się zwykle wyłącznie pierwszej albo żadnej.

Formaty wyjścia to checkstyle, default, agent, github, gitlab, json, junit, sarif, stylish i unix. Format agent jest przeznaczony dla asystentów piszących kod, github dla adnotacji przy zmianach w repozytorium.

Konfiguracja i pola, które naprawdę istnieją

Plik .oxlintrc.json przyjmuje dokładnie dwanaście pól najwyższego poziomu: $schema, categories, env, extends, globals, ignorePatterns, jsPlugins, options, overrides, plugins, rules oraz settings. Wszystko poza tą listą zostanie odrzucone.

Code
JSON
{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "plugins": ["eslint", "typescript", "unicorn", "oxc", "import", "react", "vitest"],
  "categories": {
    "correctness": "error",
    "suspicious": "warn",
    "pedantic": "off"
  },
  "env": { "browser": true, "es2024": true },
  "globals": { "__DEV__": "readonly" },
  "ignorePatterns": ["dist", "coverage", "**/*.generated.ts"],
  "options": {
    "denyWarnings": false,
    "maxWarnings": 50,
    "reportUnusedDisableDirectives": true,
    "respectEslintDisableDirectives": true,
    "typeAware": false,
    "typeCheck": false
  },
  "rules": {
    "eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
    "typescript/no-explicit-any": "warn",
    "import/no-cycle": "error"
  },
  "overrides": [
    {
      "files": ["**/*.test.ts", "**/*.test.tsx"],
      "excludeFiles": ["**/fixtures/**"],
      "plugins": ["vitest"],
      "rules": { "vitest/expect-expect": "error" }
    }
  ]
}

Kategorii jest siedem i każda przyjmuje wartość allow, off, warn, error albo deny: correctness, suspicious, pedantic, perf, style, restriction oraz nursery. Skrót all dostępny w wierszu poleceń obejmuje wszystkie poza nursery.

Pole plugins przyjmuje wartości z zamkniętej listy piętnastu nazw: eslint, react, unicorn, typescript, oxc, import, jsdoc, jest, vitest, jsx-a11y, nextjs, react-perf, promise, node, vue. Ustawienie tego pola nadpisuje zestaw domyślny, którym są unicorn, typescript i oxc, a nie dokłada się do niego. To najczęstsza przyczyna sytuacji, w której po dodaniu jednej wtyczki część reguł nagle przestaje raportować.

Obiekt overrides przyjmuje pola files, excludeFiles, env, globals, jsPlugins, plugins oraz rules. Pola typeAware i typeCheck z sekcji options działają wyłącznie w konfiguracji korzeniowej i są ignorowane w konfiguracjach zagnieżdżonych.

Alternatywą jest plik oxlint.config.ts, oznaczony w dokumentacji jako eksperymentalny i wymagający uruchomienia przez Node.

Code
TypeScript
import { defineConfig } from "oxlint";

export default defineConfig({
  plugins: ["typescript", "unicorn", "oxc"],
  options: {
    typeAware: true,
    typeCheck: true
  },
  rules: {
    "typescript/no-floating-promises": ["error", { ignoreVoid: true }],
    "typescript/no-unsafe-assignment": "warn"
  }
});

Różnica dotyczy też pola extends. W .oxlintrc.json jest to lista ścieżek w postaci napisów, rozwiązywanych względem pliku, który je zawiera. W oxlint.config.ts jest to lista zaimportowanych obiektów konfiguracji. Skopiowanie jednego wprost do drugiego nie zadziała.

Ile reguł oxlint naprawdę ma

Zamiast powtarzać liczbę z materiałów projektu, policzyłem ją poleceniem --print-config na wersji 1.79.0.

Code
Bash
npx oxlint --print-config | node -e "
  let s=''; process.stdin.on('data', d => s += d).on('end', () => {
    console.log(Object.keys(JSON.parse(s).rules).length)
  })"

npx oxlint --print-config -D all -D nursery \
  --import-plugin --react-plugin --jsdoc-plugin --jest-plugin \
  --vitest-plugin --jsx-a11y-plugin --nextjs-plugin --react-perf-plugin \
  --promise-plugin --node-plugin --vue-plugin > full.json

Bez konfiguracji włączonych jest 111 reguł. Po włączeniu wszystkich kategorii razem z nursery oraz wszystkich wtyczek wychodzi 870 reguł, rozłożonych następująco.

Przestrzeń nazwLiczba regułOdpowiednik w świecie ESLinta
eslint187reguły rdzenia ESLinta
unicorn138eslint-plugin-unicorn
typescript110typescript-eslint
react85react, react-hooks, react-refresh, React Compiler
vitest73@vitest/eslint-plugin
jest60eslint-plugin-jest
vue46eslint-plugin-vue, tylko sekcja skryptu
jsx_a11y36eslint-plugin-jsx-a11y
import33eslint-plugin-import
oxc27reguły własne oraz porty z deepscan
jsdoc23eslint-plugin-jsdoc
nextjs21@next/eslint-plugin-next
promise16eslint-plugin-promise
node11eslint-plugin-n
react_perf4eslint-plugin-react-perf

Ta tabela pokazuje zarówno zasięg, jak i jego granice. Czternaście wtyczek wbudowanych pokrywa zestawy, które spotyka się najczęściej, a poza nimi nie ma nic natywnego. Reguł dotyczących TypeScriptu jest 110 i nie pokrywają one całego typescript-eslint, a wtyczka Vue obsługuje wyłącznie reguły działające na sekcji skryptu, więc analiza szablonu odpada.

Reguły korzystające z informacji o typach to osobna historia. Obsługuje je składnik oxlint-tsgolint, wersja 7.0.2001 z 21 lipca 2026 roku, licencja MIT, napisany w Go i oparty na typescript-go. Dokumentacja podaje pokrycie 59 z 61 reguł typowanych z typescript-eslint. Cena jest konkretna: wymagany jest TypeScript w wersji 7.0 lub nowszej, część starszych opcji tsconfig.json nie działa, w tym baseUrl, a przy bardzo dużych repozytoriach dokumentacja sama ostrzega przed wysokim zużyciem pamięci.

Code
Bash
npm install --save-dev oxlint-tsgolint@7.0.2001
npx oxlint --type-aware
npx oxlint --type-aware --type-check
npx oxlint --type-aware --debug timings
OXC_LOG=debug npx oxlint --type-aware

Tryb --type-check zgłasza błędy typów obok wyników lintowania i może zastąpić osobny krok tsc --noEmit na serwerze budującym. To niepozorna, ale duża zmiana wobec Biome, które sprawdzania typów nie robi wcale.

Dla wtyczek, których nie ma natywnie, istnieje mechanizm jsPlugins zgodny z interfejsem ESLinta w wersji dziewiątej. Jest oznaczony jako alfa i ma dwa wyraźne braki: nie obsługuje własnych parserów, czyli plików Svelte, Vue i Angulara, oraz nie obsługuje reguł korzystających z typów. Reguły z takich wtyczek działają wolniej, bo przechodzą przez warstwę JavaScriptu, czyli dokładnie to, czego oxlint miał unikać.

Współistnienie z ESLintem

Oxlint nie jest zamiennikiem ESLinta w sensie „usuń jedno, wstaw drugie”. Dokumentacja projektu mówi to zresztą wprost i zaleca układ dwuetapowy.

Code
Bash
npx @oxlint/migrate
npx @oxlint/migrate --type-aware
npx @oxlint/migrate --js-plugins=false
npm install --save-dev eslint-plugin-oxlint@1.79.0
npx oxlint && npx eslint .

Narzędzie @oxlint/migrate w wersji 1.79.0 czyta płaską konfigurację ESLinta z wersji dziewiątej lub dziesiątej i generuje .oxlintrc.json, zachowując poziomy zgłoszeń, opcje reguł, nadpisania dla ścieżek oraz zmienne globalne. Stare pliki .eslintrc.js nie przejdą bezpośrednio, trzeba je najpierw przepuścić przez @eslint/migrate-config. Lokalne wtyczki z własnego repozytorium nie są przenoszone automatycznie i trzeba je dopisać ręcznie do pola jsPlugins.

Pakiet eslint-plugin-oxlint, również w wersji 1.79.0, robi rzecz odwrotną: wyłącza w ESLincie te reguły, które oxlint już sprawdza. Bez tego dostaniesz każdy problem zgłoszony dwa razy, a łączny czas przebiegu wcale nie spadnie.

Kolejność ma znaczenie. Oxlint uruchamiany pierwszy odrzuca zmianę w kilkadziesiąt milisekund, więc ESLint włącza się dopiero na kodzie, który przeszedł tani etap. Odwrotna kolejność nie daje nic. Jeśli budujesz w Turborepo, oba przebiegi opłaca się trzymać jako osobne zadania, żeby pamięć podręczna liczyła je niezależnie.

Oxlint a Biome

Biome jest najbliższym konkurentem i wybór między nimi sprowadza się do jednej decyzji: czy chcesz jedno narzędzie do formatowania i lintowania, czy dwa osobne.

CechaOxlint 1.79.0Biome 2.5.9
Zakrestylko lintowanieformatowanie, lintowanie, akcje porządkowe
Formatowanieosobny pakiet oxfmt 0.64.0wbudowane, dojrzałe
LicencjaMITMIT albo Apache 2.0 do wyboru
Reguły własnewtyczki w JavaScripcie zgodne z ESLint v9, alfawyłącznie GritQL w plikach .grit
Reguły typowane59 z 61 przez oxlint-tsgolint, wymaga TypeScript 7własne wnioskowanie, bez tsc
Sprawdzanie typów--type-check zastępuje tsc --noEmitbrak, tsc zostaje w potoku
Języki poza JS i TSbrakCSS, GraphQL, JSON, wstępnie Vue i Svelte
Plik konfiguracji.oxlintrc.json lub oxlint.config.tsbiome.json

Praktyczny wniosek jest taki. Jeśli masz już Prettiera i jesteś z niego zadowolony, a chcesz wyłącznie skrócić czas lintowania, oxlint pasuje lepiej, bo nie próbuje przy okazji przepisać całego repozytorium. Jeśli chcesz wyrzucić parę ESLint plus Prettier za jednym zamachem, Biome robi to dziś w sposób bardziej kompletny, bo jego formater jest po wersji drugiej, a oxfmt dopiero po zerowej. Jeśli zależy Ci na regułach korzystających z typów, oxlint w trybie --type-aware jest bliżej celu, o ile możesz podnieść TypeScript do wersji siódmej.

Oba narzędzia mają ten sam obszar, którego nie dotykają: nie budują aplikacji, od czego jest esbuild albo Vite, i nie mają nic wspólnego z warstwą danych, którą zajmuje się na przykład Prisma.

Warto rozróżnić dwie sąsiadujące kategorie, bo granica bywa płynna. Linter pilnuje stylu i typowych błędów, a Semgrep dopasowuje wzorce do drzewa składniowego i szuka podatności, więc reguła przetrwa zmianę formatowania czy nazwy zmiennej. Przed wdrożeniem sprawdź jednak, gdzie przebiega granica wersji płatnej: analiza międzyplikowa i międzyfunkcyjna nie jest w otwartym kodzie, tylko w zamkniętej binarce pobieranej po zalogowaniu, a reguły ze zbioru społecznościowego mają własną licencję zakazującą redystrybucji. Bezpłatne i otwarte to tam dwie różne rzeczy.

Typowe błędy przy wdrożeniu

Pierwszy to instalacja pakietu oxc zamiast oxlint. Dostaniesz wtedy niepowiązany program z 2016 roku i żadnego ostrzeżenia.

Drugi to ustawienie pola plugins z myślą, że dokłada się ono do domyślnych. Nadpisuje. Lista musi zawierać wszystkie wtyczki, których chcesz używać, razem z unicorn, typescript i oxc, jeśli mają zostać.

Trzeci to przeniesienie reguły, której oxlint nie implementuje. Konfiguracja nie zgłasza wtedy ostrzeżenia, tylko odmawia wczytania: komunikat brzmi „Failed to parse oxlint configuration file” i wskazuje regułę nieznaną w danej wtyczce. Przepisywanie konfiguracji ręcznie, linijka po linijce, kończy się serią takich niespodzianek, dlatego lepiej puścić @oxlint/migrate, który nieobsługiwane reguły po prostu pomija.

Czwarty to instalacja z flagą pomijającą zależności opcjonalne. Bez pakietu @oxlint/binding-* odpowiedniego dla systemu nie ma czego uruchomić.

Piąty to Node starszy niż 20.19. Pole engines jest tu realnym ograniczeniem, a nie zapisem na wyrost.

Szósty to ustawianie typeAware albo typeCheck w konfiguracji zagnieżdżonej. Oba pola działają wyłącznie w pliku korzeniowym i w podkatalogu zostaną zignorowane bez słowa wyjaśnienia.

Siódmy to uruchomienie trybu --type-aware na repozytorium, którego korzeniowy tsconfig.json ma include ustawione na **/*. Powstaje wtedy jeden ogromny program obejmujący także wyniki budowania, a przebieg rozciąga się na minuty. Diagnoza jest prosta: przy OXC_LOG=debug widać w dzienniku linię z liczbą plików źródłowych w programie.

Ósmy to oczekiwanie, że oxlint sformatuje kod. Nie sformatuje, bo to zadanie oxfmt, który jest osobnym pakietem i osobną decyzją.

Dziewiąty to włączanie kategorii nursery bez przypięcia dokładnej wersji. Reguły z tej grupy zmieniają nazwy i zachowanie między wydaniami, a wydania wychodzą co tydzień.

FAQ

Czy oxlint zastąpi ESLinta w moim projekcie?

Zależy od konfiguracji. Jeśli opiera się na regułach rdzenia, typescript-eslint, unicorn, import, react albo jsx-a11y, pokrycie jest wysokie i oxlint sam wystarczy. Jeśli używasz wtyczek spoza listy czternastu wbudowanych, zostaje mechanizm jsPlugins w wersji alfa albo utrzymywanie obu narzędzi obok siebie.

Ile reguł ma oxlint w wersji 1.79.0?

Po włączeniu wszystkich kategorii i wszystkich wtyczek polecenie --print-config wypisuje 870 reguł. Bez żadnej konfiguracji aktywnych jest 111, bo domyślnie działa kategoria correctness oraz wtyczki unicorn, typescript i oxc.

Czy reguły wymagające informacji o typach działają?

Tak, po doinstalowaniu oxlint-tsgolint i uruchomieniu z flagą --type-aware. Pokrycie wynosi 59 z 61 reguł typowanych z typescript-eslint. Wymagany jest TypeScript 7.0 lub nowszy, a baseUrl w tsconfig.json nie jest obsługiwane.

Czym różni się oxlint od oxfmt?

Oxlint sprawdza kod i zgłasza problemy, oxfmt przepisuje go według reguł formatowania. To dwa osobne pakiety npm z osobną numeracją: 1.79.0 dla lintera, 0.64.0 dla formatera. Instalacja jednego nie daje drugiego.

Czy oxlint jest płatny?

Nie. Pakiet, wszystkie binaria i składnik oxlint-tsgolint są na licencji MIT, bez wariantu płatnego i bez ograniczeń komercyjnych. Firma VoidZero sprzedaje osobny produkt o nazwie Vite+, do którego dokumentacja migracji kieruje osoby szukające zintegrowanego łańcucha narzędzi.

Dokumentacja mieszka na stronie Oxc, przewodnik migracji w sekcji poświęconej ESLintowi, a kod źródłowy w repozytorium na GitHubie.

Czytaj dalej

Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie