Олег Марков
Prettier конфиг prettier-config - как настроить форматирование кода под ваш проект
Введение
Prettier часто называют «безкомпромиссным форматтером кода». Он берет на себя полностью автоматическое форматирование и избавляет вас от бесконечных споров о стиле в команде. Но чтобы форматирование действительно соответствовало потребностям проекта, нужно правильно настроить конфиг Prettier.
Смотрите, в этой статье я подробно покажу вам, как устроен конфиг Prettier, какие форматы конфигурационных файлов существуют, как работает приоритет настроек и как подключить общий конфиг через пакет prettier-config. Мы шаг за шагом разберем типичные сценарии:
- как создать базовый конфиг под проект;
- как разделить конфиг по разным типам файлов с помощью
overrides; - как использовать общий конфиг для нескольких репозиториев;
- как подключить Prettier к редактору и CI, чтобы форматирование было единым и предсказуемым.
Задача статьи — не просто перечислить опции, а помочь вам выстроить удобную и понятную систему форматирования кода в реальных проектах.
Что такое конфиг Prettier и зачем он нужен
Prettier по умолчанию имеет базовые настройки, которые подходят многим проектам. Но, как только вы начинаете работать командой или поддерживать большой код, почти всегда появляются требования:
- ограничить ширину строки;
- настроить кавычки — одинарные или двойные;
- управлять точкой с запятой;
- включить или выключить trailing запятые;
- по-разному форматировать разные типы файлов.
Конфигурация Prettier решает эти задачи. По сути, это набор правил форматирования, который:
- хранится в файле конфигурации в корне проекта;
- используется всеми разработчиками и инструментами (редактор, CLI, линтер);
- может быть вынесен в отдельный npm-пакет и переиспользован.
Давайте разберемся, какие есть варианты и как их правильно использовать.
Варианты конфигурационных файлов Prettier
Prettier понимает несколько форматов конфигурации. Вы можете выбрать тот, который удобен в вашем проекте и стеке.
Основные форматы конфигурации
Prettier поддерживает следующие файлы конфигурации (по приоритету поиска):
.prettierrc.prettierrc.json.prettierrc.ymlили.prettierrc.yaml.prettierrc.jsили.prettierrc.cjsprettier.config.jsилиprettier.config.cjs- поле
prettierвpackage.json
Prettier автоматически ищет конфиг, начиная от директории, где вы запускаете форматирование, и поднимаясь вверх по дереву каталогов до корня файловой системы.
Простой JSON-конфиг .prettierrc
Это один из самых распространенных вариантов, особенно в JS/TS проектах. Вот минимальный пример:
{
// Максимальная длина строки
"printWidth": 100,
// Использовать пробелы вместо табов
"useTabs": false,
// Размер таба в пробелах
"tabWidth": 2,
// Одинарные кавычки вместо двойных
"singleQuote": true,
// Всегда ставить точку с запятой в конце выражения
"semi": true
}
Здесь вы задаете базовый стиль, который будет применяться ко всем поддерживаемым Prettier файлам в проекте.
JavaScript-конфиг prettier.config.js или .prettierrc.js
JS-конфиг полезен, когда нужно:
- использовать условия в конфиге;
- импортировать общий конфиг из пакета;
- работать с
require/importи программно модифицировать опции.
Пример:
// prettier.config.js
// Здесь мы импортируем базовый конфиг из npm-пакета
const baseConfig = require('@company/prettier-config');
module.exports = {
// Расширяем базовый конфиг
...baseConfig,
// Переопределяем отдельные параметры
printWidth: 100,
// Добавляем overrides для специфичных файлов
overrides: [
...(baseConfig.overrides || []),
{
files: '*.md',
options: {
// В Markdown часто удобно иметь больше ширину строки
printWidth: 120
}
}
]
};
Как видите, JavaScript-конфиг дает вам большую гибкость, особенно при работе с общими конфигами в монорепозиториях или в компании.
Конфиг в package.json
Если вы не хотите множить файлы конфигурации в корне проекта, можно хранить настройки прямо в package.json:
{
"name": "my-project",
"version": "1.0.0",
// Другие поля package.json опущены для краткости
"prettier": {
// Ширина строки
"printWidth": 100,
// Одинарные кавычки
"singleQuote": true
}
}
Такой подход удобен в простых проектах или когда вы хотите минимизировать количество файлов.
Приоритет конфигураций и опций
Prettier учитывает приоритет, когда вы задаете настройки в нескольких местах. Важно понимать, что ближе к конкретному файлу — сильнее влияние.
Общий порядок приоритета:
- CLI-параметры (например,
prettier --single-quote). - Комментарии в файле
// prettier-ignoreи подобные директивы. - Конфиг-файлы (
.prettierrc*,prettier.config.*,package.jsonполеprettier). - Настройки по умолчанию внутри Prettier.
Если у вас несколько конфигов в разных директориях (например, в корне репозитория и в поддиректории пакета), Prettier найдет ближайший к форматируемому файлу и использует его. Это полезно в монорепозиториях, где разные пакеты могут иметь разные требования к форматированию.
Давайте посмотрим на пример структуры:
repo/
.prettierrc // базовый конфиг
packages/
app/
.prettierrc // локальный конфиг для приложения
src/
index.ts
Если вы запускаете Prettier для packages/app/src/index.ts, то:
- будет использован
.prettierrcизpackages/app; - корневой
.prettierrcбудет проигнорирован для этого файла.
Базовые настройки Prettier на практике
Теперь давайте разберем основные опции конфигурации, которые используются чаще всего. Я покажу их на примерах, чтобы вам было проще понять, как они влияют на форматирование.
Основные опции форматирования
printWidth — максимальная длина строки
Определяет, по какой ширине Prettier будет «ломать» строки.
{
"printWidth": 80
}
Пример до форматирования:
// Здесь строка довольно длинная и выходит за 80 символов
const query = 'SELECT id, name, created_at, updated_at FROM users WHERE deleted_at IS NULL ORDER BY created_at DESC';
После форматирования с printWidth: 80:
// Prettier разбивает строку на несколько
const query =
'SELECT id, name, created_at, updated_at FROM users WHERE deleted_at IS NULL ORDER BY created_at DESC';
Prettier постарается разорвать строку в логичных местах, чтобы код оставался читаемым.
tabWidth и useTabs — отступы
Управляют отступами в коде.
{
"tabWidth": 2, // размер отступа
"useTabs": false // использовать пробелы вместо табов
}
Если вы хотите табы:
{
"useTabs": true
}
Prettier тогда будет использовать символ таба вместо пробелов, но визуальная ширина будет зависеть уже от настроек редактора.
semi — точки с запятой
Управляет тем, ставить ли точку с запятой в конце строк.
{
"semi": true
}
Пример:
// До
const x = 1
const y = 2
// После с semi: true
const x = 1;
const y = 2;
Если вы хотите стиль без точек с запятой:
{
"semi": false
}
Тогда Prettier их уберет там, где это безопасно по синтаксису JS.
singleQuote — тип кавычек
{
"singleQuote": true
}
Пример:
// До
const msg = "Hello, world";
// После с singleQuote: true
const msg = 'Hello, world';
Prettier постарается использовать одинарные кавычки там, где это возможно.
trailingComma — висячие запятые
Смотрите, это одна из опций, которая сильно влияет на диффы и удобство изменений.
Варианты:
"none"— без висячих запятых;"es5"— в объектах, массивах, аргументах функций, где поддерживает ES5;"all"— везде, где разрешено синтаксисом (включая параметры функций).
Пример:
{
"trailingComma": "es5"
}
До форматирования:
const user = {
id: 1,
name: 'Ivan'
};
const arr = [1, 2, 3];
После:
const user = {
id: 1,
name: 'Ivan', // добавлена запятая
};
const arr = [1, 2, 3]; // массив уже в одной строке, тут запятая не добавляется
При "all" Prettier добавит запятые в списки аргументов функций и параметров, что делает диффы более «чистыми» при добавлении новых аргументов.
Другие важные опции
Перечислю еще несколько часто используемых параметров с краткими примерами.
arrowParens
Определяет, нужно ли оборачивать параметр стрелочной функции в скобки.
{
"arrowParens": "always"
}
До:
const square = x => x * x;
После с "always":
const square = (x) => x * x;
Зачастую это улучшает читаемость и упрощает добавление второго аргумента.
endOfLine
Управляет символами конца строки — важно в кроссплатформенных проектах.
Варианты значений:
"lf"— перевод строки\n;"crlf"—\r\n(Windows-стиль);"cr";"auto"— определять автоматически по содержимому файла.
Типичный выбор:
{
"endOfLine": "lf"
}
Так вы избегаете постоянных переформатирований между Linux/macOS и Windows.
bracketSpacing
Управляет пробелами внутри фигурных скобок объектов.
{
"bracketSpacing": true
}
Результат:
// bracketSpacing: true
const obj = { a: 1, b: 2 };
// bracketSpacing: false
const obj2 = {a: 1, b: 2};
jsxSingleQuote и jsxBracketSameLine (до Prettier 3) / bracketSameLine (в Prettier 3+)
Если вы работаете с React/JSX, эти опции будут вам полезны.
{
"jsxSingleQuote": true,
"bracketSameLine": false
}
jsxSingleQuote: true приводит JSX-атрибуты к одинарным кавычкам:
// После форматирования
<MyComponent title='Привет' />
bracketSameLine управляет тем, будет ли закрывающая скобка JSX на той же строке, что и последний атрибут, или на новой строке.
Настройка Prettier под разные типы файлов с помощью overrides
Часто нужно по-разному форматировать, например, JavaScript, YAML и Markdown. Для этого у Prettier есть полезный механизм overrides.
Основной принцип overrides
В конфиге вы можете указать массив правил, где каждое правило определяет:
- какие файлы оно затрагивает (через
files,excludeFiles); - какие опции применяются к этим файлам.
Пример:
// .prettierrc.js
module.exports = {
printWidth: 100,
singleQuote: true,
// Глобальные опции выше, а ниже — overrides
overrides: [
{
// Применяем для всех YAML файлов
files: '*.yml',
options: {
// В YAML часто требуется меньшая ширина строки
printWidth: 80,
// В YAML нет одинарных кавычек по умолчанию, оставим кавычки как есть
singleQuote: false
}
},
{
// Применяем к Markdown
files: '*.md',
options: {
printWidth: 80,
proseWrap: 'always' // всегда переносить текст
}
}
]
};
Теперь вы увидите, что JS-файлы форматируются с printWidth: 100, а Markdown — с printWidth: 80.
Маски файлов в overrides
Параметр files поддерживает:
- строку с маской
*.ts; - массив строк;
- шаблоны с поддиректориями
src/**/*.ts.
Пример с несколькими типами:
// Здесь мы настраиваем TS и тестовые файлы отдельно
module.exports = {
printWidth: 100,
overrides: [
{
files: ['*.ts', '*.tsx'],
options: {
// В TypeScript часто используют точку с запятой
semi: true
}
},
{
files: ['*.test.ts', '*.spec.ts'],
options: {
// Для тестов допускаем более длинные строки
printWidth: 120
}
}
]
};
Такой подход особенно удобен, когда в проекте много типов файлов и вы хотите детально контролировать форматирование.
Общий конфиг через npm-пакет prettier-config
Теперь давайте перейдем к ключевой части: как вынести конфигурацию Prettier в отдельный пакет и переиспользовать ее в нескольких проектах. Это часто называют prettier-config пакетом.
Зачем выносить конфиг в пакет
Это особенно полезно, когда:
- у вас несколько репозиториев, и вы хотите единый стиль форматирования;
- есть команда или компания с общими правилами;
- вы поддерживаете монорепозиторий с разными пакетами.
Преимущества:
- единый источник правды для настроек;
- обновление правил в одном месте;
- возможность публиковать свои стили как open-source.
Как создать собственный пакет с конфигом Prettier
Давайте разберем, как это сделать пошагово.
1. Создаем новый npm-пакет
Структура:
company-prettier-config/
package.json
index.js
README.md
package.json:
{
"name": "@company/prettier-config",
"version": "1.0.0",
"main": "index.js",
"license": "MIT"
}
index.js:
// index.js
// Здесь мы экспортируем объект конфигурации Prettier
module.exports = {
printWidth: 100,
singleQuote: true,
semi: true,
trailingComma: 'all',
tabWidth: 2,
useTabs: false,
bracketSpacing: true,
arrowParens: 'always',
overrides: [
{
files: '*.md',
options: {
printWidth: 80,
proseWrap: 'always'
}
},
{
files: '*.yml',
options: {
printWidth: 80
}
}
]
};
Комментарии в коде подсказывают, что именно вы экспортируете: это обычный JS-объект с опциями Prettier.
После этого вы публикуете пакет в registry (npm или внутренний).
2. Подключаем общий конфиг в проекте
Теперь в любом проекте, где вы хотите использовать этот стиль, вы можете подключить пакет.
Сначала устанавливаем пакет:
npm install --save-dev @company/prettier-config
# или
yarn add -D @company/prettier-config
Дальше есть два основных способа подключения.
Вариант 1. Через prettier поле в package.json
Этот способ рекомендован самим Prettier для пакетов-конфигов.
{
"name": "my-app",
"version": "1.0.0",
"prettier": "@company/prettier-config"
}
Что здесь происходит:
- при запуске Prettier он видит, что значение поля
prettier— это строка; - воспринимает ее как
require('@company/prettier-config'); - загружает конфиг из пакета и применяет его.
Никаких дополнительных файлов конфигурации создавать не нужно.
Вариант 2. Через JS-конфиг prettier.config.js
Этот вариант дает больше гибкости, если вы хотите дополнительно переопределить некоторые настройки.
// prettier.config.js
// Подключаем общий конфиг
const baseConfig = require('@company/prettier-config');
module.exports = {
// Расширяем общий конфиг
...baseConfig,
// Переопределяем параметры на уровне проекта
printWidth: 90,
overrides: [
...(baseConfig.overrides || []),
// Добавляем локальное правило
{
files: 'docs/**/*.md',
options: {
printWidth: 72
}
}
]
};
Смотрите, я специально добавил комментарии:
- сначала мы импортируем базовый конфиг;
- затем «разворачиваем» его через оператор расширения;
- после этого можем при необходимости изменять или дополнять настройки.
Что такое prettier-config как стандартное имя
Часто команды называют свой пакет с конфигом строго prettier-config или @scope/prettier-config. Это не жесткое требование Prettier, но общепринятая практика. Она делает смысл пакета очевидным:
- при виде
@company/prettier-configсразу понятно, что это именно конфиг для Prettier; - в
package.jsonможно лаконично прописать"prettier": "@company/prettier-config".
Важно: Prettier не ищет автоматически пакет с именем prettier-config. Его все равно нужно явно указать в конфигурации (через prettier поле или JS-конфиг).
Локальные и глобальные настройки: как их сочетать
Частый вопрос — как правильно сочетать:
- глобальные настройки из общего конфига;
- локальные требования конкретного проекта.
Вот базовый подход, который хорошо работает на практике.
1. Вынесите максимально возможную часть в общий конфиг
Например:
- ширина строки;
- тип кавычек;
- точки с запятой;
- trailing запятые;
- форматирование JS/TS/JSON/Markdown по умолчанию.
Это то, что должно быть единым стилем по всем проектам.
2. В проекте переопределяйте только особые случаи
Например, вам нужно:
- другое
printWidthдля документации; - особое форматирование для legacy-кода в поддиректории;
- отключить какую-то опцию для специфичных файлов.
Тогда в проекте используйте подход с расширением:
// prettier.config.js
const baseConfig = require('@company/prettier-config');
module.exports = {
...baseConfig,
overrides: [
...(baseConfig.overrides || []),
{
// Локальное правило только для этого проекта
files: 'legacy/**/*.js',
options: {
printWidth: 120,
semi: false
}
}
]
};
Так вы сохраняете единый стиль везде, где это возможно, и не размножаете копии одного и того же набора опций.
Интеграция Prettier конфига в рабочий процесс
Сам конфиг — это только часть истории. Чтобы форматирование реально работало стабильно, нужно правильно подключить Prettier в инструменты разработки.
Интеграция с редактором (VS Code как пример)
В VS Code рекомендуется установить расширение Prettier - Code formatter. Затем вы можете привязать его к конфигу проекта.
Файл настроек .vscode/settings.json в репозитории:
{
// Включаем форматирование при сохранении
"editor.formatOnSave": true,
// Указываем, что форматтер по умолчанию — Prettier
"editor.defaultFormatter": "esbenp.prettier-vscode",
// Опционально — включаем формат только для конкретных языков
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
Расширение Prettier будет автоматически использовать конфигурацию из файла:
.prettierrc*;prettier.config.*;- или поле
prettierвpackage.json.
Если вы используете пакет prettier-config, настройки также будут подхвачены, потому что редактор использует тот же механизм, что и CLI Prettier.
Интеграция с линтером (ESLint)
Часто Prettier используют совместно с ESLint. Общий подход:
- ESLint отвечает за «качество кода» (ошибки, потенциальные баги);
- Prettier отвечает только за форматирование.
Типичный вариант — использовать eslint-config-prettier, который отключает правила ESLint, конфликтующие с Prettier.
Пример .eslintrc.cjs:
// .eslintrc.cjs
module.exports = {
extends: [
'eslint:recommended',
'plugin:react/recommended',
// Подключаем конфиг, который отключает конфликтующие с Prettier правила
'prettier'
],
plugins: ['react'],
rules: {
// Ваши кастомные правила
}
};
А Prettier конфиг задаете отдельно, как мы уже обсудили.
Если вы хотите запускать Prettier через ESLint (eslint --fix), можно использовать плагин eslint-plugin-prettier, но на практике многие команды предпочитают запускать Prettier отдельно — так проще контролировать поведение.
Интеграция в CI (проверка форматирования)
Еще один важный шаг — убедиться, что в репозиторий попадает уже отформатированный код. Для этого обычно:
- Настраивают pre-commit хук через Husky или аналогичный инструмент.
- Добавляют проверку форматирования в CI.
Пример pre-commit hook с Husky и lint-staged
package.json:
{
"devDependencies": {
"husky": "^9.0.0",
"lint-staged": "^15.0.0",
"prettier": "^3.0.0"
},
"scripts": {
"prepare": "husky install",
"lint:prettier": "prettier --check ."
},
"lint-staged": {
// Здесь мы указываем, какие файлы форматировать
"*.{js,jsx,ts,tsx,json,md,yml,yaml}": [
"prettier --write" // форматируем файлы
]
}
}
Хук:
npx husky add .husky/pre-commit "npx lint-staged"
Комментарии:
lint-stagedзапускает Prettier только для измененных файлов;- используется конфиг Prettier из проекта или общий
prettier-config; - вы получаете автоматически отформатированный код до коммита.
Проверка форматирования в CI
В CI можно добавить шаг:
npm run lint:prettier
Где команда, как мы указали выше:
{
"scripts": {
"lint:prettier": "prettier --check ."
}
}
--check не переписывает файлы, а только проверяет соответствие формату. Если есть расхождения, команда завершится с ошибкой, и пайплайн упадет.
Типичные ошибки и подводные камни при работе с prettier-config
Сейчас я перечислю несколько ситуаций, с которыми часто сталкиваются разработчики, и покажу, как их диагностировать.
1. Prettier не видит конфиг из пакета prettier-config
Сценарий: вы прописали в package.json:
{
"prettier": "@company/prettier-config"
}
Но форматирование не меняется.
Что проверить:
- Установлен ли пакет в
devDependenciesилиdependencies. - Нет ли в корне других конфигов Prettier, которые перекрывают этот (
.prettierrc,prettier.config.js). - Правильно ли указан путь. Например, если пакет называется
@company/prettier-config-base, нужно указать именно его.
Если вы используете JS-конфиг, проверьте, что require отрабатывает корректно:
// prettier.config.js
const config = require('@company/prettier-config');
console.log(config); // временно добавьте для проверки
module.exports = config;
Запустите Prettier в CLI и убедитесь, что ошибок нет.
2. Конфиг в поддиректории перекрывает корневой
Иногда вы ожидаете, что проект использует общий конфиг из корня, но в поддиректории лежит свой .prettierrc, и он «перебивает» глобальные настройки.
Решения:
- удалить локальный
.prettierrc, если он больше не нужен; - или явно расширить общий конфиг в локальном файле через JS-конфиг:
// packages/app/prettier.config.js
const base = require('../../prettier.config.js');
module.exports = {
...base,
// локальные изменения
printWidth: 90
};
3. Конфликты с ESLint правилами форматирования
Если вы видите, что ESLint и Prettier «дерутся» за форматирование (один ставит кавычки так, другой по-другому), скорее всего:
- не подключен
eslint-config-prettier; - в ESLint включены правила, дублирующие ответственность Prettier (
quotes,semi,max-lenи т.д.).
Общее решение — добавить prettier в extends ESLint и убрать правила форматирования из ESLint.
4. Разные версии Prettier в монорепозитории
В монорепозитории может получиться так, что разные пакеты используют разные версии Prettier. В итоге форматирование будет отличаться.
Практический подход:
- вынести Prettier в корневой
devDependenciesмонорепозитория; - в пакетах не указывать Prettier как зависимость;
- запускать Prettier из корня.
Так все пакеты используют одну и ту же версию инструмента и один общий конфиг.
Заключение
Конфиг Prettier — это основа предсказуемого и единообразного форматирования кода. От того, как вы его настроите и как будете распространять в проектах, зависит качество и стабильность кода, а также удобство работы в команде.
Мы разобрали:
- какие форматы конфигурации доступны и чем они отличаются;
- как устроен приоритет настроек и как работает поиск конфигов;
- базовые и продвинутые опции форматирования и их влияние на код;
- механизм
overridesдля разных типов файлов; - как вынести конфиг в npm-пакет
prettier-configи использовать его в нескольких репозиториях; - интеграцию конфигурации с редактором, линтером и CI;
- типичные проблемы при работе с конфигами Prettier и способы их решить.
Опираясь на эти примеры и принципы, вы можете выстроить удобную и гибкую систему форматирования в любых проектах — от маленького pet-проекта до крупного монорепозитория.
Частозадаваемые технические вопросы
Как в prettier-config подключить разные плагины Prettier для специфичных языков
Если вы используете плагины (например, для Prisma или Tailwind), установите их как зависимости проекта и укажите в JS-конфиге:
// prettier.config.js
module.exports = {
plugins: [
// Здесь мы указываем плагины
require('prettier-plugin-tailwindcss'),
require('prettier-plugin-prisma')
]
};
После этого Prettier автоматически начнет форматировать соответствующие файлы, используя плагины. Важно, чтобы плагины были доступны из контекста проекта, где запускается Prettier.
Как сделать так чтобы один проект использовал два разных prettier-config пакета для разных директорий
Напрямую использовать два пакета в одном конфиге нельзя, но вы можете объединить их через JS:
// prettier.config.js
const baseA = require('@company/prettier-config-a');
const baseB = require('@company/prettier-config-b');
module.exports = {
...baseA,
overrides: [
...(baseA.overrides || []),
{
files: 'special/**',
// Здесь используем настройки из второго конфига
options: {
...baseB
}
}
]
};
Так вы применяете второй конфиг как набор опций внутри overrides для нужных директорий.
Как временно переопределить часть настроек Prettier только для одной команды в монорепозитории
Создайте локальный prettier.config.js в пакете этой команды и расширьте общий конфиг:
// packages/team-a/prettier.config.js
const base = require('../../prettier.config.js');
module.exports = {
...base,
printWidth: 90, // локальное изменение
overrides: [
...(base.overrides || []),
{
files: 'experiments/**',
options: {
semi: false
}
}
]
};
Prettier автоматически возьмет ближайший конфиг к файлам, поэтому другие пакеты останутся на общем конфиге.
Как отключить Prettier для конкретного файла не меняя конфиг
В самом файле вверху добавьте комментарий-директиву:
// prettier-ignore
// Следующая структура останется в исходном виде
const data = { a:1,b:2 };
Если нужно игнорировать весь файл, лучше добавить его путь в .prettierignore:
# .prettierignore
legacy/**/*
Так Prettier не будет форматировать эти файлы вообще.
Как узнать какие именно настройки Prettier применяются к конкретному файлу с учетом prettier-config и overrides
Используйте CLI-команду:
prettier path/to/file.js --debug-check --loglevel debug
Она покажет подробную отладочную информацию. Либо запустите:
prettier path/to/file.js --config-precedence file-override --print-width 80
и экспериментируйте с параметрами, чтобы увидеть, какие опции реально влияют. Для точного просмотра итоговых опций удобно временно добавить console.log в JS-конфиг и проверить, какие значения приходят в module.exports.