## Множественные точки входа в Vite
### Базовая модель сборки и ограничения одностраничного входа
Vite по умолчанию ориентирован на одностраничные приложения, где основная точка входа задаётся через `index.html`, а модульное дерево строится от него. Такой подход упрощает конфигурацию и ускоряет холодный старт, поскольку сборщик работает с графом модулей, начиная с одного корня.
Однако при разработке более сложных систем возникает необходимость в нескольких независимых точках входа. Это характерно для:
* многостраничных приложений (MPA)
* административных панелей с отдельными разделами
* библиотек с несколькими бандлами
* гибридных приложений (часть страниц статические, часть SPA)
Vite поддерживает такие сценарии через конфигурацию Rollup, на котором основана production-сборка.
---
## Концепция multi-page application в Vite
Множественные точки входа в Vite реализуются на этапе production build через параметр `build.rollupOptions.input`. В режиме dev сервер продолжает работать в SPA-режиме, но сборка формирует несколько HTML и JS бандлов.
Ключевая идея заключается в том, что каждая точка входа представляет собой отдельный граф зависимостей, начинающийся с собственного HTML или JS файла.
---
## Структура проекта с несколькими входами
Типичная организация проекта:
```
project/
index.html
admin.html
dashboard.html
src/
main.js
admin.js
dashboard.js
```
Каждый HTML-файл ссылается на свой входной модуль:
```html
```
```html
```
```html
```
Такой подход сохраняет изоляцию контекстов и позволяет строить независимые приложения внутри одного репозитория.
---
## Настройка Vite для нескольких входных точек
Основная конфигурация задаётся в `vite.config.js`:
```js
import { defineConfig } from 'vite';
export default defineConfig({
build: {
rollupOptions: {
input: {
main: 'index.html',
admin: 'admin.html',
dashboard: 'dashboard.html'
}
}
}
});
```
Каждый ключ объекта `input` становится именем выходного чанка.
---
## Поведение dev-сервера
Dev-сервер Vite не требует дополнительной настройки для работы с несколькими HTML-файлами. Он обслуживает каждый файл как отдельную страницу:
* `/index.html`
* `/admin.html`
* `/dashboard.html`
При этом сохраняется поддержка HMR в каждом модуле независимо.
Особенность заключается в том, что маршрутизация не объединяется автоматически. Нет единого роутера, как в SPA, если он не реализован вручную.
---
## Формирование выходной структуры сборки
После выполнения `vite build` структура `dist` становится многостраничной:
```
dist/
index.html
admin.html
dashboard.html
assets/
main-[hash].js
admin-[hash].js
dashboard-[hash].js
```
Rollup анализирует зависимости каждой точки входа и оптимизирует общие модули, выделяя shared chunks.
---
## Разделение общих зависимостей
При наличии пересечений между входами Vite автоматически выносит общие зависимости в отдельные чанки.
Пример:
```js
// src/utils/api.js
export function request() {}
```
Если `main.js` и `admin.js` используют `api.js`, он попадёт в общий бандл:
```
assets/
vendor-[hash].js
```
Это снижает общий размер загрузки при переходах между страницами.
---
## Управление shared chunks через manualChunks
Для более точного контроля используется `manualChunks`:
```js
export default defineConfig({
build: {
rollupOptions: {
input: {
main: 'index.html',
admin: 'admin.html'
},
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor';
}
if (id.includes('src/utils')) {
return 'common';
}
}
}
}
}
});
```
Такое разделение полезно при необходимости стабилизировать кеширование или изолировать большие библиотеки.
---
## Динамические точки входа
В некоторых архитектурах входные страницы генерируются автоматически. В этом случае используется динамическая сборка списка входов:
```js
import { resolve } from 'path';
import { readdirSync } from 'fs';
function getInputs() {
const pages = readdirSync('pages');
return pages.reduce((acc, file) => {
const name = file.replace('.html', '');
acc[name] = resolve(__dirname, 'pages', file);
return acc;
}, {});
}
export default defineConfig({
build: {
rollupOptions: {
input: getInputs()
}
}
});
```
Такой подход применяется в больших корпоративных приложениях, где страницы создаются по шаблонам.
---
## Разделение SPA и MPA внутри одного проекта
Vite позволяет комбинировать подходы:
* часть приложения работает как SPA
* часть как независимые HTML-страницы
Пример структуры:
```
index.html → SPA
admin.html → отдельный интерфейс
landing.html → статическая страница
```
SPA может использовать `createRouter`, тогда как остальные страницы остаются изолированными.
---
## Роутинг и навигация между точками входа
При множественных HTML-страницах навигация реализуется стандартными ссылками:
```html
Админка
Дашборд
```
При этом переход между страницами приводит к полной перезагрузке контекста, что принципиально отличается от SPA-роутинга.
---
## Переиспользование модулей между входами
Общая логика выносится в отдельные модули:
```
src/
shared/
api.js
auth.js
```
Использование:
```js
import { login } from './shared/auth.js';
```
Vite анализирует граф зависимостей и автоматически объединяет код, если это оптимально.
---
## Кеширование и стабильность бандлов
Множественные входы усложняют стратегию кеширования. Vite решает это через:
* хеширование файлов
* разделение vendor chunks
* стабильное имя entry chunk
Пример результата:
```
admin-[hash].js
main-[hash].js
vendor-[hash].js
```
Изменение одной страницы не инвалидирует остальные чанки при корректном разделении зависимостей.
---
## Особенности работы с HTML как точкой входа
Vite рассматривает HTML как полноценный модуль:
* поддерживает `
`
* обрабатывает алиасы
* разрешает импорт ассетов
Это позволяет использовать HTML как первичный входной слой без дополнительной обвязки.
---
## Типичные ошибки при настройке нескольких входов
### Отсутствие явного указания input
Если `rollupOptions.input` не задан, сборка создаст только один HTML-бандл.
### Конфликт путей
При неправильной структуре возможно дублирование или потеря HTML-файлов в `dist`.
### Неправильные абсолютные пути
Использование `/src/...` без учёта base path может приводить к ошибкам в продакшене.
---
## Использование base path при multi-entry
При деплое в подпапку важно учитывать `base`:
```js
export default defineConfig({
base: '/app/',
build: {
rollupOptions: {
input: {
main: 'index.html',
admin: 'admin.html'
}
}
}
});
```
Без этого ресурсы могут загружаться по неверным путям.
---
## Взаимодействие с плагинами Vite
Многие плагины корректно работают с multi-entry, но требуют проверки:
* плагин может ожидать единственный HTML
* SSR-плагины могут требовать отдельной настройки
* плагины оптимизации изображений обрабатывают все входы одинаково
Особое внимание требуется при использовании плагинов, модифицирующих HTML.
---
## Масштабирование архитектуры с множественными входами
При росте проекта multi-entry структура часто становится промежуточным этапом перед:
* микрофронтендами
* модульными монорепозиториями
* разделением по доменным областям
Vite в этом контексте выступает как слой сборки, не ограничивающий архитектурные решения, но требующий явного контроля входных точек и зависимостей.