Oxlint и кастомные правила на JS
• build
Введение
Oxlint – линтер на Rust, который пытается покрыть ESLint из коробки. В частности, он поддерживает 841 (на момент написания статьи) правило, включая пачку правил из популярных плагинов к ESLint.
Более того, несмотря на выход TypeScript 7, у которого всё ещё нет апи, Oxlint предлагает поддержку правил из typescript-eslint на основе информации о типах, используя новый TS на Go!
И, в отличии от предыдущей статьи, к Oxlint можно писать свои правила. Не только на Rust, а на JS (альфа-версия). Вот этим и займёмся, а заодно посмотрим, что из этого выйдет.
Чуть больше про плагины
Oxlint старается воспроизвести апи ESLint 1-в-1, чтобы существующие плагины просто работали. Например, eslint-plugin-playwright проходит 99.9% тестов.
Но они пошли дальше, и сделали “подвариант” этого апи, чтобы линтинг работал быстрее. Когда-то в будущем. Правила в этом варианте апи будут работать и в ESLint, и в Oxlint.
Я рекомендую ознакомиться со страницей в документации, чтобы узнать больше деталей.
В рамках текущего поста попробуем использовать именно альтернативное апи.
Пишем плагин
Для примера я решил сделать простое правило – проверку, что все идентификаторы содержат только латиницу / цифры и ещё пару символов. Ведь все мы любим находить русские “с” в неожиданных местах! По сути, это некоторый аналог eslint-plugin-ascii или встроенного правила id-match с регуляркой.
Пишем правило с плагином:
// plugin.js
import { eslintCompatPlugin } from '@oxlint/plugins';
const RE = /^[a-z0-9$_]+$/i;
const rule = {
createOnce(context) {
return {
Identifier(node) {
if (!RE.test(node.name)) {
context.report({ message: 'Incorrect id', node });
}
},
};
},
};
export default eslintCompatPlugin({
meta: {
name: 'my-plugin',
},
rules: {
'restrict-ids': rule,
},
});Отличия от обычного апи плагинов ESLint – обёртка eslintCompatPlugin и createOnce вместо create.
Дописываем в конфиг и проверяем – работают оба линтера:
npx eslint test.js
npx oxlint test.jsСверяем скорость
Для проверки я взял тот же файл, который использовал для проверки плагинов к SWC/OXC, размножил его 10 раз (чтобы утилизировать многопоточность), а дальше прогнал каждый линтер по маленькому файлу и по этим 10 (примерно 21 МБ JS кода).
Один простой файл:
| Время | |
|---|---|
| Oxlint | 0.45s |
| ESLint | 0.47s |
Десять больших файлов:
| Время | |
|---|---|
| Oxlint+plugin | 1.32s |
| Oxlint+id-match | 0.48s |
| ESLint+plugin | 4.5s |
Время простого файла я взял, чтобы посчитать время на “инициализацию” каждого инструмента. Делаю это с прицелом на то, как это будет работать на больших проектах (где время инициализации будет не так важно). Итого время на сложные файлы без “инициализации”:
| Время | |
|---|---|
| Oxlint+plugin | 0.87s |
| Oxlint+id-match | 0.03s |
| ESLint+plugin | 4.03s |
Выводы. “Чистый” Oxlint значительно превосходит ESLint по скорости (на несколько порядков?). Если мы добавляем плагин на JS, то это значительно замедляет Oxlint, но всё равно такая конструкция быстрее в разы.
Кроме того, теоретически можно написать плагин к Oxlint на Rust. Несмотря на то, что способ уже не очень рекомендуется, потенциал по скорости в нём огромный. Если вдруг вы упрётесь в скорость JS плагинов, такая возможность есть, и это здорово.
Соображения по удобству
Уже сейчас Oxlint позволяет задавать конфиги и плагины в TS (ESLint требует дополнительный пакет). Тайпинги к конфигу есть, а вот с кастомным правилом беда, тайпингов нет (в явном виде), тут ESLint впереди.
Конфиг Oxlint на первый взгляд больше напоминает старый формат ESLint, чем новый FlatConfig.
Oxlint завёлся без проблем. Правило через слой совместимости завелось с первого раза и там и там.
Документация есть, сотни страниц документации на каждое правило в наличии.
Итого
Авторы Oxlint замахнулись одновременно на простую замену ESLint из коробки и на целую кучу плагинов сверху в придачу.
Несмотря на “статус” альфы, плагины заводятся за 5 минут. Готовые пакеты из npm, судя по всему, тоже.
Чудовищная скорость и обилие встроенного функционала без дополнительных зависимостей являются значимым достоинством.
Перед нами идеальный “убийца” ESLint? Без серьёзного использования в крупном проекте сказать нельзя, но как кандидат на пристальное изучение и эксперименты – 100%.
Обсудить в Telegram



