Условное применение загрузчиков: include, exclude, resource

В конфигурации Webpack управление тем, какие файлы обрабатываются загрузчиками (loaders), является одним из ключевых механизмов оптимизации сборки. Даже простая цепочка загрузчиков может существенно замедлить сборку, если она применяется ко всему дереву зависимостей без ограничений. Именно поэтому используются фильтры области применения: include, exclude и более современный механизм resource (resourceQuery, resourceFragment).

Эти параметры позволяют точно определить, к каким файлам применять конкретный loader, исключая лишнюю работу и повышая предсказуемость сборки.


Базовый принцип работы условий применения loaders

Каждое правило module.rules в Webpack содержит описание:

  • какие файлы обрабатывать (test)
  • чем обрабатывать (use)
  • и при каких условиях это делать (include, exclude, resource)

На уровне механизма Webpack каждое правило проходит проверку: подходит ли ресурс под условия. Если условия совпадают — loader применяется, если нет — правило игнорируется.


include: ограничение области обработки

Суть include

Параметр include задаёт список директорий или файлов, которые должны обрабатываться данным loader’ом. Всё, что не входит в указанный диапазон, игнорируется.

Это наиболее часто используемый способ ускорения сборки.

Логика работы

Webpack проверяет путь файла:

  • если файл находится внутри указанных директорий — правило применяется
  • если вне — правило пропускается

Пример использования

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve(__dirname, 'src'),
        use: 'babel-loader'
      }
    ]
  }
};

В данном случае babel-loader применяется только к файлам внутри src, исключая node_modules, тестовые директории и любые сторонние зависимости.


Практический смысл include

Основная задача:

  • ограничить трансформацию только исходным кодом проекта
  • избежать повторной обработки библиотек
  • уменьшить время сборки

Особенно важно при использовании:

  • babel-loader
  • ts-loader
  • eslint-loader (устаревший)
  • sass-loader

Множественные include

Можно указывать массив путей:

include: [
  path.resolve(__dirname, 'src'),
  path.resolve(__dirname, 'shared')
]

Webpack будет обрабатывать файлы, которые находятся хотя бы в одной из директорий.


exclude: явное исключение файлов

Суть exclude

Параметр exclude работает противоположно include: он запрещает обработку файлов, даже если они подходят под test.

Логика приоритетов

При конфликте:

  • include задаёт допустимую область
  • exclude вырезает часть из неё

Если файл совпадает с exclude — loader не применяется, независимо от include.


Пример использования

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      }
    ]
  }
};

Здесь исключаются все зависимости из node_modules, что является стандартной практикой.


Типичные сценарии exclude

Используется для:

  • исключения node_modules
  • отключения обработки сборочных папок (dist, build)
  • исключения тестов или mock-данных
  • предотвращения двойной трансформации

include vs exclude: стратегия выбора

Оба параметра могут использоваться вместе, но логика следующая:

  • include — задаёт белый список
  • exclude — задаёт чёрный список

На практике предпочтительнее:

  • либо использовать include (более безопасно)
  • либо комбинировать include + exclude для точной настройки

Пример комбинированного использования

{
  test: /\.ts$/,
  include: path.resolve(__dirname, 'src'),
  exclude: /node_modules/,
  use: 'ts-loader'
}

Здесь:

  • обрабатываются только файлы src
  • при этом дополнительно исключаются любые попадания в node_modules

resource: точечное управление применением loader

Переход к более точному контролю

Параметр resource (и связанные с ним resourceQuery, resourceFragment) позволяет задавать условия на уровне самого ресурса, а не только пути.

Это более современный и гибкий механизм, который используется в сложных конфигурациях.


resource: базовое использование

resource задаёт фильтрацию по абсолютному пути файла.

Пример

module.exports = {
  module: {
    rules: [
      {
        resource: {
          test: /\.css$/
        },
        use: ['style-loader', 'css-loader']
      }
    ]
  }
};

В этом случае правило применяется только к ресурсам, удовлетворяющим условию внутри resource.test.


Разница между test и resource

Классический вариант:

{
  test: /\.css$/,
  use: 'css-loader'
}

Эквивалент через resource:

{
  resource: {
    test: /\.css$/
  },
  use: 'css-loader'
}

Однако resource позволяет комбинировать более сложные условия, включая дополнительные параметры.


resourceQuery: фильтрация по запросу импорта

Суть

Webpack позволяет импортировать ресурсы с query-параметрами:

import styles from './button.css?inline';

resourceQuery позволяет реагировать на такие случаи.

Пример

{
  resourceQuery: /inline/,
  type: 'asset/source'
}

Теперь правило применяется только если импорт содержит ?inline.


Практическое применение resourceQuery

Используется для:

  • разных режимов загрузки одного и того же файла
  • переключения между inline и file-loader логикой
  • кастомной обработки ресурсов

resourceFragment: работа с фрагментами URL

Webpack также поддерживает #hash-часть импортов:

import icon from './sprite.svg#icon-user';

Пример использования

{
  resourceFragment: /icon-user/,
  type: 'asset/resource'
}

Позволяет выбирать поведение в зависимости от фрагмента ресурса.


Совместное использование resource с другими фильтрами

На практике resource редко используется изолированно. Он комбинируется с:

  • issuer (откуда импортирован файл)
  • include
  • exclude

Пример сложной логики

{
  test: /\.svg$/,
  issuer: /\.js$/,
  resourceQuery: /component/,
  use: ['svgr-loader']
}

Здесь loader применяется только если:

  • файл .svg
  • импортирован из JS
  • содержит ?component

Приоритет и порядок проверки условий

Webpack оценивает условия последовательно:

  1. resource (если задан)
  2. test
  3. include
  4. exclude

Если хотя бы одно условие не проходит — loader не применяется.


Производительность и влияние условий

Правильное использование include/exclude/resource напрямую влияет на:

  • скорость initial build
  • скорость rebuild при watch режиме
  • использование памяти
  • количество обработанных модулей

Наиболее критичный фактор — ограничение Babel/TypeScript трансформаций только исходным кодом.


Типичные ошибки при использовании условий

Отсутствие include

{
  test: /\.js$/,
  use: 'babel-loader'
}

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


Слишком широкий include

include: path.resolve(__dirname)

Такой подход включает даже node_modules, что часто приводит к ненужной обработке.


Конфликт include и exclude

Если включены оба параметра без понимания приоритетов, возможны ситуации, когда правило не срабатывает вовсе или срабатывает частично.


Роль условий в архитектуре сборки

Условия применения loaders являются частью архитектуры сборочного процесса. Они определяют:

  • границы ответственности каждого loader’а
  • изоляцию стороннего кода от трансформаций
  • структуру пайплайна обработки ресурсов

Правильно настроенные include/exclude/resource позволяют превратить Webpack из «глобального обработчика» в систему точечных правил, работающих только там, где это действительно необходимо.