Долгосрочное кэширование в фронтенд-сборке строится на строгом правиле: если содержимое файла не изменилось, его URL должен оставаться неизменным. Браузер и CDN опираются на этот принцип при сохранении ресурсов в кэше.
Ключевая идея:
URL файла = ключ к кэшу
Если имя файла включает хэш, зависящий от содержимого, любое изменение кода автоматически приводит к новому имени, а старый файл остаётся доступным для повторного использования.
В контексте сборщика Esbuild это реализуется через шаблоны имён выходных файлов, где в имя подставляются специальные токены:
[name] — исходное имя модуля[ext] — расширение файла[hash] — хэш содержимогоEsbuild не хранит отдельную систему кэш-ключей как Webpack, но предоставляет встроенную поддержку шаблонов именования выходных файлов.
Основные параметры конфигурации:
entryNameschunkNamesassetNamesПример базовой конфигурации:
import * as esbuild from 'esbuild';
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
entryNames: '[name]-[hash]',
chunkNames: 'chunks/[name]-[hash]',
assetNames: 'assets/[name]-[hash]',
});
[hash]Хэш в Esbuild:
Важное свойство:
Один и тот же входной код всегда даёт одинаковый хэш в рамках одинаковой сборки
Entry-файлы — это точки входа приложения.
entryNames: '[name]-[hash]'
Пример результата:
dist/index-a1b2c3.js
dist/admin-d4e5f6.js
Здесь:
index и admin — имена entry pointsa1b2c3, d4e5f6 — хэши содержимогоПри включённом splitting: true Esbuild формирует
динамические чанки:
esbuild.build({
entryPoints: ['src/app.js'],
bundle: true,
splitting: true,
format: 'esm',
outdir: 'dist',
chunkNames: 'chunks/[name]-[hash]',
});
Пример структуры:
dist/
app-9f8e1c.js
chunks/
vendor-3aa21d.js
utils-7c19bd.js
Особенности:
Ассеты, импортируемые через JS или CSS, также получают хэшированные имена:
assetNames: 'assets/[name]-[hash]'
Пример:
dist/assets/logo-91c2ab.png
dist/assets/font-12fe44.woff2
Esbuild формирует хэш не от исходного файла, а от финального результата:
Следствие:
Любое изменение в зависимостях может изменить хэш даже без изменения самого файла.
При стабильной сборке:
дают стабильные хэши, что критично для CDN-кэширования.
Tree shaking напрямую влияет на итоговый хэш.
Пример:
// utils.js
export const a = 1;
export const b = 2;
// index.js
import { a } from './utils.js';
console.log(a);
После сборки:
b удаляетсяaaТаким образом:
меньше кода → другой хэш → корректная инвалидизация кэша
Esbuild может генерировать метафайл сборки:
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
metafile: true,
});
Он содержит структуру:
Это позволяет:
Система долгосрочного кэширования обычно разделяет ресурсы:
app-3f2a1d.js
vendor-91c44e.js
styles-88bd11.css
Заголовки:
Cache-Control: public, max-age=31536000, immutable
index.html
Он всегда обновляется и содержит ссылки на новые хэшированные файлы.
Esbuild сам по себе не генерирует HTML, но часто используется вместе с плагинами.
Пример логики:
<script src="app-3f2a1d.js"></script>
После пересборки:
<script src="app-7c91aa.js"></script>
HTML становится единственной точкой инвалидации кэша.
Даже незначительные изменения могут менять хэш большого бандла:
Это связано с тем, что Esbuild генерирует единый граф и пересчитывает финальный результат.
Для повышения стабильности используется разделение:
entryPoints: {
vendor: ['react', 'react-dom']
}
или через splitting:
При использовании:
import('./module.js');
Esbuild создаёт отдельный чанк.
Поведение:
Это позволяет:
Ассеты часто имеют самый стабильный хэш.
Пример:
import logo from './logo.png';
После сборки:
logo-82ad91.png
Особенности:
Несмотря на встроенную поддержку, существуют ограничения:
Из metafile можно извлечь карту:
Пример логики:
src/index.js → dist/index-3f2a1d.js
src/utils.js → dist/chunks/utils-91c44e.js
Это используется для:
Браузер применяет стратегию:
Хэш в имени файла делает URL:
Типичная схема:
index.html — без кэша или с коротким TTL*.js, *.css, assets/* —
immutable + long cacheРезультат:
Minification напрямую влияет на хэш:
До минификации:
function sum(a, b) {
return a + b;
}
После:
function s(n,r){return n+r}
Хэш изменяется, даже если логика не менялась.
Это важное свойство:
хэш отражает не исходник, а итоговую поставку
В системах непрерывной доставки важно:
Иначе: