Экспорт объекта, функции и Promise

Конфигурация Webpack не ограничивается статическим объектом. Хотя базовый вариант представляет собой обычный JavaScript-объект, система загрузки конфигурации поддерживает более гибкие формы экспорта: функцию и Promise. Эти варианты позволяют адаптировать сборку под окружение, параметры запуска, режим выполнения и даже асинхронные источники данных.

Статический экспорт объекта

Наиболее простая и часто используемая форма — экспорт конфигурационного объекта напрямую:

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: __dirname + '/dist'
  }
};

Такой подход фиксирует конфигурацию на этапе загрузки файла. Webpack просто читает объект и использует его без дополнительной обработки. Это удобно для небольших проектов или стандартных сценариев, где не требуется адаптация под окружение.

Особенности статического объекта:

  • конфигурация не зависит от внешних параметров
  • отсутствует возможность динамического изменения настроек
  • минимальная гибкость при мультиокружениях (development/production/staging)

При увеличении сложности проекта статический объект начинает ограничивать архитектурные возможности, особенно при необходимости условной сборки.


Экспорт функции: динамическая конфигурация

Webpack поддерживает экспорт функции вместо объекта. Эта функция может возвращать конфигурацию на основе входных параметров.

Базовый формат:

module.exports = (env, argv) => {
  return {
    mode: argv.mode || 'development',
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: __dirname + '/dist'
    }
  };
};

Параметр env

env — это объект, передаваемый через CLI при запуске Webpack:

webpack --env production

или

webpack --env apiUrl=https://example.com

Пример обработки:

module.exports = (env) => {
  return {
    mode: env.production ? 'production' : 'development',
    entry: './src/index.js'
  };
};

env позволяет создавать конфигурации, зависящие от внешних условий, не изменяя сам файл конфигурации.


Параметр argv

argv содержит аргументы командной строки, переданные Webpack CLI:

module.exports = (env, argv) => {
  return {
    mode: argv.mode,
    devtool: argv.mode === 'development' ? 'source-map' : false,
    entry: './src/index.js'
  };
};

Наиболее часто используется поле argv.mode, которое автоматически задаётся при запуске:

webpack --mode production

Условная конфигурация внутри функции

Экспорт функции позволяет формировать различные конфигурации в зависимости от логики приложения:

module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';

  return {
    mode: isProduction ? 'production' : 'development',
    entry: './src/index.js',
    output: {
      filename: isProduction ? 'bundle.min.js' : 'bundle.js',
      path: __dirname + '/dist'
    },
    devtool: isProduction ? false : 'source-map'
  };
};

Такой подход позволяет централизовать правила сборки и избегать дублирования конфигураций.


Разделение конфигураций через функции

Функциональный экспорт часто используется для построения конфигураций по шаблону:

const createConfig = (env, argv) => {
  const isProd = argv.mode === 'production';

  return {
    mode: isProd ? 'production' : 'development',
    entry: './src/index.js',
    output: {
      filename: isProd ? 'app.min.js' : 'app.js',
      path: __dirname + '/dist'
    }
  };
};

module.exports = createConfig;

Такой подход позволяет:

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

Экспорт Promise: асинхронная конфигурация

Webpack поддерживает асинхронный экспорт через Promise. Это используется в случаях, когда конфигурация зависит от внешних источников: файлов, API, переменных окружения, удалённых сервисов.

Простейший пример:

module.exports = new Promise((resolve) => {
  setTimeout(() => {
    resolve({
      mode: 'development',
      entry: './src/index.js',
      output: {
        filename: 'bundle.js',
        path: __dirname + '/dist'
      }
    });
  }, 1000);
});

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


Использование внешних конфигурационных файлов

Promise-экспорт часто применяется для загрузки JSON или других источников:

const fs = require('fs');

module.exports = new Promise((resolve, reject) => {
  fs.readFile('./webpack.settings.json', 'utf-8', (err, data) => {
    if (err) {
      reject(err);
      return;
    }

    const settings = JSON.parse(data);

    resolve({
      mode: settings.mode,
      entry: settings.entry,
      output: {
        filename: settings.outputFile,
        path: __dirname + '/dist'
      }
    });
  });
});

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


Комбинирование Promise с логикой окружения

Асинхронная конфигурация может учитывать окружение:

module.exports = new Promise((resolve) => {
  const env = process.env.NODE_ENV;

  const config = {
    mode: env === 'production' ? 'production' : 'development',
    entry: './src/index.js',
    output: {
      filename: env === 'production' ? 'bundle.min.js' : 'bundle.js',
      path: __dirname + '/dist'
    }
  };

  resolve(config);
});

Здесь Promise не добавляет задержки, но сохраняет возможность расширения асинхронной логики в будущем.


Функция, возвращающая Promise

Наиболее гибкая форма — комбинация функции и Promise:

module.exports = (env, argv) => {
  return new Promise((resolve) => {
    const isProd = argv.mode === 'production';

    setTimeout(() => {
      resolve({
        mode: isProd ? 'production' : 'development',
        entry: './src/index.js',
        output: {
          filename: isProd ? 'bundle.min.js' : 'bundle.js',
          path: __dirname + '/dist'
        }
      });
    }, 500);
  });
};

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

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

Приоритет форм экспорта

Webpack определяет конфигурацию по типу экспортируемого значения:

  1. Объект — синхронная статическая конфигурация
  2. Функция — синхронная динамическая конфигурация
  3. Promise — асинхронная конфигурация

Функция может возвращать как объект, так и Promise, что делает её универсальным вариантом.


Практическая модель выбора

Статический объект применяется, когда конфигурация фиксирована и не зависит от внешних факторов.

Функция используется при наличии:

  • нескольких режимов сборки
  • необходимости обработки CLI-параметров
  • условной логики внутри конфигурации

Promise применяется при:

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

Архитектурное значение динамического экспорта

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

Функциональный и асинхронный экспорт делает возможными:

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

Webpack в таком подходе перестаёт быть просто инструментом бандлинга и становится системой выполнения конфигурационной логики на Node.js-уровне.