Опция cssChunkNames

В процессе сборки приложений, использующих CSS-модули или импорт стилей из JavaScript, система бандлинга сталкивается с задачей разбиения CSS на отдельные файлы (чанки). Это особенно важно при использовании code splitting, динамических импортов и ленивой загрузки модулей. В таких сценариях возникает необходимость управлять тем, как именно будут называться итоговые CSS-файлы.

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


Поведение CSS-чанков в Esbuild

При включённом code splitting Esbuild может извлекать CSS из JavaScript-модулей и формировать отдельные CSS-файлы для каждого чанка. Это происходит в следующих случаях:

  • использование динамического import()
  • разделение входных точек (multiple entry points)
  • наличие общих зависимостей между чанками
  • импорт CSS через import './styles.css'

В результате сборки формируются:

  • JavaScript-чанки
  • CSS-чанки, соответствующие этим JS-чанкам
  • общие CSS-файлы, если стили используются в нескольких местах

Именно для управления именованием этих CSS-файлов используется cssChunkNames.


Синтаксис и базовая форма

Опция задаётся в конфигурации сборки:

import * as esbuild from 'esbuild';

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  splitting: true,
  outdir: 'dist',
  cssChunkNames: 'styles/[name]-[hash]'
});

Значение cssChunkNames представляет собой строковый шаблон, аналогичный chunkNames, но применяемый исключительно к CSS-файлам, выделенным из чанков.


Плейсхолдеры в cssChunkNames

Шаблон поддерживает специальные токены, которые заменяются во время сборки.

[name]

Подставляет имя чанка, полученное из:

  • имени входной точки
  • имени динамического импорта
  • имени внутреннего чанка, вычисленного Esbuild

Пример:

styles/[name]-[hash]

Результат:

styles/dashboard-8a3f2c.css

[hash]

Генерируемый хеш содержимого CSS-чанка. Используется для:

  • кеширования
  • предотвращения конфликтов имён
  • инвалидации при изменении стилей

Хеш зависит от содержимого CSS, включая:

  • импортированные стили
  • зависимости модулей
  • итоговую структуру чанка

[dir] (при наличии вложенной структуры)

Используется для сохранения структуры каталогов исходного проекта в выходной директории.

Пример:

cssChunkNames: 'styles/[dir]/[name]-[hash]'

Если входной файл:

src/pages/admin/dashboard.js

Результат:

styles/pages/admin/dashboard-8a3f2c.css

Отличие от chunkNames

Esbuild разделяет именование JavaScript и CSS-чанков:

Опция Назначение
chunkNames JS-чанки
entryNames JS entry points
assetNames статические ресурсы
cssChunkNames CSS-чанки

Это разделение важно, поскольку CSS-чанки часто требуют иной стратегии именования, чем Jav * aScript:

  • CSS обычно кэшируется отдельно
  • стили могут загружаться раньше JS
  • возможна интеграция с CSS-пайплайнами (PostCSS, Tailwind)

Поведение при code splitting

При включённом параметре:

splitting: true

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

  1. извлекается из JS
  2. группируется по чанкам
  3. записывается в отдельные .css файлы
  4. получает имя по шаблону cssChunkNames

Пример структуры:

dist/
  app-1a2b3c.js
  dashboard-9f8e7d.js
  styles/
    app-4c5d6e.css
    dashboard-7a8b9c.css

Взаимодействие с разделяемыми стилями

Если один CSS импортируется в нескольких чанках, Esbuild может:

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

В этом случае cssChunkNames применяется к итоговому объединённому чанку, а не к исходному модулю.


Использование с вложенными структурами проектов

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

src/
  features/
    auth/
      login.js
      login.css
    profile/
      profile.js
      profile.css

Конфигурация:

cssChunkNames: 'styles/[dir]/[name]-[hash]'

Результат:

dist/styles/features/auth/login-a1b2c3.css
dist/styles/features/profile/profile-d4e5f6.css

Такой подход упрощает:

  • отладку
  • анализ сборки
  • интеграцию с CDN

Сценарии использования хеширования

Хеширование ([hash]) в CSS-чанках особенно важно при:

Кешировании на CDN

Файлы становятся immutable:

dashboard-8a3f2c.css

При изменении стилей:

dashboard-91c4d8.css

Браузер загружает новую версию без конфликтов кеша.


Изоляции версий модулей

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


Связь с runtime загрузкой

При динамических импортах:

import('./dashboard.js');

Esbuild создаёт отдельный JS-чанк и соответствующий CSS-чанк. Runtime автоматически подгружает оба файла.

Если используется шаблон:

cssChunkNames: 'css/[name]-[hash]'

то при загрузке dashboard.js также будет запрошен:

css/dashboard-xxxxxx.css

Особенности генерации имён

Стабильность именования

Имя [name] может изменяться в зависимости от:

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

Поэтому для production-сборок рекомендуется сочетать:

  • [name] для читаемости
  • [hash] для стабильности

Коллизии имён

Если несколько модулей имеют одинаковое имя (например, index.js в разных директориях), Esbuild автоматически разрешает конфликт, добавляя контекст пути в name.


Пример комплексной конфигурации

esbuild.build({
  entryPoints: ['src/app.js'],
  bundle: true,
  splitting: true,
  outdir: 'dist',
  format: 'esm',

  entryNames: 'js/[name]-[hash]',
  chunkNames: 'js/chunks/[name]-[hash]',
  assetNames: 'assets/[name]-[hash]',
  cssChunkNames: 'styles/chunks/[name]-[hash]'
});

В результате формируется единая структура:

dist/
  js/
  app-1a2b3c.js
  chunks/
    dashboard-4d5e6f.js
  styles/
    chunks/
      dashboard-7a8b9c.css

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

Опция cssChunkNames практически не влияет на скорость сборки, так как:

  • имя формируется на финальном этапе
  • не требует дополнительного анализа AST
  • не влияет на граф зависимостей

Основная нагрузка остаётся связанной с:

  • анализом импортов CSS
  • code splitting
  • минификацией

Поведение при отсутствии опции

Если cssChunkNames не задана, Esbuild использует дефолтный шаблон, аналогичный стандартному именованию чанков, обычно включающий:

  • имя чанка
  • внутренний хеш
  • базовую структуру выходной директории

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


Ограничения и нюансы

  • шаблон применяется только к CSS-чанкам, не к inline-стилям
  • не влияет на CSS, встроенный в JS без извлечения
  • не управляет минификацией CSS
  • не заменяет assetNames
  • не контролирует порядок загрузки стилей

Интеграция с другими инструментами

При использовании PostCSS или Tailwind CSS:

  • Esbuild сначала обрабатывает импорт
  • затем PostCSS трансформирует CSS
  • после этого формируется CSS-чанк
  • на финальном этапе применяется cssChunkNames

Это делает опцию независимой от CSS-трансформаций, но зависимой от финального графа модулей.