Работа с несколькими точками входа

## Множественные точки входа в 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 в этом контексте выступает как слой сборки, не ограничивающий архитектурные решения, но требующий явного контроля входных точек и зависимостей.