Стек: 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/.+'], // петтерны внутренних путей
      },
    ],
  },
};

Результат применения

примеры до

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

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

Комментарии (5)


  1. subzey
    24.02.2026 05:08

    Чувствую, что нахватаю минусов, но… не очень понимаю, зачем люди сортируют импорты.

    От этого же нет практической пользы: машинам наплевать на порядок, а люди всё равно эту простыню импортов не читают и проматывают сразу на реализацию.

    Я видел мерж реквесты, которые откладываются на день из-за неправильного переноса строки между импортами. Я видел мерж конфликты от того, что кто-то решил отсортировать импорты по алфавиту. Человеческие усилия и время впустую, и чего ради?


    1. ooko
      24.02.2026 05:08

      Чтоб ИИ быстрее заменил людей


    1. onmotion
      24.02.2026 05:08

      Порядок некоторых импортов, например таких, как scss важен (вы можете получить другой результат рендера).
      Так же, без правила сортировки, каждый мейнтенер будет коммитить кучу конфликтов или просто мусорных изменений в порядке импортов, согласно его видения или видения его IDE


      1. subzey
        24.02.2026 05:08

        Стили конечно особняком стоят, соглашусь. Но тут есть нюанс: Бандлер постарается сохранить порядок импортов в выхлопе, но совершенно не факт, что у него это получится если структура чанков станет сложнее плоского списка: при наследовании энтрей и аснхронном импорте. Хорошо, что у нас теперь есть @layer, и мы можем вручную устанавливать специфичность, а не полагаться на порядок импорта!

        А IDE — ну так у IDE есть оператор. Вводить автомат чтобы он огородился от действий других автоматов — Скайнет уже победил?)


    1. mops2
      24.02.2026 05:08

      Ну, то, что люди не читают импорты, не всегда верно. Думаю, в 90% это, конечно, так, особенно в мире фронта, где компонентный подход с потенциально маленькими компонентами. Но когда тебе нужно разобраться в импортах, вручную что-то поправить ну или по другим любым причинам, я думаю, проще смотреть на отсортированные и сгруппированные импорты, чем когда в каждом файле свой порядок.

      Ну и плюс импорты — это тоже часть кодстайла на проекте.

      Что касается последнего абзаца, то откладывание МРа из-за переноса строк между импортами уже выглядит как неправильно настроенные линтеры и форматеры. По поводу конфликтов они все равно будут, просто теперь ты можешь не тратить на это время, а вмержить и прогнать линтером. Как раз меньше человеческих усилий и больше автоматизации.

      Могу сказать за себя, я не сортирую импорты руками и не трачу на это время, но я пробегаюсь глазами по импортам, и, когда они отсортированы, в этом проще разобраться, а остальное делает линтер.