Общие плагины и конфигурации
## Конфигурационный слой 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-сервера
* управление сборкой
* контроль оптимизации
* расширение поведения через хуки
Архитектура построена так, что практически любое изменение поведения системы достигается через плагины и конфигурацию без модификации ядра.