Олег Марков
Prettier конфиг prettier-config - полное руководство по настройке
Введение
Prettier давно стал стандартом де-факто для автоформатирования кода в JavaScript и не только. Но по-настоящему полезным он становится тогда, когда вы настраиваете его под свой проект и команду. Для этого и нужен конфиг Prettier — файл с настройками форматирования. А когда этих проектов несколько, на сцену выходит отдельный пакет prettier-config, который позволяет вынести общие правила в одну переиспользуемую конфигурацию.
В этой статье мы разберем, как устроен конфиг Prettier, какие бывают форматы и способы подключения, что такое prettier-config как npm-пакет, как им пользоваться в реальных проектах и как построить общий стиль кодовой базы для команды или организации.
Смотрите, я покажу вам, как последовательно пройти путь от простой локальной настройки до собственного общего конфигурационного пакета.
Что такое конфиг Prettier и зачем нужен prettier-config
Основная идея конфига Prettier
Конфиг Prettier — это набор правил, определяющих, как именно форматировать код:
- ширина строки;
- какие кавычки использовать;
- нужен ли точка с запятой в конце строки;
- стиль отступов;
- форматирование JSX, HTML, JSON и других файлов.
Без явного конфига Prettier использует свои дефолтные настройки. Часто их достаточно для пет-проектов, но для командной разработки и больших репозиториев нужно больше контроля и предсказуемости.
Зачем выносить конфиг в prettier-config
Когда у вас несколько проектов (например, фронтенд, бэкенд, сервисы, SDK), вы, скорее всего, захотите:
- одинаковый стиль кода во всех репозиториях;
- единое место, где меняются правила форматирования;
- минимизацию копипасты настроек.
Для этого удобно сделать отдельный npm-пакет с конфигом, например:
@company/prettier-config;prettier-config-myteam;@my-org/prettier.
Такой пакет называют prettier-config. Это не официальный термин, а общепринятое название для npm-пакетов, которые экспортируют объект с настройками Prettier.
Форматы и расположение локального конфига Prettier
Прежде чем выносить конфиг в пакет, давайте разберемся с локальными файлами конфигурации.
Поддерживаемые форматы файлов
Prettier умеет считывать конфигурацию из множества форматов. Вы можете выбрать тот, который удобнее вашей команде и стэку:
Варианты конфигов
.prettierrc— JSON или YAML (в зависимости от содержимого)..prettierrc.json— явно JSON..prettierrc.yamlили.prettierrc.yml— YAML.prettier.config.jsили.prettierrc.js— JavaScript-файл.prettier.config.cjsили.prettierrc.cjs— CommonJS для проектов с type module.package.json— через полеprettier.
Если Prettier находит несколько файлов, он следует определенному приоритету и обычно берет ближайший конфиг от текущего файла вверх по дереву директорий.
Примеры базовых конфигов
Давайте разберемся на примере.
JSON-конфиг
Файл: .prettierrc.json
{
"printWidth": 100, // Максимальная длина строки
"tabWidth": 2, // Размер таба в пробелах
"useTabs": false, // Использовать пробелы вместо табов
"semi": true, // Добавлять точку с запятой
"singleQuote": true, // Использовать одинарные кавычки
"trailingComma": "all", // Запятая в конце списков и объектов
"bracketSpacing": true, // Пробелы внутри фигурных скобок
"arrowParens": "always" // Всегда оборачивать аргументы стрелочных функций в скобки
}
JS-конфиг
Файл: prettier.config.js
// Экспортируем объект с настройками Prettier
module.exports = {
printWidth: 100, // Максимальная длина строки
tabWidth: 2, // Отступ в пробелах
useTabs: false, // Не использовать символ табуляции
semi: true, // Всегда ставить точку с запятой
singleQuote: true, // Одинарные кавычки предпочтительнее
trailingComma: 'all', // Запятая в конце для всех возможных мест
bracketSpacing: true, // Пробелы внутри { ... }
arrowParens: 'always' // (x) => x вместо x => x
};
JS-конфиг удобен тем, что туда можно добавлять комментарии, использовать переменные, условную логику и т.д.
Конфиг в package.json
Файл: package.json
{
"name": "my-project",
"version": "1.0.0",
"prettier": {
"printWidth": 80, // Здесь задаются те же самые опции
"singleQuote": true
}
}
Так можно обойтись без отдельного файла, но для сложных настроек и командной работы отдельный конфиг обычно удобнее.
Ключевые опции конфига Prettier
Сейчас вы увидите, как выглядят самые часто используемые опции и что они делают. Это поможет лучше понимать, что именно вы выносите в общий prettier-config.
Форматирование строк и отступов
module.exports = {
printWidth: 80, // Максимальная длина строки
tabWidth: 2, // Размер таба
useTabs: false, // Отступы пробелами
endOfLine: 'lf' // Стиль переноса строк (lf, crlf, cr, auto)
};
printWidthпомогает контролировать читаемость — длинные строки переносятся.endOfLineважен для кросс-платформенных проектов (Windows vs Unix). Зачастую ставятlfи настраивают редактор.
Кавычки, точки с запятой, запятые
module.exports = {
semi: true, // Всегда ставить ;
singleQuote: true, // 'строка' вместо "строка"
jsxSingleQuote: false, // В JSX чаще используют двойные кавычки
trailingComma: 'all', // Возможные значения: "none", "es5", "all"
bracketSpacing: true, // { foo: bar } vs {foo: bar}
quoteProps: 'as-needed' // Кавычки для свойств объектов: as-needed, consistent, preserve
};
Давайте посмотрим, что происходит в следующем примере.
До форматирования:
const user = {name: "John", age: 30,};
function greet ( user ) {
console.log("Hello " + user.name)
}
После форматирования с указанным конфигом:
// Обратите внимание, как применяется каждая опция:
const user = { name: 'John', age: 30 }; // bracketSpacing, singleQuote, trailingComma
function greet(user) {
console.log('Hello ' + user.name); // semi, singleQuote
}
JSX и HTML
module.exports = {
jsxBracketSameLine: false, // Переносить закрывающую ">" на новую строку
bracketSameLine: false, // Новое имя опции в более новых версиях
jsxSingleQuote: false // Какие кавычки использовать в JSX
};
Пример:
// Вариант с bracketSameLine: false
<Button
color="primary"
onClick={handleClick}
>
Click me
</Button>;
Если бы bracketSameLine было true, закрывающая скобка > осталась бы на строке с последним атрибутом.
Управление форматированием в файлах
Иногда нужно отключить автоформатирование для определенных блоков. Это делается не через конфиг, а через специальные комментарии, но упомянем их здесь, чтобы картина была полной.
// prettier-ignore
const code = "оставить как есть";
// Здесь мы отключаем Prettier для всего файла
/* prettier-ignore-start */
const ugly1 = "так и останется";
const ugly2 = "и это тоже";
/* prettier-ignore-end */
Эти комментарии полезно знать, когда общие настройки из prettier-config слишком агрессивны для конкретного фрагмента.
Что такое prettier-config как npm-пакет
Теперь давайте перейдем к главной теме. Вы уже знаете, как выглядит конфиг Prettier в файле. По сути, prettier-config-пакет — это тот же самый объект конфигурации, но вынесенный в отдельный npm-пакет.
Идея переиспользуемых конфигов
Главная цель — переиспользование:
- один пакет настроек для всех проектов;
- централизованное изменение правил форматирования;
- единый стиль для команды или организации.
Смотрите, как это выглядит концептуально:
- Вы создаете отдельный репозиторий, например,
company-prettier-config. - В нем есть
package.jsonи файл конфигурации, например,index.js. - Вы публикуете этот пакет в npm (публичный или приватный реестр).
- В боевых проектах вы устанавливаете этот пакет и указываете Prettierу, что нужно использовать его.
Создание собственного prettier-config пакета
Давайте разберемся на примере, как создать свой пакет с конфигом шаг за шагом.
1. Структура проекта с конфигом
Создаем новую папку:
mkdir @my-org-prettier-config
cd @my-org-prettier-config
npm init -y
Теперь создаем файл index.js с содержимым:
// Здесь мы просто экспортируем объект с настройками Prettier
module.exports = {
printWidth: 100, // Более широкие строки
tabWidth: 2, // Стандартный отступ
useTabs: false, // Пробелы вместо табов
semi: true, // Всегда ставим ;
singleQuote: true, // Одинарные кавычки
trailingComma: 'all', // Запятая везде, где возможно
bracketSpacing: true, // Пробелы внутри { ... }
arrowParens: 'always', // (x) => x
endOfLine: 'lf' // Единый стиль переноса строк
};
В package.json важно указать main, чтобы пакетом можно было пользоваться как модулем:
{
"name": "@my-org/prettier-config",
"version": "1.0.0",
"main": "index.js",
"license": "MIT"
}
Комментарий:
name— имя пакета, здесь используется scoped-пакет@my-org/prettier-config.main— точка входа, откуда будет импортироваться конфиг.
2. Публикация пакета
Если вы используете публичный npm:
npm login
npm publish --access public
Если пакет приватный и публикуется в частный реестр (например, GitHub Packages или корпоративный npm), команда и конфиг будут отличаться, но общая идея та же.
Подключение prettier-config в проектах
Теперь посмотрим, как использовать созданный пакет конфигурации в конкретном проекте.
Вариант 1. Через поле prettier в package.json
Файл проекта: package.json
{
"name": "app-frontend",
"version": "1.0.0",
"devDependencies": {
"prettier": "^3.0.0",
"@my-org/prettier-config": "^1.0.0"
},
"prettier": "@my-org/prettier-config"
}
Комментарии:
- В
devDependenciesмы ставим сам Prettier и наш конфигурационный пакет. - В поле
prettierуказываем строку с именем пакета. Prettier поймет, что это модуль и подтянет настройки из него.
Теперь, когда вы выполните:
npx prettier . --write
Prettier применит правила из @my-org/prettier-config.
Вариант 2. Через .prettierrc.js
Иногда удобнее оставить локальный файл, но подключить в нем внешний конфиг.
Файл: .prettierrc.js
// Смотрите, я покажу вам, как смешать общий конфиг с локальными правками
module.exports = {
// Импортируем общий конфиг из пакета
...require('@my-org/prettier-config'),
// А здесь можем переопределять некоторые опции под конкретный проект
printWidth: 80, // Для этого репозитория хотим более узкие строки
semi: false // И отключаем точки с запятой
};
Здесь вы видите, что мы:
- подхватили все настройки из пакета через spread-оператор;
- точечно переопределили пару опций.
Это удобный подход, когда общий конфиг — база, но отдельному проекту нужны небольшие отличия.
Вариант 3. Использование кастомного пути к конфигу
Иногда вы не хотите хранить конфиг в package.json или стандартных файлах. Тогда можно указать конфиг явно через CLI:
npx prettier "src/**/*.{js,ts,tsx}" --config node_modules/@my-org/prettier-config/index.js --write
Комментарий:
- Через флаг
--configвы передаете путь до файла-экспортера настроек. - Это удобно для CI-скриптов или необычных структур каталогов.
Паттерны именования и auto-resolve для prettier-config пакетов
Вы, скорее всего, замечали пакеты вида prettier-config-airbnb или @company/prettier-config. Есть негласные соглашения, как их называть и как Prettier их ищет.
Нотация prettier-config-*
Есть устоявшийся паттерн:
- если имя пакета начинается с
prettier-config-, его можно подключать в конфиге по короткому имени.
Пример:
{
"prettier": "myteam" // Под капотом это пакет prettier-config-myteam
}
В этом случае Prettier:
- Попытается найти пакет
prettier-config-myteamвnode_modules. - Если найдет, загрузит его как конфиг.
То же работает и для scoped-пакетов:
@my-org/prettier-configможно указать полностью как@my-org/prettier-config.- Но если бы пакет назывался
@my-org/prettier-config-custom, вы могли бы указывать просто@my-org/custom— Prettier попытается достроить имя.
Чтобы избежать путаницы, лучше:
- использовать понятное и полное имя, например
@my-org/prettier-config; - в
package.json(в полеprettier) указывать либо полное имя пакета, либо максимально очевидный псевдоним.
Локальные overrides и совместная работа с eslint-config
В реальных проектах редко ограничиваются только базовым конфигом. Чаще нужно:
- по-разному форматировать разные типы файлов;
- согласовать работу Prettier с ESLint.
Overrides для разных типов файлов
Prettier поддерживает опцию overrides для настройки разных правил под разные файлы. В локальном prettier.config.js это выглядит так:
module.exports = {
printWidth: 100,
singleQuote: true,
// Здесь мы задаем частные правила для определенных файлов
overrides: [
{
files: '*.md',
options: {
printWidth: 80 // Более узкая ширина для документации
}
},
{
files: '*.json',
options: {
tabWidth: 2,
useTabs: false // Для JSON обычно важны стабильные пробелы
}
}
]
};
Если вы хотите вынести и такие правила в общий prettier-config-пакет, структура будет та же — overrides просто окажутся в export-объекте модуля.
Сочетание Prettier и ESLint
Современный подход — разделить ответственность:
- Prettier отвечает за форматирование (пробелы, переносы строк, кавычки).
- ESLint отвечает за качество кода (антипаттерны, потенциальные ошибки, стилистика, не связанная с форматированием).
Чтобы они не конфликтовали:
- Используют
eslint-config-prettier, который отключает правила ESLint, пересекающиеся с форматированием. - Иногда добавляют
eslint-plugin-prettier, чтобы запускать Prettier как правило ESLint.
Пример eslintrc:
module.exports = {
extends: [
'eslint:recommended',
'plugin:react/recommended',
// Отключаем конфликтующие правила
'prettier'
],
plugins: ['prettier'],
rules: {
// Запускаем Prettier как ESLint правило
'prettier/prettier': 'error'
}
};
При этом конфиг Prettier, который использует ESLint, все тот же:
- либо локальный
.prettierrc; - либо пакет
@my-org/prettier-config, указанный в package.json или js-конфиге.
Версионирование и обновление prettier-config пакета
Чтобы общий конфиг был полезен, важно правильно управлять его версиями. Давайте разберемся, как это делать аккуратно.
Семантическое версионирование
Обычно пакет с конфигом используют как любой другой npm-пакет, с семантическим версионированием:
MAJOR.MINOR.PATCH—1.0.0,1.1.0,2.0.0.
Рекомендации:
- MINOR-поднимайте, когда добавляете новые опции или меняете не критичные правила.
- MAJOR-поднимайте, когда меняется стиль кода так, что при
--writeбудет много изменений по проектам.
Например:
1.2.0— сменилиtrailingCommaсes5наall.2.0.0— убралиsemi: trueи поставилиsemi: false. Это сильно изменит стиль, значит это уже мажор.
Контроль изменений по проектам
Смотрите, как можно организовать обновления:
В каждом проекте фиксируете версию
@my-org/prettier-configвpackage.json:{ "devDependencies": { "@my-org/prettier-config": "^1.2.0" } }При выпуске новой версии пакета:
- открываете PR в каждый репозиторий;
- обновляете версию;
- запускаете
npx prettier . --checkили--write, чтобы увидеть разницу.
Анализируете, насколько велик дифф. Это хорошие входные данные для принятия решения, стоит ли применять такое обновление во всех сервисах.
Интеграция prettier-config с редакторами и CI
Сам конфиг — только половина истории. Важно, чтобы он стабильно применялся везде: на вашей машине, у коллег и в CI.
Настройка редакторов
Большинство редакторов (VS Code, WebStorm, Vim) умеют использовать локальную версию Prettier и его конфиг.
VS Code
- Установите расширение Prettier — Code formatter.
В настройках VS Code включите:
{ "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true }Убедитесь, что в проекте установлены:
prettier;- и ваш
@my-org/prettier-config, указанный вpackage.json.
VS Code автоматически найдет локальный конфиг — в том числе через поле prettier в package.json, которое ссылается на ваш пакет.
WebStorm / IDEA
WebStorm сам подхватывает локальный prettier из node_modules. В настройках нужно:
- Включить использование Prettier;
- Указать использовать локальную версию (project version);
- Включить форматирование при сохранении (On Save Actions).
Настройка в CI
Чтобы предотвратить попадание неотформатированного кода в репозиторий, в CI (например, GitHub Actions, GitLab CI, Jenkins) часто добавляют шаг проверки:
npx prettier . --check
Комментарий:
--checkне изменяет файлы, а только проверяет, соответствуют ли они формату.- Если кто-то не применил форматирование, сборка упадет.
В некоторых командах добавляют отдельный скрипт для ручного запуска:
{
"scripts": {
"format": "prettier . --write",
"format:check": "prettier . --check"
}
}
Так разработчики могут сами проверить формирование перед пушем.
Распространенные конфигурации и практические примеры
Давайте еще раз систематизируем типичные сценарии использования prettier-config и покажем конкретные настройки.
Общий конфиг для организации
Файл index.js в пакете @company/prettier-config:
// Базовый конфиг для всех JS/TS проектов компании
module.exports = {
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: true,
trailingComma: 'all',
bracketSpacing: true,
arrowParens: 'always',
endOfLine: 'lf',
overrides: [
// Для Markdown делаем более узкие строки и оставляем дефолтные особенности
{
files: '*.md',
options: {
printWidth: 80
}
},
// Для YAML иногда удобнее 2 пробела и без изменений по другим опциям
{
files: ['*.yml', '*.yaml'],
options: {
tabWidth: 2
}
}
]
};
Теперь в любом проекте вы:
Устанавливаете пакет:
npm install --save-dev prettier @company/prettier-configВ
package.jsonдобавляете:{ "prettier": "@company/prettier-config" }Настраиваете команды:
{ "scripts": { "format": "prettier . --write", "format:check": "prettier . --check" } }
Комбинация общего и проектного конфига
Представим, что у вас есть общий пакет @company/prettier-config, а в конкретном проекте нужно:
- использовать
semi: false; - добавить специфические overrides для
.graphqlфайлов.
Файл .prettierrc.js в проекте:
// Покажу вам, как расширить общий конфиг без дублирования
const baseConfig = require('@company/prettier-config');
module.exports = {
// Базовые опции
...baseConfig,
// Локальное переопределение
semi: false,
// Объединяем overrides: берем из базового конфига и добавляем свои
overrides: [
...(baseConfig.overrides || []),
{
files: '*.graphql',
options: {
printWidth: 80
}
}
]
};
Обратите внимание, как этот фрагмент кода решает задачу:
- сначала импортирует базовый конфиг;
- затем аккуратно объединяет массив
overrides, не потеряв настройки для Markdown/YAML; - переопределяет только нужные опции.
Заключение
Конфиг Prettier — это центральная точка, где вы определяете стиль форматирования для проекта. Когда проектов становится много, логично вынести его в отдельный prettier-config-пакет, чтобы:
- обеспечить единый стиль кода во всех репозиториях;
- централизованно обновлять правила;
- сократить дублирование настроек и риск рассинхронизации.
Вы увидели, как:
- устроены основные форматы конфигов (
.prettierrc,prettier.config.js, полеprettierвpackage.json); - выглядят ключевые опции форматирования (строки, кавычки, точка с запятой, запятые, JSX);
- создать собственный npm-пакет с конфигом Prettier;
- подключить этот пакет в проектах и при необходимости локально его расширять;
- интегрировать такой конфиг в редакторы, ESLint и CI.
С этими знаниями вы можете построить свою систему форматирования кода — от маленького проекта до целой организации с десятками репозиториев.
Частозадаваемые технические вопросы по теме prettier-config
1. Как использовать несколько prettier-config пакетов одновременно
Обычно Prettier ожидает один источник настроек. Если нужно объединить несколько конфигов (например, общий корпоративный и конфиг фреймворка), создайте локальный .prettierrc.js и явно слейте настройки:
const base = require('@company/prettier-config');
const framework = require('prettier-config-some-framework');
module.exports = {
...base,
...framework,
overrides: [
...(base.overrides || []),
...(framework.overrides || [])
]
};
Конфликтующие опции будут переопределены в пользу последнего объекта.
2. Как подключить prettier-config из Git репозитория без публикации в npm
Если вы не хотите публиковать пакет в npm, можно использовать Git URL в package.json:
{
"devDependencies": {
"@my-org/prettier-config": "git+https://github.com/my-org/prettier-config.git"
},
"prettier": "@my-org/prettier-config"
}
При установке npm подтянет код из репозитория. Важно, чтобы в этом репозитории был корректный package.json и main указывал на файл с конфигом.
3. Как временно отключить часть правил из общего prettier-config в одном проекте
Создайте локальный JS-конфиг и переопределите нужные опции:
const base = require('@my-org/prettier-config');
module.exports = {
...base,
semi: false, // Меняем конкретную опцию
trailingComma: 'es5' // И еще одну
};
Так вы не трогаете общий пакет, но на уровне проекта частично меняете поведение форматирования.
4. Почему Prettier игнорирует мой prettier-config пакет
Проверьте:
- Установлен ли пакет с конфигом в
devDependencies. - Указан ли он в
package.json— полеprettierили в.prettierrc.js. - Не перекрывается ли конфиг другим файлом ближе к форматируемому файлу.
- Точно ли вы запускаете локальную версию Prettier (через
npx prettierилиnode_modules/.bin/prettier), а не глобально установленную.
Если сомневаетесь, запустите:
npx prettier file.js --loglevel debug
В логах Prettier покажет, какой конфиг он использует.
5. Как использовать разные prettier-config пакеты для разных пакетов в монорепозитории
В монорепо (например, с pnpm или Yarn Workspaces) на уровне каждого пакета можно держать свой package.json с полем prettier. Для пакета А:
{
"name": "@my-org/app-a",
"prettier": "@my-org/prettier-config-app"
}
Для пакета Б:
{
"name": "@my-org/app-b",
"prettier": "@my-org/prettier-config-lib"
}
Инструменты вроде prettier "**/*.{js,ts}" нужно запускать из корня, но с флагом --config можно явно указать, какой конфиг применять к какой директории, либо запускать Prettier из контекста конкретного пакета (через workspace-скрипты).