Общие плагины и конфигурации

## Конфигурационный слой Vite и его роль в сборке Vite строится вокруг строго определённой конфигурационной модели, в которой ключевым элементом выступает файл конфигурации `vite.config.js` (или `vite.config.ts`). Этот файл формирует поведение dev-сервера, системы сборки, трансформаций модулей и интеграции плагинов. Основной механизм настройки основан на функции `defineConfig`, которая позволяет явно типизировать конфигурацию и обеспечивает корректную подсказку параметров среды исполнения. Ключевая особенность конфигурации Vite заключается в том, что она выполняется в Node.js среде, а не в браузере, и может быть динамической. Это позволяет использовать условия, переменные окружения и асинхронные операции. ### Структура базовой конфигурации Конфигурационный объект Vite содержит несколько основных зон ответственности: * параметры dev-сервера (`server`) * настройки сборки (`build`) * определение алиасов и резолва модулей (`resolve`) * подключение плагинов (`plugins`) * работа с переменными окружения (`env`) * оптимизация зависимостей (`optimizeDeps`) Каждая из этих секций влияет на отдельный этап жизненного цикла приложения: от запуска dev-сервера до финальной сборки через Rollup. ### Динамическая конфигурация Конфигурация может быть функцией, возвращающей объект: ```javascript export default defineConfig(({ mode, command }) => { return { server: { port: 3000 } } }) ``` Параметры `mode` и `command` позволяют разделять поведение между разработкой и production-сборкой, а также между dev-сервером и build-процессом. Такой подход делает возможной адаптацию конфигурации под окружение без необходимости разделять файлы. ## Система плагинов Vite Плагины являются центральным механизмом расширения функциональности Vite. Архитектура плагинов основана на совместимости с Rollup, но расширена дополнительными хуками, специфичными для dev-сервера. Плагин представляет собой объект с набором функций-хуков, которые вызываются на разных этапах обработки модулей. ### Базовая структура плагина ```javascript export default function myPlugin(options = {}) { return { name: 'my-plugin', transform(code, id) { return code } } } ``` Минимальный плагин содержит поле `name`, которое используется для идентификации в цепочке обработки. ## Жизненный цикл плагинов Vite использует несколько уровней хуков, разделённых по этапам: ### Хуки инициализации * `config` * `configResolved` * `options` Хук `config` позволяет модифицировать исходную конфигурацию до её финализации. Это один из ключевых механизмов расширения поведения Vite. ```javascript config(config, env) { return { server: { port: 4000 } } } ``` `configResolved` вызывается после полного разрешения конфигурации и используется для чтения итоговых значений без возможности их изменения. ## Обработка модулей Основная логика Vite строится вокруг трансформации ES-модулей. ### transform Хук `transform` является одним из наиболее часто используемых: ```javascript transform(code, id) { if (id.endsWith('.js')) { return { code: code.replace(/console\.log/g, ''), map: null } } } ``` Он позволяет модифицировать содержимое файлов перед их передачей в браузер или сборку. ### load Хук `load` используется для подмены содержимого модуля: ```javascript load(id) { if (id === '/virtual-module') { return 'export const value = 42' } } ``` Этот механизм активно применяется для виртуальных модулей. ### resolveId Позволяет перехватывать процесс разрешения импортов: ```javascript resolveId(source) { if (source === 'virtual') { return source } } ``` Это основа для создания псевдо-пакетов и динамических импортов. ## Виртуальные модули Виртуальные модули — ключевой паттерн расширения Vite. Они не существуют в файловой системе, но ведут себя как обычные ES-модули. Комбинация `resolveId` и `load` позволяет реализовать их полностью: ```javascript const VIRTUAL = 'virtual:time' export default function timePlugin() { return { name: 'time-plugin', resolveId(id) { if (id === VIRTUAL) return VIRTUAL }, load(id) { if (id === VIRTUAL) { return `export const now = Date.now()` } } } } ``` Такая схема широко используется в официальных и сторонних плагинах. ## Совместимость с Rollup Vite использует Rollup для production-сборки, поэтому значительная часть плагиновой системы наследуется напрямую. Это означает: * Rollup-хуки поддерживаются без изменений * порядок выполнения плагинов аналогичен Rollup * tree-shaking и chunking управляются через Rollup API Однако Vite добавляет собственные хуки, связанные с dev-сервером, HMR и оптимизацией зависимостей. ## HMR-хуки Hot Module Replacement реализован через отдельный набор хуков: * `handleHotUpdate` * `hotUpdate` Пример: ```javascript handleHotUpdate(ctx) { console.log('Обновился файл:', ctx.file) return ctx.modules } ``` Эти хуки позволяют контролировать поведение обновлений без полной перезагрузки страницы. ## Конфигурация плагинов в vite.config Подключение плагинов осуществляется через массив: ```javascript import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [ react() ] }) ``` Порядок имеет значение: плагины выполняются последовательно, и каждый может влиять на результат предыдущего. ## Фабричные плагины Многие плагины реализуются как функции-фабрики, принимающие параметры: ```javascript function myPlugin(options) { return { name: 'my-plugin', transform(code) { return code } } } ``` Такой подход позволяет создавать конфигурационные вариации без дублирования логики. ## Управление порядком выполнения Порядок выполнения плагинов критичен для корректной работы трансформаций. Существуют механизмы: * явный порядок в массиве `plugins` * использование `enforce: 'pre' | 'post'` * разделение на build и dev плагины ```javascript { name: 'plugin-a', enforce: 'pre' } ``` `pre` выполняется до основных плагинов, `post` — после них. ## Конфигурация resolve и alias Секция `resolve` определяет поведение импорта: ```javascript resolve: { alias: { '@': '/src' } } ``` Это влияет на резолв модулей до стадии плагинов, поэтому часто используется совместно с ними. ## Оптимизация зависимостей Vite выполняет предварительное бандлирование через esbuild: ```javascript optimizeDeps: { include: ['lodash'], exclude: ['some-large-lib'] } ``` Плагины могут вмешиваться в этот процесс, изменяя поведение импорта и ускоряя cold start dev-сервера. ## Интеграция плагинов с сервером разработки Некоторые плагины взаимодействуют напрямую с dev-сервером через `configureServer`: ```javascript configureServer(server) { server.middlewares.use((req, res, next) => { next() }) } ``` Это позволяет внедрять middleware, API-роутинг и нестандартную логику обработки запросов. ## Условные плагины и окружения Плагины часто включаются выборочно в зависимости от режима: ```javascript export default defineConfig(({ mode }) => ({ plugins: [ mode === 'development' && devPlugin(), mode === 'production' && prodPlugin() ].filter(Boolean) })) ``` Такой подход позволяет разделять поведение без дублирования конфигурации. ## Расширенные возможности конфигурации Vite поддерживает асинхронные конфигурации: ```javascript export default defineConfig(async () => { const data = await fetchConfig() return { server: { port: data.port } } }) ``` Это делает возможной интеграцию с внешними сервисами конфигурации, CI/CD системами и динамическими окружениями. ## Плагины как слой архитектуры приложения В архитектурной модели Vite плагины выполняют роль промежуточного слоя между исходным кодом и конечным бандлом. Они отвечают за: * трансформацию синтаксиса * внедрение виртуальных модулей * генерацию кода на лету * интеграцию фреймворков * оптимизацию загрузки ресурсов Такое разделение делает систему расширяемой без изменения ядра сборщика. ## Глубокая интеграция с экосистемой Плагины Vite часто становятся основой фреймворков: * React интеграция через JSX трансформации * Vue через SFC компиляцию * Svelte через препроцессинг Каждый из этих случаев использует один и тот же набор хуков, но с разной логикой обработки кода. ## Конфигурация как точка расширения всей системы Файл конфигурации Vite выступает центральной точкой управления всей системой сборки. Через него происходит: * подключение плагинов * настройка dev-сервера * управление сборкой * контроль оптимизации * расширение поведения через хуки Архитектура построена так, что практически любое изменение поведения системы достигается через плагины и конфигурацию без модификации ядра.