Putout: линтер нового поколения
В 2015 году Николас Заказ опубликовал статью с похожим названием, только вместо Putout было ESLint. В те времена это было действительно так, ESLint безусловно стандарт дефакто в мире JavaScript линтеров. Однако совершенству нет предела, и любому успешному инструменту приходит на смену еще более успешный, либо дополняет его устраняя недостатки. Об одном из таких инструментов мы сегодня поговорим, однако начать хотелось бы с истории.
История линтеров
Начнем с истоков, чтобы было понятно откуда ноги растут, после чего перейдем к самым популярным решениям на JavaScript.
1972 — Стивен Джонсон создает первый линтер в Bell Labs, он проверяет наличие ошибок в коде на C. Слово «Lint» означает что-то вроде «комков волокон в хлопковой ткани».
2002 — Дуглас Кроуфорд создает первый JavaScript линтер JSLint с несвободной лицензией The Software shall be used for Good, not Evil. И сообщество с радостью (бы) приняло такой полезный инструмент, но были недостатки: правила (почти) нельзя конфигурировать, в нем минимум настроек.
2011 — Антон Ковалев создает форк JSHint лишенный недостатка предшественника имеет возможность обильной конфигурации, однако монолитен и не расширяем.
2013 — Николас Закас не выдерживает отсутствия плагинов в JSHint и пишет свой линтер о котором знает каждый js-разработчик: ESLint.
2018 — Coderaiser пишет инструмент, который удаляя неиспользуемые переменные, делает то, что ESLint, делать отказывается, а именно: использует правила, которые могут изменить поведение кода.
Что не так с существующими линтерами
В JavaScript Community все более-менее утряслось, и остался один линтер, выживший либо вмердживший в себя конкурентов. ESLint и правда делает очень многие вещи достаточно качественно. Но все не так просто, и есть набор моментов, который, скажем так, можно было бы улучшить:
- Нет состояния прогресса. В 2020-ом году, мы каждый день запускаем инструмент, который неизвестно когда завершит работу. Да, на маленьких проектах это не заметно и не существенно. Но фронтенд сейчас очень сильно разросся, и плагинов, и правил существует довольно-таки много, и проверка может вполне выполняться несколько минут. Как минимум, это не удобно.
- Переусложненная система плагинов. Да она быстрая, эффективная, но очень уж многословная:
- Наличие такой концепции как warning: зачем? Если нашел проблему — возьми и исправь, зачем о ней говорить, помечая желтым цветом. Постоянные напоминания о чем-то, что не сильно важно не имеют смысла.
- Отсутствие опции --fix для огромного количества правил. Это сейчас ESLint двигается в сторону autofix, но делает он это крайне плавно, и само наличие правил, которые не исправляются сами, лично меня напрягает.
В чем ключевая идея Putout
Владея основной информацией о том, что не так с существующими решениями, было решено сделать продукт в соответствии со следующими принципами:
- Возможность отображения статуса прогресса.
- Каждое правило имеет возможность исправления.
- Правила могут минимально менять поведение кода, если это делает его лучше.
- Правила имеют полные и конкретные названия (convert-equal-to-strict-equal в противовес eqeqeq).
- Нет ворнингов, есть только ошибки.
- Максимально дополнять ESLint, не дублируя его работу, косметические правки имеет смысл оставить ему.
- 100% покрытие тестами (сейчас их более 1400)
- Писать и тестировать плагины должно быть просто и легко.
- Маленькое ядро, вся система состоит из плагинов.
- Интеграция с существующими решениями.
Архитектура
Основной механизм работы Putout состоит из работы трех модулей:
- parser — парсит код в AST, а затем AST обратно в код
- loader — загружает плагины
- runner — запускает на выполнение плагины
Плагины
Встроенные плагины поддерживают 4 вида интерфейсов, начиная от самых простых, и заканчивая сложными. Благодаря этому putout содержит в себе больше 50 плагинов, каждый из которых является отдельным npm-пакетом, то есть при обновлении плагина, update придет пользователям более старых версий Putout наравне с пользователями новых версий.
Интеграция с существующими решениями
Putout поддерживает все самые популярные парсеры JavaScript кода, а так же системы написания кодмодов, такие как jscodeshift. Кроме этого может использоваться как плагин для ESLint (благодаря чему попадает во все IDE), плагин для babel, а также имеет возможность запуска ESLint для форматирования файла, после внесения изменений, а так же встроенную поддержку работы со staged файлами в git и улучшенную работу кэша (кэшируются результаты проверки всех правил Putout, и только встроенных правил eslint).
Послесловие
Я не рассказал как установить, использовать и настраивать Putout поскольку уже говорил об этом в одной из предыдущих статей, хочу лишь добавить, что все замечания написанные в комментариях были учтены и исправлены. Всем спасибо за внимание:).