Стек: React, TypeScript, ESLint 9, IDE: VS Code.
Зачем организовывать импорты
Импорты в приложении – самодокументируемая шапка файла. Взглянув на неё, можно быстро сделать вывод о содержимом: какие библиотеки, компоненты, типы и стили - если речь о React-компоненте - используются в файле, и создать общее впечатление о модуле.
Хорошо, когда эта «шапка» имеет единый порядок: мы быстро можем увидеть, например, какие типы использует файл, много ли компонентов он содержит и т.п. Короче говоря – это ускоряет и точечный, и общий анализ файла. Ну и просто приятно, когда код содержится в порядке и подчиняется единым правилам.
Цели, поставленные для организации импортов
-
Разделить импорты на группы: библиотеки / внешние / внутренние / типы TypeScript / стили и прочее.
-
Типы TypeScript тоже должны быть разделены на группы, соответствующие основным группам импортов. Также необходимо использовать в файле только top-level type imports (
import type { ... }), inline type imports не использовать (мне кажется, так удобнее). -
Чтобы разделители (новые строки) добавлялись автоматически между определёнными группами, а не между всеми подряд.
Делать это вручную или просить команду всегда выделять импорты отдельно – можно, но сложно. Всё равно будут ошибки, что послужит поводом для комментария на ревью.
Попытка использовать только eslint-plugin-import
Первый плагин, который я попробовала – популярный eslint-plugin-import. У него есть важное правило import/consistent-type-specifier-style, которое позволяет отделить все inline-импорты типов в top-level. (Если существуют другие способы выделения типов в top-level imports – было бы интересно узнать.)
С помощью этого плагина я хотела настроить и порядок импортов, но не хватило кастомизации, а именно – выделения стилей в отдельную группу (нужно создавать кастомную с регулярными выражениями), расстановки новых строк только между определенными группами, а не между всеми. Это мелочи, которые можно было решить ручной доработкой, но хотелось добиться полной автоматической правки файла при сохранении.
Добавление плагина eslint-plugin-perfectionist
В итоге я настроила порядок импортов с помощью другого популярного плагина – eslint-plugin-perfectionist. У него больше групп по умолчанию и более гибкая настройка расположения новых строк между группами. Единственный недостаток: нет встроенного правила для автоматической группировки импортов типов в соответствии с порядком основных импортов – расстановку импортов типов нужно прописывать явно в массиве групп.
Получившийся конфиг
В итоге я использовала комбинацию двух вышеуказанных плагинов, и это позволило добиться желаемого результата - автоматической настройки без ручных доработок. И некоторого снижения количества комментариев в код-ревью)
Обратите внимание на customGroups. По задумке импорты React должны идти первыми и в основных импортах, и в типах TypeScript. Группа type-react идёт первой в массиве customGroups, поэтому при сортировке типы React отделяются первыми в отдельную группу. Если поменять порядок групп в customGroups, типы React попадут наверх вместе с обычными импортами React, а это нам не нужно.
import importPlugin from 'eslint-plugin-import';
import perfectionisPlugin from 'eslint-plugin-perfectionist';
export default {
files: ['**/*.{js,ts,tsx}'],
plugins: { perfectionist: perfectionisPlugin, import: importPlugin },
rules: {
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], // разрешает только top-level type import
'import/newline-after-import': ['error', { count: 1 }], // пустая строка после импортов
'perfectionist/sort-imports': [
'error',
{
type: 'alphabetical', // сортировка элементов по алфавиту
order: 'asc', // порядок от a к z
ignoreCase: true, // игнорирование регистра при сортировке
groups: [
'side-effect', // side-effect импорты
{ newlinesBetween: 1 },
'builtin', // node встроенные модули (fs, path)
{ newlinesBetween: 1 },
'react',
{ newlinesBetween: 0 },
'external', // npm пакеты
{ newlinesBetween: 1 },
'internal', // внутренние импорты
{ newlinesBetween: 'ignore' },
'parent', // ../ импорты
{ newlinesBetween: 'ignore' },
'sibling', // ./ импорты
{ newlinesBetween: 'ignore' },
'index', // ./index импорты
{ newlinesBetween: 1 },
'import', // любые импорты
{ newlinesBetween: 1 },
// все импорты типов
'type-react',
{ newlinesBetween: 0 },
'type-external',
{ newlinesBetween: 1 },
'type-internal',
{ newlinesBetween: 'ignore' },
'type-parent',
{ newlinesBetween: 'ignore' },
'type-sibling',
{ newlinesBetween: 'ignore' },
'type-index',
{ newlinesBetween: 0 },
'type-import',
{ newlinesBetween: 1 },
'side-effect-style', // side-effect импорты стилей
{ newlinesBetween: 0 },
'style', // импорты стилей
],
customGroups: [
{
groupName: 'type-react',
elementNamePattern: ['^react$', '^react-.*'],
selector: 'type',
},
{
groupName: 'react',
elementNamePattern: ['^react$', '^react-.*'],
},
],
newlinesBetween: 1, // пустая строка между группами
internalPattern: ['^app/.+'], // петтерны внутренних путей
},
],
},
};
Результат применения
примеры до


примеры после


Если у вас есть опыт организации импортов в больших проектах или вы знаете другие способы автоматической сортировки – буду рада обсудить в комментария��!
Автор: EkaterinaSL
