Механизм environments в Vite представляет собой слой конфигурации, который позволяет разделять и изолировать разные среды выполнения приложения внутри одного проекта. В отличие от классической модели, где конфигурация часто ограничивается двумя режимами — development и production, подход Vite строится вокруг расширяемых окружений, которые могут включать произвольные цели сборки, runtime-контексты и сценарии исполнения.
Environments в Vite — это именованные контексты, в рамках которых определяются:
Каждое окружение можно рассматривать как независимую конфигурационную единицу, которая наследует базовые настройки проекта, но при этом может их переопределять.
Основная идея заключается в том, чтобы уйти от жесткой дихотомии
dev/prod и перейти к модели:
base environment → derived environments → runtime-specific overrides
Внутренне Vite рассматривает environment как объект конфигурации, который создается на этапе инициализации сервера или сборщика.
Ключевые компоненты:
mode — строковый идентификатор режимаcommand — serve или
buildisSsrBuild — флаг SSR-сборкиconfigEnv — объект, содержащий переменные
окруженияroot — корневая директория проектаВ расширенной модели environments добавляются дополнительные сущности:
envName — имя среды (например, client,
server, edge)define — инлайнинг глобальных переменныхresolve — правила резолвинга модулейbuild — параметры сборки под конкретную средуКонфигурация Vite обычно экспортируется через
defineConfig, но в контексте environments она может
возвращать динамическую структуру, зависящую от текущего окружения.
import { defineConfig } from 'vite'
export default defineConfig(({ command, mode, isSsrBuild }) => {
return {
build: {
sourcemap: mode === 'development'
}
}
})
В расширенном подходе environments логика становится более детализированной:
export default defineConfig(({ command, mode }) => {
const isClient = mode === 'client'
const isServer = mode === 'server'
return {
build: {
target: isClient ? 'es2020' : 'node18'
}
}
})
Vite позволяет формировать кастомные среды через расширение конфигурации и разделение точек входа.
Типичная структура:
vite.config.js
env/
client.env.js
server.env.js
edge.env.js
Каждый файл описывает свою часть конфигурации:
// env/client.env.js
export default {
build: {
outDir: 'dist/client',
target: 'esnext'
}
}
// env/server.env.js
export default {
build: {
outDir: 'dist/server',
target: 'node18'
}
}
Далее происходит композиция:
import clientEnv from './env/client.env'
import serverEnv from './env/server.env'
export default defineConfig(({ mode }) => {
if (mode === 'client') {
return clientEnv
}
if (mode === 'server') {
return serverEnv
}
return {}
})
Vite использует систему import.meta.env, которая тесно
связана с текущим environment.
Основные принципы:
.env,
.env.[mode]loadEnvimport { loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '')
return {
define: {
__API_URL__: JSON.stringify(env.API_URL)
}
}
})
В рамках environments важно разделять:
VITE_ prefix)Одним из ключевых сценариев использования environments является разделение клиентской и серверной сборки.
SSR в Vite подразумевает два независимых графа модулей:
Конфигурация environments позволяет явно разделить их:
export default defineConfig(({ ssrBuild }) => {
return {
build: {
ssr: ssrBuild ? true : false,
rollupOptions: {
input: ssrBuild ? 'src/entry-server.js' : 'src/entry-client.js'
}
}
}
})
SSR environment обычно отличается:
ssr.externalСовременные архитектуры часто включают edge runtime (Cloudflare Workers, Vercel Edge, Deno Deploy). Vite environments позволяют выделять такие контексты отдельно.
export default defineConfig(({ mode }) => {
if (mode === 'edge') {
return {
build: {
target: 'es2022',
minify: true
},
ssr: {
target: 'webworker'
}
}
}
})
Особенности edge environments:
Одним из ключевых аспектов является управление
ssr.external и ssr.noExternal, которые
становятся критичными при разделении environments.
export default defineConfig({
ssr: {
external: ['express', 'fastify'],
noExternal: ['my-shared-lib']
}
})
В multi-environment подходе это может различаться:
Environments позволяют логически разделять pipeline сборки:
Пример различий:
// client
build: {
cssCodeSplit: true,
sourcemap: true
}
// server
build: {
cssCodeSplit: false,
sourcemap: false
}
Vite плагины могут адаптироваться под текущую среду через контекст конфигурации.
export function myPlugin() {
return {
name: 'my-plugin',
config(config, { command, mode }) {
if (mode === 'server') {
config.resolve.alias = {
...config.resolve.alias,
'@runtime': '/src/runtime/server'
}
}
}
}
}
Плагин становится частью environment-aware системы, где поведение изменяется в зависимости от цели сборки.
В сложных приложениях встречается гибридная модель:
Каждое окружение имеет:
Пример конфигурации:
export default defineConfig(({ mode }) => {
const configs = {
client: {
build: { outDir: 'dist/client' }
},
server: {
build: { outDir: 'dist/server', ssr: true }
},
worker: {
build: { outDir: 'dist/worker', target: 'es2022' }
}
}
return configs[mode] || {}
})
Разделение environments напрямую влияет на:
Разные environments позволяют уменьшить пересечение зависимостей и избежать лишнего кода в итоговом бандле.
Особенно это заметно при:
Частые проблемы при работе с environments:
ssr.noExternalТипичный анти-паттерн:
export default defineConfig({
build: {
ssr: true,
target: 'esnext'
}
})
Без разделения environments это приводит к некорректному бандлу и runtime-ошибкам.
Наиболее устойчивый подход включает:
ssr.externalТакая модель делает Vite-конфигурацию предсказуемой и масштабируемой при росте архитектуры приложения.