1. Фон
Если в предыдущей статье мы рассматривали физическую структуру на основе монорепозитория (Monorepo), то в этот раз мы поговорим о том, как унифицировать правила написания кода между разработчиками, которые пишут код на этом уровне.
По мере увеличения масштаба проекта увеличилось количество случаев, когда несколько разработчиков редактируют один и тот же файл, что постоянно приводило к ненужным Git diff из-за различий в отступах или стиле кавычек. Эти различия в стиле стали причиной повторяющихся обсуждений в процессе ревизии кода, что в конечном итоге увеличивало усталость от ревью.
Только сортировка руководства на корпоративной вики (Wiki) имела свои ограничения в решении этих проблем, и необходима была автоматизированная система, способная принудительно применять правила вне зависимости от ошибок разработчиков до того, как код был отражён в удалённом репозитории.
В этой статье мы поделимся процессом внедрения кодовых соглашений с использованием ESLint и Prettier на основе среды Vue 3 и TypeScript, а также способов применения одних и тех же правил в среде VS Code и IntelliJ.
2. Разделение ролей ESLint и Prettier
Чтобы решить эти проблемы, сначала необходимо четко разграничить роли ESLint и Prettier.
ESLint является инструментом проверки качества кода, который обнаруживает неиспользуемые переменные, потенциальные шаблоны ошибок, неправильную структуру кода и т.д.
С другой стороны, Prettier — это инструмент, который автоматически упорядочивает визуальные правила, такие как отступы, разрывы строк, стиль кавычек, чтобы поддерживать единообразие формата кода.
Наиболее распространенная проблема при совместном использовании этих двух инструментов — столкновение правил. Поскольку ESLint также включает некоторые стилистические правила, он может по-разному оценивать одни и те же области по сравнению с Prettier.
Для решения этой проблемы в данном проекте мы использовали plugin:prettier/recommended, чтобы результаты Prettier можно было проверять также в процессе выполнения ESLint. Это позволяет одновременно проверять качество кода и проблемы форматирования только с помощью выполнения ESLint.
Пример настройки ESLint, примененного в проекте, приведён ниже.
// .eslintrc
{
"root": true,
"env": {
"node": true,
"browser": true,
"es2021": true
},
"parser": "vue-eslint-parser",
"parserOptions": {
"parser": "@typescript-eslint/parser",
"ecmaVersion": "latest",
"sourceType": "module"
},
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-recommended", // Vue 3 환경에서 권장되는 규칙 적용
"plugin:prettier/recommended"
],
"rules": {
"vue/multi-word-component-names": "off", // 단일 단어 컴포넌트명 허용
"no-console": "warn",
"@typescript-eslint/no-explicit-any": "off"
}
}
Обратите внимание, что данный пример основан на Legacy Config среде на основе .eslintrc. В зависимости от версии eslint-plugin-vue, используемой в проекте, можно использовать plugin:vue/vue3-recommended или plugin:vue/recommended.
Кроме того, начиная с ESLint 9, рекомендуется использовать Flat Config (eslint.config.js), поэтому для новых проектов будет полезно ознакомиться с официальным документом.
3. Составление общих правил проекта
Мы добавили .editorconfig, чтобы редакторы, поддерживающие EditorConfig в проекте, следовали одинаковым основным правилам.
В частности, настройка end_of_line = lf помогает сократить ненужные Git diff, возникающие из-за различий в способах разбиения строк между Windows и macOS (CRLF/LF).
Значение каждой настройки следующее:
-
indent_style = space: унификация отступов
-
indent_size = 2: поддержание стилевых стандартов проекта Vue/TS
-
end_of_line = lf: предотвращение конфликтов разбиения строк между ОС
-
insert_final_newline = true: гарантированная новая строка в конце файла
-
trim_trailing_whitespace = true: удаление ненужных пробелов
Настройки EditorConfig следующие:
# .editorconfig
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
4. Синхронизация среды IDE
Даже если правила определены, они теряют смысл, если не применяются одинаково в IDE. На практике в среде, где используется как VS Code, так и IntelliJ (включая WebStorm), возникли проблемы с повторяющимися Git diff из-за различий в форматировании.
4.1 Причина проблемы
VS Code легко применяет Prettier на основе расширений, но IntelliJ использует свой собственный форматер по умолчанию, и в зависимости от настроек может использовать форматер IDE вместо Prettier. Это приводит к тому, что при одинаковом коде результаты форматирования отличаются в зависимости от IDE.
4.2 Решение
4.2.1 Настройки VS Code
В VS Code мы настроили автоматическое форматирование и автоматическое исправление ESLint при сохранении.
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
Обратите внимание, что способ настройки source.fixAll.eslint может различаться в зависимости от версии расширений VS Code и ESLint, и в современных средах использование "explicit" иногда рекомендуется.
4.2.2 Настройки IntelliJ
В среде IntelliJ мы унифицировали настройки следующим образом.
-
Укажите путь к Prettier на основе проекта node_modules
-
Обязательное использование Prettier при реформации кода
-
Делегируйте форматирование при сохранении не IDE-форматеру, а Prettier
Эта настройка позволила минимизировать различия в форматировании между IDE.
5. Причины и решения ошибок парсинга Vue SFC
В процессе первоначального применения возникли ошибки парсинга ESLint внутри Vue 3 Single File Component (SFC, .vue). В частности, возникала проблема с тем, что область <script setup lang="ts"> не интерпретировалась должным образом, что приводило к неестественным ошибкам, связанным с TypeScript. Это могло происходить из-за использования только @typescript-eslint/parser без vue-eslint-parser, который понимает структуру Vue SFC, или если конфигурация парсера неправильно связана.
Чтобы решить эту проблему, мы разделили парсер структуры Vue и области скрипта.
// .eslintrc
{
// ...생략
"parser": "vue-eslint-parser", // 최상단 파서로 Vue 파일의 기본 구조 해석
"parserOptions": {
"parser": "@typescript-eslint/parser", // 스크립트 내부 영역만 TS 파서가 담당
"ecmaVersion": "latest",
"sourceType": "module"
},
// ...생략
}
После этой настройки линтинг также нормально работал в файлах .vue, и ошибки парсинга были устранены.
6. Операционный опыт и ограничения
При первоначальном внедрении в существующем кодовом базисе возникло более 200 ошибок линтинга. Основными причинами были использование any, console.log и нарушение правил именования компонентов Vue. Поскольку принудительное применение всех правил в статусе ошибки может повлиять на скорость разработки, в начале мы использовали стратегию постепенного применения, устанавливая некоторые правила в warn или off. Кроме того, так как console.log часто используется в процессе отладки, в начале мы использовали no-console на уровне предупреждения.
На этом этапе мы также не применяли верификацию коммитов на основе Husky. Изначально мы рассматривали принуждение этапа коммита через lint-staged и Husky, но приоритет был отдан унификации локальной среды разработки и стабилизации опыта разработки внутри команды. В будущем мы рассматриваем возможность добавления проверки ESLint на этапе коммита или CI, чтобы не допустить влияние различий в средах разработки на качество кода.
7. Заключение
Наибольшее изменение, которое мы ощутили после применения ESLint и Prettier, касалось процесса ревью кода. Существенно сократив количество правок стиля, не связанных напрямую с функциональностью, разработчики смогли создать среду, в которой они могут сосредоточиться на бизнес-логике, а не на формате кода. В результате это помогло сократить время ревью кода и ненужные изменения, а также стало основой для поддержания качества кода на определённом уровне.
Автоматизированная среда кодовых соглашений может стать важной основой для поддержания согласованности в условиях масштабного сотрудничества.
Список литературы
- Официальная документация ESLint: https://eslint.org/
- Официальная документация Prettier: https://prettier.io/
- Официальная документация EditorConfig: https://editorconfig.org/
- Официальная документация плагина Vue ESLint: https://eslint.vuejs.org/
Code_Latte