Форматирование кода JavaScript: инструменты и стандарты
Откройте любой pull request, в котором половина diff — это изменения пробелов, и вы сразу почувствуете боль. Несогласованность форматирования тратит время, засоряет ревью кода и создаёт конфликты слияния, не имеющие никакого отношения к логике. Решение простое: выберите стандарт форматирования, автоматизируйте его соблюдение и больше никогда об этом не думайте.
Это руководство подробно разбирает инструменты и стандарты, которые делают форматирование JavaScript решённой задачей.
Почему единообразное форматирование важно
Форматирование — это не про эстетику, а про скорость работы команды. Когда каждый разработчик использует разные отступы, расположение скобок и длину строк, происходят три вещи:
Ревью кода замедляется. Рецензенты тратят умственные усилия на разбор незнакомого форматирования вместо оценки логики. Функция, выглядящая иначе, чем весь остальной код, привлекает внимание не по тем причинам.
Конфликты слияния множатся. Разработчик A переформатирует файл с табами, разработчик B использует пробелы, и теперь Git показывает каждую строку как изменённую. Реальное исправление бага из трёх строк теряется в шуме.
Когнитивная нагрузка возрастает. Переключение между файлами с разными стилями заставляет мозг постоянно заново разбирать структуру. Единообразное форматирование позволяет читать код как обычный текст — глаза уже знают, куда смотреть.
Решение не в том, чтобы спорить, какой стиль лучше. А в том, чтобы выбрать один и автоматизировать его.
Популярные руководства по стилю JavaScript
Прежде чем выбирать инструменты, полезно разобраться в основных руководствах по стилю, которые сформировали конвенции форматирования JavaScript.
Airbnb Style Guide
Самое распространённое руководство по стилю JavaScript. Оно требует точку с запятой, предпочитает одинарные кавычки, обязывает использовать завершающие запятые в многострочных конструкциях и применяет отступ в 2 пробела. Конфигурация ESLint (eslint-config-airbnb) объединяет сотни правил, охватывающих как форматирование, так и качество кода.
// Стиль Airbnb
const getUserData = (userId) => {
const user = findUser(userId);
return {
name: user.name,
email: user.email,
};
};
Standard Style
Занимает противоположную позицию по точкам с запятой — никаких точек с запятой, никогда. Использует отступ в 2 пробела и одинарные кавычки. Пакет standard включает собственный линтер, поэтому отдельная конфигурация ESLint не требуется.
// Стиль Standard
const getUserData = (userId) => {
const user = findUser(userId)
return {
name: user.name,
email: user.email
}
}
Google Style Guide
Похож на Airbnb, но имеет отличия в требованиях к JSDoc и соглашениях об именовании. Использует отступ в 2 пробела, требует точку с запятой и предпочитает одинарные кавычки.
У каждого из этих руководств есть свои плюсы и минусы. Важна согласованность, а не конкретный выбор. И всё чаще команды вообще пропускают дебаты, позволяя Prettier решать за них.
Prettier: бескомпромиссный форматировщик
Prettier изменил форматирование JavaScript, убрав большинство решений. Он парсит код в AST (Abstract Syntax Tree) и переписывает его по собственным правилам. Вы не настраиваете каждый параметр форматирования отдельно — задаёте несколько высокоуровневых опций, а Prettier делает остальное.
Установка
npm install --save-dev prettier
Создайте файл конфигурации .prettierrc:
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "always"
}
Основные параметры конфигурации
printWidth (по умолчанию: 80) — Длина строки, при которой Prettier переносит код. Это не жёсткий лимит — Prettier использует его как ориентир для принятия решения о разбиении выражений на несколько строк. Значения 100 или 120 часто встречаются в командах с широкими мониторами.
semi (по умолчанию: true) — Добавлять ли точку с запятой в конце инструкций. Установите false, если предпочитаете стиль Standard.
singleQuote (по умолчанию: false) — Использовать одинарные кавычки вместо двойных. Большинство JavaScript-разработчиков предпочитают одинарные кавычки, поэтому true — более распространённая настройка.
trailingComma (по умолчанию: "all") — Добавляет завершающие запятые везде, где это допустимо. Это даёт более чистые diff в Git, потому что добавление нового элемента в список изменяет только одну строку вместо двух.
// Без завершающих запятых — добавление "d" изменяет две строки
const items = [
- "a",
- "b",
- "c"
+ "a",
+ "b",
+ "c",
+ "d"
];
// С завершающими запятыми — добавление "d" изменяет одну строку
const items = [
"a",
"b",
"c",
+ "d",
];
arrowParens (по умолчанию: "always") — Оборачивать ли единственный параметр стрелочной функции в скобки. "always" означает (x) => x, "avoid" означает x => x.
Запуск Prettier
# Отформатировать все файлы
npx prettier --write .
# Проверить без изменения
npx prettier --check .
# Отформатировать конкретные типы файлов
npx prettier --write "src/**/*.{js,jsx,ts,tsx}"
Добавьте файл .prettierignore, чтобы пропускать сгенерированные файлы:
node_modules
dist
build
coverage
*.min.js
Если вы работаете с минифицированным JavaScript, наш Code Minifier правильно выполняет минификацию — никогда не редактируйте минифицированный код вручную.
ESLint: больше, чем форматирование
ESLint решает другую задачу, нежели Prettier. Prettier отвечает за внешний вид кода, а ESLint выявляет проблемы в поведении кода. Правила ESLint делятся на две категории:
Правила форматирования — отступы, интервалы, расположение скобок. Они пересекаются с Prettier, и при совместном использовании обоих инструментов их обычно следует отключать.
Правила качества кода — неиспользуемые переменные, недостижимый код, неявное приведение типов, отсутствующая обработка ошибок. Именно здесь ESLint раскрывается в полной мере.
Рекомендуемая настройка
npm install --save-dev eslint @eslint/js
Минимальный eslint.config.js:
import js from '@eslint/js';
export default [
js.configs.recommended,
{
rules: {
'no-unused-vars': 'warn',
'no-console': 'warn',
'eqeqeq': 'error',
'no-implicit-coercion': 'error',
},
},
];
Для TypeScript-проектов добавьте typescript-eslint:
npm install --save-dev typescript-eslint
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
);
Интеграция Prettier + ESLint
Запуск обоих инструментов без координации порождает конфликты — правила форматирования ESLint противоречат выводу Prettier. Решение — eslint-config-prettier, который отключает все правила ESLint, конфликтующие с Prettier.
npm install --save-dev eslint-config-prettier
import js from '@eslint/js';
import prettierConfig from 'eslint-config-prettier';
export default [
js.configs.recommended,
prettierConfig,
{
rules: {
// Здесь только правила качества кода
'no-unused-vars': 'warn',
'eqeqeq': 'error',
},
},
];
При такой настройке Prettier отвечает за форматирование, а ESLint — за качество кода. Никаких конфликтов, никакой путаницы.
EditorConfig для согласованности между редакторами
Не все в команде используют один и тот же редактор. EditorConfig обеспечивает базовые настройки, работающие в VS Code, WebStorm, Vim, Sublime Text и большинстве других редакторов.
Создайте файл .editorconfig в корне проекта:
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
EditorConfig берёт на себя базовые вещи — отступы, окончания строк, пробелы в конце строк — ещё до запуска Prettier. Это предотвращает типичную проблему, когда разработчик на Windows вносит окончания строк \r\n в проект на базе Unix.
Git-хуки с Husky и lint-staged
Автоматическое форматирование работает только тогда, когда оно действительно запускается. Надеяться, что разработчики не забудут выполнить npx prettier --write перед каждым коммитом, не масштабируется. Git-хуки решают эту проблему.
Настройка
npm install --save-dev husky lint-staged
npx husky init
Добавьте в package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"prettier --write",
"eslint --fix"
],
"*.{json,md,css}": [
"prettier --write"
]
}
}
Обновите хук pre-commit в Husky (.husky/pre-commit):
npx lint-staged
Теперь каждый коммит автоматически форматирует добавленные в индекс файлы и применяет исправления ESLint. Разработчикам никогда не нужно думать о форматировании — всё происходит само.
Это золотой стандарт для командных проектов: Prettier форматирует, ESLint находит баги, Husky обеспечивает выполнение обоих при каждом коммите.
Дискуссия о точке с запятой
Ни одно обсуждение форматирования JavaScript не обходится без вопроса о точке с запятой. Вот практический ответ: это не имеет значения, если команда придерживается единого подхода.
За точку с запятой: Явное завершение инструкций позволяет избежать крайних случаев ASI (Automatic Semicolon Insertion). Руководства Airbnb и Google её требуют.
Без точки с запятой: ASI в JavaScript автоматически обрабатывает завершение инструкций. Код выглядит чище с меньшим визуальным шумом. Руководство Standard их опускает.
Ловушки ASI, о которых предупреждают — например, строки, начинающиеся с ( или [ — отлавливаются правилом no-unexpected-multiline в ESLint. На практике отказ от точек с запятой при наличии корректного линтинга абсолютно безопасен.
Выберите один вариант, настройте опцию semi в Prettier и двигайтесь дальше. Prettier будет добавлять или убирать их последовательно в любом случае.
Табы или пробелы в JavaScript
Экосистема JavaScript подавляющим большинством использует пробелы — а именно, отступ в 2 пробела. Это не универсальное правило (Go использует табы, Python — 4 пробела), но в JavaScript это устоявшаяся конвенция.
Почему 2 пробела? Паттерны вложенных колбэков и цепочек методов в JavaScript быстро создают глубокую вложенность. Два пробела сохраняют читаемость глубоко вложенного кода, не сдвигая его за правый край экрана.
Почему не табы? Табы позволяют каждому разработчику задать свою ширину отображения, что звучит хорошо, но на практике приводит к нарушению выравнивания кода в разных редакторах. С пробелами то, что видите вы, видят и все остальные.
Настройте это один раз в Prettier (tabWidth: 2, useTabs: false) и EditorConfig (indent_style = space, indent_size = 2) — и вопрос закрыт.
Типичные ошибки форматирования
Непоследовательные стрелочные функции
// Непоследовательно — избегайте этого
const double = x => x * 2;
const add = (a, b) => a + b;
const greet = (name) => {
return `Hello, ${name}`;
};
// Последовательно — Prettier с arrowParens: "always"
const double = (x) => x * 2;
const add = (a, b) => a + b;
const greet = (name) => {
return `Hello, ${name}`;
};
Стиль деструктуризации объектов
// Сжато — трудно читать
const {name,email,role} = user;
// Отформатировано — Prettier делает это автоматически
const { name, email, role } = user;
// Многострочное для множества свойств
const {
name,
email,
role,
department,
startDate,
} = user;
Организация инструкций import
Prettier не сортирует импорты — это вопрос качества кода, а не форматирования. Используйте eslint-plugin-import или плагин simple-import-sort:
// Организованные импорты
import React from 'react';
import { useState, useEffect } from 'react';
import { Button } from '@/components/Button';
import { Modal } from '@/components/Modal';
import { formatDate } from '../utils/dates';
import { validateEmail } from '../utils/validation';
Длинные тернарные выражения
// Нечитаемо в одну строку
const label = isAdmin ? 'Admin Dashboard' : hasEditPermission ? 'Editor View' : 'Read Only';
// Prettier переформатирует в читаемый многострочный вариант
const label = isAdmin
? 'Admin Dashboard'
: hasEditPermission
? 'Editor View'
: 'Read Only';
Настройка нового проекта
Вот полный чек-лист для настройки нового проекта на JavaScript или TypeScript:
-
Установите зависимости:
npm install --save-dev prettier eslint eslint-config-prettier husky lint-staged -
Создайте
.prettierrcс предпочтениями вашей команды -
Создайте
.editorconfigдля базовых настроек между редакторами -
Настройте ESLint только с правилами качества кода (без правил форматирования)
-
Настройте Husky + lint-staged для проверки на pre-commit
-
Добавьте npm-скрипты:
{ "scripts": { "format": "prettier --write .", "format:check": "prettier --check .", "lint": "eslint .", "lint:fix": "eslint --fix ." } } -
Выполните начальное форматирование всей кодовой базы:
npm run format -
Закоммитьте отформатированный код одним коммитом, чтобы его было легко пропустить в
git blameс помощью--ignore-rev
Форматирование на практике
Когда ваш конвейер форматирования настроен, повседневная работа меняется кардинально:
- Пишите код как угодно. Prettier переформатирует при сохранении или коммите.
- Pull request показывают только изменения логики. Никакого шума из-за пробелов.
- Новые участники команды продуктивны с первого дня. Инструменты обеспечивают соблюдение стандартов без отдельного документа с руководством по стилю.
- Споры о стиле исчезают. Авторитет — Prettier, а не отдельный разработчик.
Когда нужно проверить структуру JSON-данных, с которыми вы работаете, наш JSON Formatter упрощает инспекцию — вставьте любой JSON и мгновенно получите читаемое форматирование прямо в браузере.
Дополнительные ресурсы
Подробнее о форматировании кода и инструментах для разработчиков:
- Code Minification Guide — Узнайте, когда и как минифицировать JavaScript для продакшена
- Naming Conventions in Programming — Единообразное именование — вторая половина читаемого кода
- SQL Formatting Best Practices — Применяйте ту же дисциплину форматирования к запросам к базе данных
Единообразное форматирование — одна из тех редких инженерных инвестиций, которая окупается сразу и продолжает приносить пользу. Настройте один раз, автоматизируйте и направьте свою энергию на код, который действительно имеет значение.