Шаблоны имён файлов: [name], [hash], [contenthash], [chunkhash]

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

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

Конфигурация обычно задаётся через параметры output.filename и output.chunkFilename.

output: {
  filename: '[name].bundle.js',
  chunkFilename: '[name].chunk.js',
}

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


Плейсхолдер [name]

[name] представляет собой символическое имя модуля или чанка. Оно формируется из ключей, заданных в конфигурации entry, либо задаётся явно при динамическом импорте.

При использовании одиночной точки входа:

entry: {
  app: './src/index.js'
}

результирующий файл:

app.bundle.js

При множественных точках входа:

entry: {
  main: './src/main.js',
  admin: './src/admin.js'
}

выходные файлы:

main.bundle.js
admin.bundle.js

Для динамических импортов [name] может формироваться из комментариев:

import(/* webpackChunkName: "utils" */ './utils.js')

Если имя не задано, Webpack использует числовой идентификатор чанка.

Ключевая особенность [name] заключается в читаемости. Он упрощает отладку и навигацию по сборке, но не гарантирует стабильность при сложной динамической структуре зависимостей.


Плейсхолдер [hash]

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

output: {
  filename: '[name].[hash].js'
}

Пример результата:

app.8f3a91c2.js

Особенности [hash]:

  • изменяется при любом изменении в проекте
  • применяется ко всей сборке целиком
  • не подходит для тонкой кеш-оптимизации
  • обеспечивает простое инвалидирование кэша

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

Использование [hash] характерно для простых сценариев деплоя, где важнее гарантированно сбросить кэш, чем минимизировать количество обновлённых файлов.


Плейсхолдер [chunkhash]

[chunkhash] привязан к конкретному чанку. Его значение вычисляется на основе содержимого модуля и всех зависимостей, входящих в данный чанк.

output: {
  filename: '[name].[chunkhash].js'
}

Пример:

app.3c1a9f2d.js
vendor.91bc44aa.js

Ключевые свойства:

  • изменяется только при изменении содержимого соответствующего чанка
  • обеспечивает точечное кеширование
  • оптимален для production-сборок с разделением кода

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

Особое значение [chunkhash] приобретает при разделении кода на vendor и application слои, где зависимости обновляются редко.


Плейсхолдер [contenthash]

[contenthash] основан исключительно на содержимом конкретного файла, независимо от того, в каком чанке он находится. Он часто применяется для ассетов, таких как CSS, изображения или отдельно извлечённые ресурсы.

output: {
  filename: '[name].[contenthash].js'
}

В случае CSS через плагины:

plugins: [
  new MiniCssExtractPlugin({
    filename: '[name].[contenthash].css'
  })
]

Пример результата:

styles.7a91c0de.css

Свойства [contenthash]:

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

В отличие от [chunkhash], он не учитывает структуру зависимостей, а опирается только на финальный результат генерации файла.


Сравнение стратегий хеширования

Различия между плейсхолдерами определяют стратегию кеширования и обновления ресурсов.

  • [hash] — глобальный хеш сборки Подходит для полного сброса кэша, но неэффективен при частичных изменениях

  • [chunkhash] — хеш отдельного чанка Оптимален для JavaScript-бандлов с разделением кода

  • [contenthash] — хеш конкретного файла Используется для статики и CSS

  • [name] — логическое имя ресурса Упрощает идентификацию, но не гарантирует стабильность


Взаимодействие с code splitting

При использовании динамического импорта и разделения кода система именования становится критически важной.

output: {
  filename: '[name].[chunkhash].js',
  chunkFilename: '[name].[chunkhash].js'
}

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

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

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

Финальное имя файла формируется как комбинация:

  1. имени чанка ([name])
  2. хеш-значения ([hash], [chunkhash], [contenthash])
  3. расширения файла

Порядок и состав зависят от конфигурации output и подключённых плагинов.

Типичная production-конфигурация:

output: {
  filename: '[name].[contenthash].js',
  chunkFilename: '[name].[contenthash].js',
  clean: true
}

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


Поведение при изменении модулей

Изменение исходного файла влияет на хеши по-разному в зависимости от выбранного плейсхолдера:

  • изменение модуля → меняется [chunkhash] только затронутого чанка
  • изменение ассета → меняется [contenthash] только этого файла
  • изменение любого кода → меняется [hash] всей сборки

Это поведение формирует основу стратегии cache busting в Webpack-сборках и определяет стабильность раздачи статических ресурсов.