Всегда чистый код: 5 инструментов для JavaScript-разработчика

Хотите научиться писать чистый код, но не знаете, с чего начать? Начните с хороших инструментов, которые сделают все за вас.

Если вы уже пытались покорить неприступную крепость "чистого кода", то знаете, что это совсем непросто. Мертвый код, неиспользуемые переменные, несоответствие типов, потенциально проблемные шаблоны… Нужно проследить за столькими вещами, что голова идет кругом, а руки опускаются.

Или, быть может, вы руководитель команды разработчиков и беспокоитесь, что ваши подопечные напишут код, не соответствующий стандартам вашего проекта. Из-за этого вы вынуждены долгими часами проверять форму вместо действительно важного содержания.

Все это утомительно, беспокойно и просто бессмысленно. Забудьте об этом. В конце концов, вы же программист! Так переложите ответственность за чистый код на машину.

Давайте вместе разберемся с пятью лучшими инструментами в арсенале веб-разработчика: Prettier, ESLint, Husky, Lint-Staged и EditorConfig. Чтобы увидеть, как они используются на практике, загляните в этот репозиторий.

Prettier

Prettier – инструмент, который будет форматировать ваш код за вас. Примерно вот так:

У Prettier есть огромные преимущества:

  • Чистит весь код проекта. В качестве альтернативы можете самостоятельно пересмотреть 20 тысяч строк кода.
  • Без проблем настраивается под нужды конкретного проекта.
  • Позволяет сконцентрироваться на главном. Вы даже не представляете, сколько времени и энергии тратите на форматирование. Займитесь логикой приложения, а его красотой займется Prettier.
  • Облегчает жизнь новичкам. Благодаря настроенным правилам молодые программисты могут работать вместе с профессиональными разработчиками.

Настройка

Создайте директорию app и инициализируйте проект с помощью команды npm init -y. Дальше в примерах будет использоваться yarn, но вы можете продолжать управлять пакетами через npm.

Установите первый пакет:

yarn add --dev prettier

package.json теперь выглядит так:

{
  "name": "react-boiler-plate",
  "version": "1.0.0",
  "description": "A react boiler plate",
  "main": "src/index.js",
  "author": "Adeel Imran",
  "license": "MIT",
  "scripts": {
    "prettier": "prettier --write src/**/*.js"
  },
  "devDependencies": {
    "prettier": "^1.14.3"
  }
}

Через секунду мы разберемся, что делает строка "prettier": "prettier --write src/**/*.js" в секции scripts, но сначала создайте внутри директории приложения новую папку src, а внутри нее – файл index.js со следующим кодом:

let person =                     {
  name: "Yoda",
                designation: 'Jedi Master '
                };


              function trainJedi (jediWarrion) {
if (jediWarrion.name === 'Yoda') {
  console.log('No need! already trained');
}
console.log(`Training ${jediWarrion.name} complete`)
              }

trainJedi(person)
              trainJedi({ name: 'Adeel',
              designation: 'padawan' 
  });

Это выглядит ужасно, очень ужасно. Что вам теперь делать с этим уродливым кодом?

  • расставьте отступы вручную или...
  • используйте специальный инструмент форматирования или...
  • не переживайте и работайте дальше (нет-нет-нет, не делайте этого).

У нас уже почти все готово для реализации второго варианта, осталось лишь создать файл конфигурации для Prettier. Он называется prettier.config.js.

module.exports = {
  printWidth: 100,
  singleQuote: true,
  trailingComma: 'all',
  bracketSpacing: true,
  jsxBracketSameLine: false,
  tabWidth: 2,
  semi: true,
};

Пробежимся по настройкам:

  • printWidth следит, чтобы строчки кода были не длиннее 100 символов.
  • singleQuote меняет двойные кавычки на одинарные.
  • trailingComma расставляет висящие запятые после последнего свойства объектов.
  • bracketSpacing ставит пробелы после открывающей и перед закрывающей скобками объектных литералов.
    If bracketSpacing is true - Example: { foo: bar }
    If bracketSpacing is false - Example: {foo: bar}
  • jsxBracketSameLine помещает закрывающую угловую скобку > JSX-элемента на последнюю строчку:
    // true example
    
    <button
      className="prettier-class"
      id="prettier-id"
      onClick={this.handleClick}>
      Click Here
    </button>
    
    // false example
    
    <button
      className="prettier-class"
      id="prettier-id"
      onClick={this.handleClick}
    >
      Click Here
    </button>
  • tabWidth регулирует размер символа табуляции.
  • semi расставляет везде точки с запятой.

Вот список всех возможных опций Prettier.

Теперь давайте разберемся, как работает этот скрипт:

"prettier": "prettier — write src/**/*.js"

Он запускает Prettier, дает ему команду найти все файлы с расширением .js в директории src и отформатировать их. Запустите эту команду в терминале:

yarn prettier

С нашим уродливым кодом происходит чудо:

Легким движением руки он превращается в чистый код. Круто, правда?

ESLint

Линтинг – это статический анализ кода, который позволяет обнаружить проблемные места или несоответствия определенному стилю. Для линтинга JavaScript мы будем использовать ESLint.

