Важно выдерживать единый стиль написания кода в проекте, особенно если он выполнен на JavaScript и TypeScript. Это связано с тем, что JavaScript — очень гибкий язык, а TypeScript, хотя и менее гибок в синтаксисе, все же достаточно гибок в форматировании.
Представьте, что в одной части кода используется 2 пробела для отступа, а в другой — 4. Вы можете подумать, что подобный линтинг носит лишь косметический характер. Тем не менее линтеры могут также проверять синтаксис и помогать улучшать качество кода в соответствии с общепринятыми отраслевыми стандартами.
Проверять качество кода и стили его написания вручную довольно обременительно. К счастью, с помощью Git-хуков это можно сделать автоматически, а автор кода не сможет создавать коммиты, если линтинг не был пройден.
Для проектов JavaScript и TypeScript разработано несколько хорошо зарекомендовавших себя пакетов, которые можно использовать для линтинга и управления Git-хуками. В этой статье речь пойдет о том, как создать хук Git pre-commit для проверки кода JavaScript и TypeScript с помощью ESLint, Prettier, lint-staged и Husky.
Установка и настройка ESLint
Настроить ESLint сложнее, чем пакеты, упомянутые выше.
Чтобы сделать это быстро, выполните команду для установки и конфигурации ESLint с помощью мастера:
$ npm init @eslint/config
Выберите параметры, которые лучше всего подходят для проекта, и файл package.json
будет обновлен соответствующим образом. Автоматически создастся файл .eslintrc.js
на основе сделанного вами выбора. Вам потребуется внести в него некоторые изменения, чтобы он соответствовал вашим требованиям. В этой статье будет использоваться этот файл .eslintrc.js
.
Установка и настройка Prettier
Если проект содержит только код JavaScript и TypeScript, анализатора ESLint обычно достаточно, поскольку он может выполнять проверку синтаксиса и формата. Однако если в проекте есть также файлы HTML и CSS, потребуется установить Prettier — специальный инструмент для форматирования кода. Кроме того, поскольку Prettier доступен в большинстве IDE (например, VS Code), для автоматического форматирования кода удобнее использовать Prettier, чем ESLint.
Выполните следующую команду для установки Prettier:
$ npm install prettier eslint-plugin-prettier eslint-config-prettier --save-dev
Обратите внимание: кроме пакета Prettier также устанавливаются два пакета для ESLint. Таким образом, Prettier может работать совместно с ESLint, поскольку эти инструменты обладают схожими функциями в плане форматирования кода.
В большинстве случаев достаточно оставить настройки Prettier по умолчанию. Однако, если нужны особые стили, добавьте их в файл с именем .prettierrc.json
в корневой папке проекта. Можно также непосредственно добавить опции в командную строку, если их не слишком много. Перейдите по этой ссылке, чтобы ознакомиться со всеми опциями форматирования для Prettier.
Установка и настройка lint-staged
По умолчанию линтеры, такие как ESLint и Prettier, проверяют все файлы в проекте. Однако это крайне неэффективно. При создании коммита нужно, чтобы линтеры проверяли только те файлы, которые были изменены или индексированы. Файл индексируется, когда вы выполняете git add
, чтобы добавить его в область индексирования. Именно здесь поможет пакет lint-staged, который позволяет линтить только индексированные файлы.
Чтобы установить lint-staged, выполните команду:
$ npm install --save-dev lint-staged
Чтобы настроить lint-staged, можно создать либо новый объект под названием lint-staged
в package.json
, либо новый файл .lintstagedrc.json
в папке проекта. Последний вариант предпочтительней, если у вас сложные настройки. Однако здесь будет использовать первый вариант, поскольку в данном случае настроек немного:
"lint-staged": {
"*.ts": "npx tsc --noEmit",
"*.{js,jsx,ts,tsx}": "npx eslint",
"*.{js,jsx,ts,tsx,html,css}": "npx prettier --check"
}
Мы определяем три задачи для lint-staged. По умолчанию lint-staged будет выполнять их параллельно. Поэтому потребуется особое внимание, если один и тот же файл изменяется разными задачами. Результат может быть непредсказуемым из-за эффекта гонки. Необходимо убедиться в том, что настройки разных линтеров не конфликтуют. При необходимости можно отключить параллелизм, указав в командной строке для lint-staged
параметр --concurrent false
:
# Запустить задачи параллельно:
$ npx lint-staged
# Запустить задачи последовательно:
$ npx lint-staged --concurrent false
Обратите внимание, что при сбое одной задачи все остальные будут пропущены или завершены.
Установка и настройка Husky
Выше мы запустили lint-staged вручную с помощью npx
. Если нужно обеспечить линтинг до создания коммита, следует запустить lint-staged в Git-хуке pre-commit. Этот хук является просто запускаемым скриптом, который выполняется перед созданием коммита. В него можно поместить любой код, и код линтинга — идеальный пример для использования.
Вот три способа добавить код линтинга для lint-staged в хук pre-commit.
- Создать хук pre-commit вручную и добавить в него приведенную выше команду для запуска lint-staged. Это немного громоздко, поскольку придется вручную скопировать и перенести хук pre-commit в папку
.git/hooks/
. - Использовать программу установки pre-commit. Это удобно, если есть только хуки pre-commit, и нет других типов Git-хуков, таких как commit-msg и pre-push.
- Использовать Husky! Husky поддерживает все Git-хуки. В настоящее время это самый популярный способ управления Git-хуками в проекте JavaScript/TypeScript, и мы выберем именно этот вариант.
Чтобы установить Husky и инициализировать проект с его помощью, выполните следующую команду:
$ npx husky-init && npm install
В папке проекта будет создана папка с именем .husky
, которая включает в себя специальную папку, названную знаком подчеркивания _
, и шаблон хука pre-commit. Кроме того, в package.json
добавляется новый скрипт prepare
, который запускает команду husky install
. Скрипт prepare
создаст папку .husky
до упаковки пакета.
Добавим команду для запуска lint-staged в хук pre-commit в папке .husky
:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
Этот хук pre-commit будет вызываться перед созданием коммита в текущем проекте. Нужно добавить его и в папку проекта, чтобы он сохранялся в проекте при его переносе в удаленный репозиторий. Не стоит переживать: он не будет перезаписан командой husky install
.
$ git add package.json
$ git add package-lock.json
$ git add .husky/pre-commit
$ git commit
Теперь, когда вы попытаетесь создать коммит для файла, соответствующего шаблонам, определенным lint-staged, как показано выше, произойдет автоматический вызов хука pre-commit. Будут проверены только индексированные файлы:
[lynn@js-ts-git-hooks]$git add src/example.ts
[lynn@js-ts-git-hooks]$git commit
✔ Preparing lint-staged...
❯ Running tasks for staged files...
❯ package.json — 1 file
❯ *.ts — 1 file
✖ npx tsc --noEmit [KILLED]
❯ *.{js,jsx,ts,tsx} — 1 file
✖ npx eslint [KILLED]
❯ *.{js,jsx,ts,tsx,html,css} — 1 file
✖ npx prettier --check [FAILED]
↓ Skipped because of errors from tasks. [SKIPPED]
✔ Reverting to original state because of errors...
✔ Cleaning up temporary files...
✖ npx prettier --check:
[warn] src/example.ts
[warn] Code style issues found in the above file. Forgot to run Prettier?
Checking formatting...
✖ npx eslint failed without output (KILLED).
✖ npx tsc --noEmit failed without output (KILLED).
husky - pre-commit hook exited with code 1 (error)
Мы успешно настроили хук Git pre-commit, который помогает поддерживать стандарты написания и форматирования кода. Теперь не получится добавить коммит с файлом, нарушающим правила, определенные линтерами. Это делает кодовую базу менее подверженной ошибкам, более простой в обслуживании и более приятной для чтения.
Весь код, представленный в этой статье, можно найти в этом репозитории.
Читайте также:
- GitHub Actions и Vercel — быстрое развертывание проектов
- Как удалять локальные ветки с помощью псевдонимов Git
- Руководство для начинающих по Git: что такое журнал изменений и как его создать
Читайте нас в Telegram, VK и Дзен
Перевод статьи Lynn Kwong: Create a Pre-commit Git Hook to Check and Fix Your JavaScript/TypeScript Code Automatically