# ESLint и Prettier

Кратко о библиотеках:

## ESLint

[Линтер](https://eslint.org/) - это помощник по части "здоровья" кода. Вы определяете список правил и в дальнейшем, при настроенном плагине в вашем редакторе, он как Microsoft Word "проферка орфографии" проверяет все, что вы написали.

Например, определили переменную, но нигде не используете? Сработает правило: no-unused-vars (долой неиспользуемые переменные) и переменная будет подчеркнута.

![no-unused-vars-eslint](https://3842968617-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8zv6fVL10WKBbo%2F-LvLmz1YS_tUOICnhzwj%2F-LvLnSDCF0-tuhPzkT37%2Fno-unused-vars-eslint.jpg?generation=1575561877123161\&alt=media)

Когда вы видите "подчеркивание", и после наведения видите в скобочках название правила - не нужно бежать гуглить. Нужно идти на сайт [eslint.org](https://eslint.org/) и там в "поиск" вставлять текст ошибки, будет быстрее.

![eslint-org-rule-search](https://3842968617-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8zv6fVL10WKBbo%2F-LvLmz1YS_tUOICnhzwj%2F-LvLnSDEwdJ4yC6A40b8%2Feslint-org-rule-search.jpg?generation=1575561877341435\&alt=media)

## Prettier

[Преттир](https://prettier.io/) - это помощник по части оформления кода. Можно писать с пробелами перед именем свойства, кавычками, запятыми в последней строке и тд тп - преттир, настроенный на сохранение или на пре-коммит хук - "перетрясет" ваши файлы и оформит их в соответствии с настройками, которых у него минимум. Это сделано специально, ибо чем меньше настроек, тем меньше конфигураций - когда-нибудь, спор "табы vs пробелы" уйдет в небытие, но кто выиграет?)

Одна из работ "преттира" - форматировать длинные строки.

Было:

![too-long-string](https://3842968617-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8zv6fVL10WKBbo%2F-LvLmz1YS_tUOICnhzwj%2F-LvLnSDGzt4AkcJdSIYy%2Ftoo-long-string.jpg?generation=1575561877315245\&alt=media)

Стало:

![too-long-string-after-prettier](https://3842968617-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8zv6fVL10WKBbo%2F-LvLmz1YS_tUOICnhzwj%2F-LvLnSDIvIVspzBJFibb%2Ftoo-long-string-after-prettier.jpg?generation=1575561877153562\&alt=media)

Я думаю преимущества очевидны, поэтому давайте настроим необходимые ускорители повседневной разработки.

## Настройка

Линтер встроен в create-react-app, но для работы в связке с Prettier, а так же для подсветки кода во время написания в VS Code нужна небольшая донастройка.

Для начала установите пакеты:

```
npm install eslint-config-prettier eslint-plugin-prettier prettier lint-staged husky --save-dev
```

Все пакеты в целом понятны зачем, кроме [lint-staged](https://github.com/okonet/lint-staged) и [husky](https://github.com/typicode/husky)

* husky - упрощает работу с git hooks ("пре-коммит" (момент, когда вы собираетесь делать коммит) легко настроить с помощью этой "собаки")
* lint-staged - пакет, который позволяет вам сделать обработку командой из терминала только тех файлов, которые собираются улететь в коммит.

*Husky* и *lint-staged* - сладкая парочка для борьбы с плохим кодом в нашем репозитории. Например, мы можем настроить, что если ESLint вернул ошибку, то коммит будет автоматически отменен. Вернемся к этому позже.

Итак, **настройка eslint**, создайте следующий файл в корне проекта:

*.eslintrc*

```javascript
{
  "extends": [
    "react-app",
    "prettier"
  ],
  "rules": {
    "jsx-quotes": [
      1,
      "prefer-double"
    ]
  },
  "plugins": [
    "prettier"
  ]
}
```

Достаточно скромный конфиг, который "наследует" стандартные правила (их много) из *react-app* и *prettier* (это глобальные конфиги, один встроен в create-react-app, второй мы установили посредством пакета [eslint-config-prettier](https://www.npmjs.com/package/eslint-config-prettier))

Затем я переопределил одно правило: [jsx-quotes](https://eslint.org/docs/rules/jsx-quotes) (для имен классов внутри JSX будут ставиться двойные кавычки. Не могу сказать, насколько это важно на сегодняшний день, но раньше у меня были конфликты с преттиром без этого правила).

Вы можете переопределить в списке любые правила, которые вас интересуют. Список можно найти в документации, но проще просто начать работать и по ходу пьесы смотреть на "подчеркивания". Те, которые вас не устраивают - переопределяйте.

Последняя опция в конфиге - использование плагинов. Мы используем плагин prettier (пакет [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier)), чтобы не было конфликтов между "помощниками" (напоминаю, у нас их два: prettier и eslint).

После настройки конфига, вам нужно настроить ваш редактор. Я приведу пример только для Visual Studio Code.

Добавьте в файл с настройками, следующие строки:

```javascript
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"[javascript]": {
    "editor.formatOnSave": true,
},
"[html]": {
    "editor.formatOnSave": false,
},
"[json]": {
    "editor.formatOnSave": false,
},
"eslint.autoFixOnSave": true,
"eslint.alwaysShowStatus": true,
```

Напоследок, для корректной работы вам потребуется парочка плагинов из маркет-плейса ([eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) и [prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)).

Мой список плагинов:

![my-plugins](https://3842968617-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8zv6fVL10WKBbo%2F-LvLmz1YS_tUOICnhzwj%2F-LvLnSDKxKzmxuSHjhmM%2Fmy-plugins.jpg?generation=1575561877197383\&alt=media)

Конфиг может быть настроен различными способами, например, взгляните на эти два видео:

* [Add ESLint & Prettier to VS Code for a Create React App](https://www.youtube.com/watch?v=bfyI9yl3qfE)
* [How to Setup VS Code + Prettier + ESLint](https://www.youtube.com/watch?v=YIvjKId9m2c)

Настроим prettier (нам так же нужен конфигурационный файл):

*.prettierrc*

```javascript
{
  "useTabs": false, // использовать табы? нет (я за пробелы)
  "printWidth": 80, // длина строки - 80
  "tabWidth": 2, // длина "таба" - 2 пробела
  "singleQuote": true, // использовать одинарные кавычки - да!
  "trailingComma": "es5", // запятая в последней строке - да
  "jsxBracketSameLine": false, // закрывающийся jsx в этой же строке
  "parser": "flow", // парсер - flow (пока не важно)
  "semi": false // точка с запятой - нет
}
```

Вот и все настройки. Настройка - parser, вам пока не должна мешать, а что такое trailingComma - пример ниже:

```javascript
const data = {
  name: 'Max',
  city: 'Moscow, // <-- traling comma ("висячая запятая")
}
```

Почему так? Мне это нравится, так как если добавится новое свойство, в *git difference* (изменения в файле) будет только одна строка, вместо двух (в одной добавилась бы запятая, во второй - новое свойство).

На данный момент, если вы будете писать код, у вас уже будет отрабатывать eslint. Так же в момент сохранения, код будет преобразовываться с помощью prettier. Однако, нам еще не хватает настройки пре-коммит хука.

Представьте ситуацию: вы работает с коллегой. Он пишет в блокноте, у него нет никаких "преттиров". Следовательно, чтобы он не закоммитил код, который не отформатирован как вам нужно, мы настраиваем пре-коммит хук. Это значит, в момент коммита, весь `js/jsx/json` код из директории *src*, который он "коммитит" будет преобразован преттиром, так же, как если бы он преобразовался при сохранении в вашем редакторе.

*package.json*

```javascript
{
  "name": "redux-course-ru-v2",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-scripts": "1.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject",
    "precommit": "lint-staged"
  },
  "devDependencies": {
    "eslint-config-prettier": "^2.9.0",
    "eslint-plugin-prettier": "^2.6.2",
    "husky": "^0.14.3",
    "lint-staged": "^7.2.0",
    "prettier": "^1.14.0"
  },
  "lint-staged": {
    "*.{js, jsx}": [
      "prettier --write",
      "git add"
    ]
  }
}
```

В секции scripts добавилась команда *precommit*, и добавилось свойство lint-staged с настройками.

Теперь в момент коммита, в терминале будет похожая ситуация:

![git-commit-husky](https://3842968617-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8zv6fVL10WKBbo%2F-LvLmz1YS_tUOICnhzwj%2F-LvLnSDMZVfri5bTpm1M%2Fgit-commit-husky.jpg?generation=1575561877034875\&alt=media)

Резонный вопрос, у коллеги с блокнотом, у него и ESLint отсутствует же? Верно. Нужно усложнить ему жизнь и "обламывать" коммит, если в нем есть ошибки/предупреждения от ESLint.

Удалите `<TestComponent />` из отрисовки в `<App />`, но оставьте создание переменной.

*src/App.js*

```jsx
import React, { Component } from 'react'
import './App.css'

const TestComponent = () => <p>просто render</p>

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    )
  }
}

export default App
```

Выполните команду в терминале (находясь в директории с проектом):

```
node_modules/.bin/eslint src/
```

![eslint-warning-terminal](https://3842968617-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8zv6fVL10WKBbo%2F-LvLmz1YS_tUOICnhzwj%2F-LvLnSDOAYTKCbqvpzMP%2Feslint-warning-terminal.jpg?generation=1575561877746998\&alt=media)

Так как я не люблю глобальные зависимости, я использую локально установленный eslint (его установил для нас create-react-app). Чтобы упростить вызов в терминале, можно добавить в секцию *scripts* в *package.json* новую команду:

*package.json*

```javascript
...
"scripts": {
  "start": "react-scripts start",
  "build": "react-scripts build",
  "test": "react-scripts test --env=jsdom",
  "eject": "react-scripts eject",
  "precommit": "lint-staged",
  "eslint": "node_modules/.bin/eslint src/"
},
...
```

Теперь eslint в терминале можно запускать так: `npm run eslint`. После запуска этой команды, eslint проверит весь src/ на наличие ошибок/предупреждений. Это полезно сделать в начале внедрения "жесткого пре-коммита" и лично исправить все ошибки, чтобы команда научилась на хорошем примере.

Вернемся к настройке. Изменим lint-stage скрипт в package.json на:

```
"lint-staged": {
  "*.{js, jsx}": [
    "node_modules/.bin/eslint --max-warnings=0",
    "prettier --write",
    "git add"
  ]
}
```

Теперь в момент пре-коммита будет запускаться lint-staged проверка в которой eslint и prettier обработают все файлы, готовящиеся к коммиту.

Что интересно, я настроил еслинт агрессивно (опция `--max-warnings=0`), то есть, даже любое предупреждение прервет коммит.

Проверим:

![eslint-fall-max-warnings-0](https://3842968617-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvLmy8zv6fVL10WKBbo%2F-LvLmz1YS_tUOICnhzwj%2F-LvLnSDQn96V3VrDJTAf%2Feslint-fall-max-warnings-0.jpg?generation=1575561877644800\&alt=media)

На скрине видно "вредный совет". Да, если добавить `--no-verify` к команде `git commit`, то проверок не будет. Но за это сразу бейте по рукам.

**Итого**: Настроили ESLint, prettier и pre-commit hook. Очень сильно облегчили жизнь себе и коллегам, кто болеет за единый стиль и чистый код.

[Исходный код](https://github.com/maxfarseer/redux-course-ru-v2/tree/chp2-setup-eslint-and-prettier) (без ошибок).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://max-frontend.gitbook.io/redux-course-ru-v2/chapter1/eslint-i-prettier.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