Слабая динамическая типизация JavaScript – причина многих ошибок. Этот язык не компилируется, поэтому для проверки кода приходится полностью выполнить его. Линтеры позволяют найти подозрительные места, не запуская каждый раз программу.

Работать с ESLint очень удобно. Вы можете добавлять правила во время выполнения, включать и выключать их, задавать отдельные предупреждения и ошибки.

В настоящее время существует два популярных JS-стайлгайда, чтобы создавать чистый код: от Google и от Airbnb. Воспользуемся последним.

Настройка

Для начала обновите файл package.json:

{
  "name": "react-boiler-plate",
  "version": "1.0.0",
  "description": "A react boiler plate",
  "main": "src/index.js",
  "author": "Adeel Imran",
  "license": "MIT",
  "scripts": {
    "lint": "eslint --debug src/",
    "lint:write": "eslint --debug src/ --fix",
    "prettier": "prettier --write src/**/*.js"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.(js|jsx)": ["npm run lint:write", "git add"]
  },
  "devDependencies": {
    "babel-eslint": "^8.2.3",
    "eslint": "^4.19.1",
    "eslint-config-airbnb": "^17.0.0",
    "eslint-config-jest-enzyme": "^6.0.2",
    "eslint-plugin-babel": "^5.1.0",
    "eslint-plugin-import": "^2.12.0",
    "eslint-plugin-jest": "^21.18.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-prettier": "^2.6.0",
    "eslint-plugin-react": "^7.9.1",
    "husky": "^1.1.2",
    "lint-staged": "^7.3.0",
    "prettier": "^1.14.3"
  }
}

Появилась пара новых скриптов и множество eslint-пакетов. Разберемся, зачем они нужны.

  • babel-eslint и eslint-plugin-babel необходимы для совместной работы ESLint и Babel.
  • eslint – главный модуль линтера.
  • eslint-config-airbnb – готовая конфигурация для использования стайлгайда Airbnb.
  • eslint-plugin-import предназначен для поддержки синтаксиса импорта/экспорта и управления путями к файлам. Подробнее можно прочитать в документации плагина.
  • eslint-plugin-jsx-a11y проверяет доступность JSX-кода.
  • eslint-plugin-prettier позволяет ESLint и Prettier работать вместе.
  • eslint-plugin-react добавляет специфические настройки линтинга для проектов React.

В этой статье не рассматривается модульное тестирование с помощью Jest/Enzyme. Но если вы его используете, вам могут пригодиться также пакеты eslint-config-jest-enzyme и eslint-plugin-jest.

С плагинами husky и lint-staged мы разберемся позже в разделе, посвященном автоматизации, а сейчас приступим к работе.

В корне приложения разместите файл конфигурации .eslintrc.js:

module.exports = {
	env: {
		es6: true,
		browser: true,
		node: true,
	},
	extends: ['airbnb', 'plugin:jest/recommended', 'jest-enzyme'],
	plugins: [
		'babel',
		'import',
		'jsx-a11y',
		'react',
		'prettier',
	],
	parser: 'babel-eslint',
	parserOptions: {
		ecmaVersion: 6,
		sourceType: 'module',
		ecmaFeatures: {
			jsx: true
		}
	},
	rules: {
		'linebreak-style': 'off', // с Windows работает плохо

		'arrow-parens': 'off', // несовместимо с prettier
		'object-curly-newline': 'off', // несовместимо с prettier
		'no-mixed-operators': 'off', // несовместимо с prettier
		'arrow-body-style': 'off', 
		'function-paren-newline': 'off', // несовместимо с prettier
		'no-plusplus': 'off',
		'space-before-function-paren': 0, // несовместимо с prettier

		'max-len': ['error', 100, 2, { ignoreUrls: true, }], 
		'no-console': 'error', // airbnb использует warn
		'no-alert': 'error', // airbnb использует warn

		'no-param-reassign': 'off', 
		"radix": "off",

		'react/require-default-props': 'off', // airbnb использует error
		'react/forbid-prop-types': 'off', // airbnb использует error
		'react/jsx-filename-extension': ['error', { extensions: ['.js'] }], // airbnb is использует .jsx

		'prefer-destructuring': 'off',

		'react/no-find-dom-node': 'off', 
		'react/no-did-mount-set-state': 'off',
		'react/no-unused-prop-types': 'off', 
		'react/jsx-one-expression-per-line': 'off',

		"jsx-a11y/anchor-is-valid": ["error", { "components": ["Link"], "specialLink": ["to"] }],
		"jsx-a11y/label-has-for": [2, {
			"required": {
				"every": ["id"]
			}
		}], 

		'prettier/prettier': ['error'],
	},
};

а также файл .eslintignore:

/.git
/.vscode
node_modules

Разберем каждую секцию файла конфигурации отдельно:

