clean: автоматическая очистка директории вывода

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

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


При стандартной конфигурации Webpack:

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
  },
};

каждая сборка может порождать новый набор файлов, при этом старые версии остаются в директории. Это приводит к следующим эффектам:

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

output.clean в Webpack 5

Начиная с Webpack 5 встроен механизм автоматической очистки директории через параметр output.clean.

const path = require('path');

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
    clean: true,
  },
};

При установке clean: true Webpack перед генерацией новых ассетов удаляет содержимое выходной директории, относящееся к текущей сборке.

Особенности поведения

Очистка выполняется с учетом следующих принципов:

  • удаляются только файлы внутри output.path;
  • операция выполняется перед эмиссией новых ассетов;
  • не затрагиваются файлы вне контекста сборки;
  • работает на уровне внутренней файловой системы Webpack без внешних плагинов.

Тонкая настройка очистки

Параметр clean поддерживает объектную форму конфигурации, позволяющую управлять исключениями.

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
    clean: {
      keep: /static/,
    },
  },
};

Поведение keep

Опция keep определяет файлы или директории, которые не должны удаляться:

  • регулярные выражения;
  • строки;
  • функции фильтрации.

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

clean: {
  keep: ['favicon.ico', 'static'],
}

или

clean: {
  keep: (asset) => asset.includes('legacy'),
}

Это позволяет сохранять:

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

CleanWebpackPlugin и исторический контекст

До Webpack 5 очистка выполнялась через CleanWebpackPlugin:

const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  plugins: [new CleanWebpackPlugin()],
};

Плагин предоставлял расширенные возможности:

  • очистка нескольких директорий;
  • dry-run режим;
  • подробное логирование удалений;
  • более гибкая фильтрация.

Сравнение подходов

Встроенный output.clean:

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

CleanWebpackPlugin:

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

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


Режимы сборки и влияние очистки

Development режим

В режиме разработки частая пересборка может приводить к:

  • перезаписи файлов;
  • росту времени I/O операций при очистке;
  • нежелательному удалению кэша ассетов.

В некоторых случаях очистка отключается:

module.exports = {
  output: {
    clean: false,
  },
};

или управляется условно:

clean: process.env.NODE_ENV === 'production',

Production режим

В production очистка критична для обеспечения:

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

Работа с хешированными файлами

Использование [contenthash] приводит к генерации уникальных имен при изменении содержимого:

filename: '[name].[contenthash].js'

Без очистки директории возникают ситуации:

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

Очистка решает задачу атомарности сборки: результат всегда представляет полный актуальный снимок.


Мультиконфигурации и shared output

При использовании массива конфигураций:

module.exports = [
  {
    name: 'client',
    output: {
      path: path.resolve(__dirname, 'dist/client'),
      clean: true,
    },
  },
  {
    name: 'server',
    output: {
      path: path.resolve(__dirname, 'dist/server'),
      clean: true,
    },
  },
];

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

  • client/server сборок;
  • legacy/modern bundles;
  • разных окружений.

Incremental builds и watch mode

В режиме watch очистка выполняется иначе, чем в полной сборке:

  • Webpack старается минимизировать операции удаления;
  • обновляются только измененные ассеты;
  • полная очистка происходит только при перезапуске процесса.

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


Особенности взаимодействия с HTML генерацией

При использовании HtmlWebpackPlugin:

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  output: {
    clean: true,
  },
};

очистка директории обеспечивает согласованность:

  • HTML всегда ссылается на актуальные файлы;
  • отсутствуют «битые» ссылки на удаленные чанки;
  • нет накопления старых HTML-версий при ручной генерации.

Потенциальные проблемы и ограничения

Удаление внешних файлов

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

Типичный риск:

  • сервисы деплоя копируют файлы в dist;
  • Webpack с clean: true удаляет их перед новой сборкой.

Конкуренция процессов

При параллельных сборках:

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

CI/CD сценарии

В системах непрерывной интеграции очистка используется как гарант детерминированности:

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

Часто применяется комбинация:

  • clean: true;
  • изолированные директории сборки;
  • кеширование вне dist.

Безопасность и предсказуемость

Механизм очистки ограничен output.path, что снижает риск удаления файлов вне области ответственности сборщика. Однако конфигурационные ошибки могут привести к:

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

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


Поведение при ошибках сборки

При неуспешной сборке:

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

В некоторых инфраструктурах используется стратегия:

  • сборка в временную директорию;
  • атомарное перемещение результата в dist.

Инкрементальная стратегия через staging директории

Подход с промежуточной директорией:

output: {
  path: path.resolve(__dirname, 'build-temp'),
  clean: true,
}

После успешной сборки:

  • содержимое переносится в dist;
  • предыдущая версия сохраняется до подтверждения новой.

Это снижает риск простоя при частично успешных сборках.


Влияние на производительность

Операция очистки зависит от:

  • количества файлов в директории;
  • особенностей файловой системы;
  • типа диска (SSD/HDD);
  • режима параллельной записи.

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

  • исключения clean в dev;
  • оптимизации структуры ассетов;
  • вынесения статических файлов за пределы output.