## Механизм генерации manifest в сборке Vite
В процессе production-сборки Vite формирует оптимизированный набор статических ресурсов, разбивая код на чанки, применяя хеширование имён файлов и выполняя tree-shaking. В некоторых архитектурах приложений требуется явное знание того, какие файлы были сгенерированы сборщиком, их взаимосвязей и точек входа. Для этих целей используется режим генерации манифеста сборки.
## Назначение build.manifest
Параметр `build.manifest` включает генерацию JSON-файла, содержащего карту всех ассетов, созданных во время сборки. Этот файл выступает как индекс артефактов сборки и позволяет внешним системам или серверной части приложения точно определять:
* какие JS и CSS файлы соответствуют конкретным entry points
* какие чанки являются динамическими зависимостями
* какие ассеты были извлечены из модулей
* какие файлы имеют хешированные имена
Основная идея заключается в переносе ответственности за связывание HTML и ассетов с клиента на сервер или отдельный слой интеграции.
## Включение manifest в конфигурации
Включение механизма выполняется через конфигурационный файл Vite:
```javascript
import { defineConfig } from 'vite'
export default defineConfig({
build: {
manifest: true
}
})
```
После выполнения сборки в директории `dist` появляется файл `manifest.json`.
## Структура manifest.json
Содержимое манифеста представляет собой объект, где ключами являются исходные входные модули или виртуальные entry points, а значениями — описания соответствующих собранных ресурсов.
Пример упрощённой структуры:
```json
{
"src/main.js": {
"file": "assets/main.8f3a1c2d.js",
"src": "src/main.js",
"isEntry": true,
"css": ["assets/main.4e2b1c9d.css"],
"imports": ["vendor.js"]
},
"vendor.js": {
"file": "assets/vendor.91ab3f0c.js",
"isEntry": false
}
}
```
Каждое поле имеет конкретную семантику:
* `file` — основной JS-файл чанка
* `css` — массив CSS-файлов, извлечённых из данного entry
* `imports` — зависимости, подгружаемые динамически или как shared chunks
* `isEntry` — признак точки входа
## Роль manifest в архитектуре SSR
В серверно-рендеринговых приложениях (SSR) манифест используется как связующее звено между сервером и клиентскими ассетами. Сервер не знает заранее имён файлов, поскольку Vite добавляет хеши для кеширования. Поэтому именно manifest становится источником истины.
Типичный сценарий:
1. Сервер обрабатывает запрос
2. Определяет нужный entry point
3. Считывает manifest.json
4. Находит соответствующие JS и CSS файлы
5. Вставляет их в HTML-ответ
Пример серверной логики:
```javascript
import manifest from './dist/manifest.json' assert { type: 'json' }
function getAssets(entry) {
const chunk = manifest[entry]
return {
js: chunk.file,
css: chunk.css || []
}
}
```
## Связь manifest и code splitting
Vite автоматически применяет разделение кода при использовании динамических импортов:
```javascript
import('./module.js')
```
Каждый такой импорт формирует отдельный chunk, который также попадает в manifest. В результате manifest становится графом зависимостей, отражающим структуру приложения после оптимизации.
Особенности отражения динамических импортов:
* каждый async chunk получает собственный ключ
* зависимости между чанками фиксируются через `imports`
* повторно используемые модули выносятся в shared chunks
## Использование manifest в шаблонизации HTML
В классическом SPA Vite сам подставляет скрипты в HTML. Однако при серверной интеграции HTML формируется вручную.
Пример генерации HTML:
```javascript
function renderHtml(entry) {
const { js, css } = getAssets(entry)
const cssLinks = css
.map(file => `
`)
.join('\n')
return `
${cssLinks}