module.exports = { 
   env:{}, 
   extends: {}, 
   plugin: {}, 
   parser: {}, 
   parserOptions: {}, 
   rules: {},
};
  • env (environment) – среда выполнения кода. Это свойство подключает глобальные переменные и доступные фичи ECMAScript 6, браузера и Node.js.  Доступно множество сред, полный список – в документации.
  • extends – дополнительные конфигурации, последовательно расширяющие друг друга.
  • plugins – плагины, определяющие способ форматирования кода.
  • parser и parserOptions – в качестве дефолтного парсера ESList использует Espree, но мы подключаем babel, поэтому нужно подключить Babel-ESLint и настраиваем его для проекта.
  • rules – в этой секции можно переопределить любые правила.

В файле .eslintignore можно указать адреса, которые будут игнорироваться линтером, например, файлы git или конфигурация редактора кода.

Перейдем к новым командам из секции scripts:

"lint": "eslint --debug src/"
"lint:write": "eslint --debug src/ --fix"
  • yarn lint – проходит через все файлы в директории src/ и составляет подробный журнал ошибок, которые вы затем можете исправить.
  • yarn lint:write – действует аналогично, но ошибки исправляет самостоятельно, оставляя только чистый код.

Что ж, если вы дошли до этого раздела, вы молодец!

Автоматизация

Итак, мы настроили Prettier и ESLint, но чтобы запустить их, приходится каждый раз вводить команду в терминале. Было бы здорово автоматически проверять и форматировать код при сохранении файла в редакторе, а также при каждом коммите.

Линтинг при сохранении файла

Если вы работаете в  VS Code, это очень просто. Нужно лишь установить расширение ESLint. Загрузите его отсюда или откройте поиск с помощью ctrl+shift+x и введите там eslint.

После установки, создайте в корне проекта папку с именем .vscode, а внутри него – файл settings.json.

{
  "editor.formatOnSave": false,
  "eslint.autoFixOnSave": true,
}
  • параметр editor.formatOnSave имеет значение false, чтобы конфигурация редактора не конфликтовала с ESLint и Prettier.
  • eslint.autoFixOnSave устанавливает проверку при каждом сохранении файла.

Работать стало удобнее, можно продолжать автоматизацию.

Husky

Husky дает возможность зацепиться за хуки git. Это значит, что вы можете выполнять некоторые действия перед тем, как изменения будут закоммичены и отправлены в удаленный репозиторий.

Сначала установите пакет husky:

yarn add --dev husky

и добавьте этот фрагмент в файл package.json:

"husky": {    
   "hooks": {      
     "pre-commit": "YOUR_COMMAND_HERE", 
     "pre-push": "YOUR_COMMAND_HERE"   
   }  
},

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

Lint-staged

Lint-staged помогает запускать линтеры в файлах, подготовленных к коммиту, чтобы неформатированный код не попадал в репозиторий.

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

Установите пакет lint-staged:

yarn add --dev lint-staged

и добавьте этот фрагмент в файл package.json:

"lint-staged": {    
   "*.(js|jsx)": ["npm run lint:write", "git add"]  
},

Теперь прежде чем выполнить команду git add и добавить файл в область подготовленных изменений, инструмент запустит скрипт линтинга для всех файлов с расширениями .js и .jsx.

Husky + Lint-staged

Финальный вариант файла package.json:

{
  "name": "react-boiler-plate",
  "version": "1.0.0",
  "description": "A react boiler plate",
  "main": "src/index.js",
  "author": "Adeel Imran",
  "license": "MIT",
  "scripts": {
    "lint": "eslint --debug src/",
    "lint:write": "eslint --debug src/ --fix",
    "prettier": "prettier --write src/**/*.js"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.(js|jsx)": ["npm run lint:write", "git add"]
  },
  "devDependencies": {
    "babel-eslint": "^8.2.3",
    "eslint": "^4.19.1",
    "eslint-config-airbnb": "^17.0.0",
    "eslint-config-jest-enzyme": "^6.0.2",
    "eslint-plugin-babel": "^5.1.0",
    "eslint-plugin-import": "^2.12.0",
    "eslint-plugin-jest": "^21.18.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-prettier": "^2.6.0",
    "eslint-plugin-react": "^7.9.1",
    "husky": "^1.1.2",
    "lint-staged": "^7.3.0",
    "prettier": "^1.14.3"
  }
}

Теперь каждый раз, когда вы сохраняете изменения:

$ git add .
$ git commit -m "some descriptive message here"

весь код будет проверен и отформатирован, так что ваш репозиторий будет чист.

EditorConfig

В корне проекта создайте файл .editorconfig и добавьте в него этот код:

# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

[*.md]
trim_trailing_whitespace = false

[*.js]
trim_trailing_whitespace = true

# Unix-style newlines with a newline ending every file
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
insert_final_newline = true
max_line_length = 100

Конфигурация EditorConfig применима для многих редакторов. Этот пример управляет пробелами и табуляцией, максимальной длиной строки и стилем перевода строки.

Исходный код проекта вы можете найти в этом git-репозитории.

Оригинал: These tools will help you write clean code, автор Adeel Imran.

Пишите чистый код:

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

admin
10 июня 2018

Лайфхак: в какой последовательности изучать JavaScript

Огромный инструментарий JS и тонны материалов по нему. С чего начать? Расск...