Хабрахабр

Лошадь сдохла – слезь: переход с tslint на eslint

До недавнего времени во всех проектах фронта разработчики Dodo Pizza Engineering использовали tslint – полезный инструмент, который подсказывает, когда ты накосячил в коде допустил неточность, помогает поддерживать код в одном стиле и сам исправляет многие замечания. Но тут tslint взял и умер. Под катом я расскажу, почему так вышло, как перестать лить слёзы по умершему и перейти на инструмент eslint, а также покажу кое-что очень интимное.

И это тот момент, когда пора начать говорить «последний», если кто-то до сих пор говорит «крайний», потому что тот релиз был действительно последним.
На самом деле, началось всё довольно давно: последний релиз ядра tslint был аж в 2016 году. В нём компания-разработчик (кстати, это даже не Microsoft) настоятельно советует переходить всем на eslint, так как их усилия теперь будут направлены на улучшение поддержки TypeScript в этом линтере. 19 февраля 2019 года вышел официальный пост о прекращении разработки tslint.

Один язык, один стек, одно комьюнити

Microsoft видит TypeScript, как основной язык веб-разработки, который должен вытеснить Java/ECMA Script. Очевидно, что такая амбициозная цель подразумевает единый стек инструментов для всей фронтовой разработки. Это должно существенно упростить миграцию большого комьюнити JS на TypeScript. Кроме гаранта доверия от Microsoft, у eslint архитектура лучше, чем у tslint. Например, можно подключать парсеры, а также выбор подключаемых правил больше.

Что бы мы не говорили про качество их ПО, но инструменты разработки они делают отличные (и, кстати, устройства ввода). Microsoft не был бы собой, если бы просто хотел. В соответствие с этим планом, разработка правил tslint уже прекращена 1 авгуcта 2019, а 1 ноября 2019 прекратится и разработка самого tslint. Вот и в этот раз они пришли не с пустыми руками, а написали план миграции. выше про последний релиз). Хотя, если быть честными, разработка прекращена уже давно (см.

Чтобы подсластить пилюлю, стоит сказать что: Здесь читателю должно стать очевидно, что пора переходить на eslint, другого выбора нет.

  • в то время, как tslint ориентирован на TypeScript с бОльшим уклоном в правильное использование типов и проверку синтаксиса, eslint покрывает всё, что может быть во фронте, включая синтаксис React-компонентов;
  • в eslint гораздо больше готовых правил;
  • есть правила (и плагины), которые проверяют код на уровне блоков (дублирование кода, воспринимаемая сложность т.п.);
  • есть плагины, которые проверяют вообще не код, а, например, регулярные выражения.

В общем, выглядит так, что переход на новый линтер, который являет собой мейнстримовый продукт, откроет нам целый мир ранее невиданных возможностей. Что ж, попробуем!

Добавляем eslint в проект

Про миграцию правил расскажу ниже. А пока настроим проект для работы с eslint.
Если у вас уже есть проект с tslint, то для начала удалите из него все пакеты, имеющие отношение к tslint: сам tslint, tslint-react, tslint-config-prettier и т.п.

Теперь добавьте в проект пакеты eslint (все ставим как devDependencies):

  • сам eslint;
  • @typescript-eslint/parser – движок парсинга TypeScript;
  • @typescript-eslint/eslint-plugin – наборы правил для TypeScript

Минимальная настройка eslint

Создаём файл конфигурации .eslintrc.json. Eslint поддерживает много форматов файлов для своей конфигурации, но JSON кажется самым удобным. Вот как выглядит минимальный рабочий вариант:

, // Наборы правил "extends": [ // Базовый набор правил eslint "eslint:recommended", // Отключаем правила из базового набора "plugin:@typescript-eslint/eslint-recommended", // Базовые правила для TypeScript "plugin:@typescript-eslint/recommended", // Правила TS, требующие инфо о типах "plugin:@typescript-eslint/recommended-requiring-type-checking" ], // Движок парсинга "parser": "@typescript-eslint/parser", "parserOptions": { // Движку нужен проект TS для правил с типами "project": "tsconfig.json", "tsconfigRootDir": ".", }, // Плагин с наборами правил для TypeScript "plugins": ["@typescript-eslint"], "rules": {}
}

Раздел env рассказывает eslint о параметрах вашего проекта. В моём примере – это проект для браузера (т.е. код будет работать в браузере). Пишите для Node.JS – ставьте node: true. Две последующие опции указывают на диалект проверяемого JS. Вообще, мы будем проверять код на TypeScript, но если в вашем проекте есть код и на JS, то не забудьте их подкрутить. Для себя мы решили, что ставим эти параметры в такое же значение, как и target в tsconfig.json.

Все правила однозначно полезные. В стандартных набораx правил eslint нет ничего спорного, вроде обязательной точки с запятой в конце выражений или пробелов/табов. Посмотреть, какие правила и с каким уровнем включаются, можно здесь.

Это необходимо, потому что они не работают с TypeScript и вместо нормальной работы будут сыпать кучу ошибок. Следующей же строкой вам необходимо отключить половину правил.

Здесь нужно иметь в виду, что общие синтаксические правила (типа запрета var) будут работать и так. Затем следует подключить рекомендованные правила из TypeScript отдельным пакетиком.

А движку будет нужен файл tsconfig.json, путь до которого необходимо указать. А вот для правил, использующих типы TS (например, @typescript-eslint/no-unnecessary-type-assertion), необходим движок TypeScript.

Но для работы eslint необходимо указать и include. В tsconfig.json мы в Dodo Pizza Engineering обычно указываем exclude и выкидываем тесты, чтобы они не билдились вместе с проектом. Без этого eslint будет ругаться на каждый файл, который он найдет: «Файл не в проекте, я ничего делать не буду, буду сыпать кучу ошибок». То есть все файлы, которые нужно линтить, должны быть включены в проект явно. Это, по сути, значит: «Всё, что найдешь – парси». Есть вариант без явного указания файлов проекта – установить параметр createDefaultProgram: true. Но делать так разработчики настоятельно не советуют из-за существенного падения производительности.

Если для обработки файлов TypeScript вы используете ForkTsCheckerWebpackPlugin, то замените в его параметрах (в webpack.config.ts) tslint: true на eslint: true.

До этого добавьте такое значение в раздел scripts в package.json: Также стоит настроить запуск линтера из командной строки.

"eslint": "eslint --cache --ext .js,.jsx,.ts,.tsx src", "eslint:dump": "eslint --print-config ./.eslintrc.json",

Первая строка просто запускает проверку eslint без сборки проекта. Вторая выводит актуальные настройки eslint, что позволяет увидеть настройки параметров правил.

В таком варианте eslint в проекте уже будет работать и даже ловить некоторые косяки: переопределение globals, неиспользуемые переменные и т.п.

Настройка Visual Studio Code

После того, как вы проделали весь этот путь, уже можете запустить линтер из командной строки. Также он будет неявно запущен при сборке проекта. Но в Visual Studio Code замечаний от линтера мы не увидим. Да как так-то?!

После этого ничего всё равно не заработает, ничего не будет подчёркиваться и исправляться. Для студии есть плагин eslint (dbaeumer.vscode-eslint), его нужно поставить. Потому что у плагина есть конфиг, в котором написано, что работать нужно только в файлах JavaScript. Почему?

Полный список языков можно найти в недрах документации студии. Эта подлая настройка не вынесена в UI, поэтому нужно зайти в файл настроек студии и добавить вручную нужные вам языки в параметр eslint.validate. Вот как выглядит эта настройка у нас:

"eslint.validate": [ "javascript", "javascriptreact", "typescriptreact", "typescript", ],

После этого перезапустите студию, и всё наконец-то начнёт работать.

Теперь осталось настроить правила

Проект настроили. Теперь про правила, ведь в примере выше список правил был пуст.

Например, забывать await. Должен сказать, что tslint никак не мешал нам косячить в формально корректном коде. Сюда же относятся стилистические проблемы среднего уровня сложности: использование лямбды или function и т.п., что уже не умеет Prettier. Eslint умеет находить подобные семантические ошибки и ругаться на них: сообщать, что возвращаемое значение – Promise, но для него, почему-то, не написан await.

spaces и т.п., есть мнение, что их следует отдать в Prettier или подобный пакет. Что касается простых правил: положение скобок, tabs vs. Более того, этот рубеж можно автоматизировать: например, husky, позволяет запускать линтер автоматически на каждый commit. Но в линтере их следует оставлять всё равно: это последний рубеж, который ещё способен остановить нерадивого разработчика упавшей сборкой проекта.

А создать свой набор с нуля. Мы решили не мигрировать ни один из наборов правил tslint, что есть у нас.

Для eslint есть готовые наборы правил:

  • ESLint Recommended – нейтральный набор правил, который сделан с мыслью о том, чтобы не порождать холивары. Включены только очевидно необходимые проверки: неиспользуемые переменные и т.п. Все последующие наборы расширяют этот.
  • Google – здесь уже есть повод для холивара: для отступов строго пробелы, точка с запятой обязательна.
  • AirBnB – здесь также есть строгие правила стиля, включая обязательную точку с запятой.
  • Standart – здесь запрещена точка с запятой, но запрещены и завершающие запятые.

Ни один из готовых пакетов нам не понравился. Это может прозвучать странно, но для нас важно перейти на новый линтер, избежав стилистических войн. Если уж мы везде так пишем (табы, без точки с запятой, завершающие запятые обязательны), то пусть оно так и остаётся – главное, чтобы одинаково во всех проектах.

Обещанный интим: свой набор правил

Честно сказать, показать свой набор правил eslint – это как девушке показать сиськи: секретов больше нет. Я долго думал, стоит ли так делать. Но, посоветовавшись с коллегами-девушками, решил, что стоит.

Начну с плагинов, которые мы используем:

  • react – проверки для кода react-компонентов. Базовый набор правил плюс наши. Из важного: топим за pure functional компоненты;
  • react-hooks – правила от разработчиков react про использование хуков;
  • promise – проверки на типичные ошибки при использовании Promise. Немного странно работает с кодом на TypeScript. Из важного: стараемся везде использовать Promise и не использовать колбеки и then/catch из-за лучшей читаемости кода;
  • optimize-regex – забавный плагин, который даёт советы по улучшению регулярных выражений. Не слишком полезный, ибо regexp у нас немного. Но и владеют магией regexp далеко не все. Так что бывает полезно, а есть много не просит;
  • sonarjs – огонь-плагин с проверками на сложность кода и типичные ошибки рефакторинга. Первое – забавная штука: плагин оценивает воспринимаемую сложность кода и даёт совет, когда код стоит упростить. Поиск ошибок рефакторинга часто позволяет также упростить код или, как минимум, улучшить читаемость;
  • @typescript-eslint – правила eslint для проверки кода на TypeScript. И набор для отключения базовых правил, не совместимых с TS.

Целиком наш файл правил лежит здесь. Отмечу, что он не является догмой и обновляется по мере адаптации в проекты.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть