Префикс VITE_ и доступ через import.meta.env

Механизм переменных окружения в Vite

Vite использует собственную модель работы с переменными окружения, основанную на import.meta.env. В отличие от традиционных сборщиков, где переменные окружения часто подменяются через process.env, здесь применяется нативная для ESM-концепция, обеспечивающая статическую подстановку значений на этапе сборки.

Ключевая особенность заключается в том, что переменные становятся частью клиентского бандла только в момент компиляции, а не во время выполнения в браузере.


Префикс VITE_ как механизм экспорта переменных

Любая переменная окружения, которая должна быть доступна в клиентском коде, обязана иметь префикс VITE_.

Пример:

VITE_API_URL=https://api.example.com
VITE_APP_NAME=MyApp

Без этого префикса переменные игнорируются системой сборки и не попадают в import.meta.env.

Такое ограничение введено для защиты от случайной утечки секретов в браузерный код.


Разделение переменных: клиентские и приватные

Система переменных окружения разделяется на два уровня:

  1. Переменные с префиксом VITE_ Доступны в клиентском коде через import.meta.env.

  2. Все остальные переменные Доступны только в Node.js-окружении (конфигурация, плагины, сервер разработки).

Пример:

VITE_PUBLIC_KEY=abc123
SECRET_KEY=super-secret

В клиентском коде:

console.log(import.meta.env.VITE_PUBLIC_KEY) // доступно
console.log(import.meta.env.SECRET_KEY) // undefined

import.meta.env как объект конфигурации

import.meta.env представляет собой статический объект, формируемый во время сборки. Он содержит как пользовательские переменные, так и встроенные системные значения.

Основные встроенные поля:

  • import.meta.env.MODE — текущий режим (development, production, кастомные режимы)
  • import.meta.env.DEV — булево значение, указывающее режим разработки
  • import.meta.env.PROD — булево значение, указывающее production-сборку
  • import.meta.env.BASE_URL — базовый публичный путь приложения
  • import.meta.env.SSR — флаг серверного рендеринга

Пример использования:

if (import.meta.env.DEV) {
  console.log('Режим разработки')
}

fetch(`${import.meta.env.VITE_API_URL}/users`)

Статическая подстановка значений

Одним из ключевых принципов работы является compile-time replacement. Значения переменных подставляются прямо в код во время сборки.

Исходный код:

const api = import.meta.env.VITE_API_URL

После сборки:

const api = "https://api.example.com"

Это означает отсутствие динамического чтения переменных в runtime, что повышает производительность и позволяет выполнять агрессивные оптимизации.


Файлы окружения и приоритет загрузки

Vite поддерживает несколько .env файлов, которые загружаются в строгом порядке приоритетов:

  • .env — базовые значения
  • .env.local — локальные переопределения (игнорируются в git)
  • .env.[mode] — режим-специфичные значения
  • .env.[mode].local — локальные значения для конкретного режима

Пример структуры:

.env
.env.development
.env.production
.env.local
.env.production.local

Приоритет более специфичных файлов выше общего .env.


Режимы работы и привязка к переменным

Режим определяется через параметр --mode:

vite --mode staging

В этом случае будут загружены:

  • .env
  • .env.staging
  • .env.staging.local

Значение import.meta.env.MODE будет равно staging.


Использование в JavaScript и TypeScript

Доступ к переменным осуществляется напрямую:

const baseUrl = import.meta.env.VITE_API_URL

В TypeScript требуется расширение интерфейса ImportMetaEnv, иначе типизация будет ограниченной:

interface ImportMetaEnv {
  readonly VITE_API_URL: string
  readonly VITE_APP_NAME: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

Это позволяет получить строгую типизацию и автодополнение в IDE.


Ограничения и безопасность

Механизм VITE_ не является системой защиты секретов. Это лишь фильтрация на этапе сборки.

Любая переменная с префиксом VITE_:

  • попадает в финальный JavaScript-бандл
  • может быть прочитана пользователем через DevTools
  • не должна содержать секреты (API keys с правами записи, пароли, токены администратора)

Пример неправильного использования:

VITE_ADMIN_PASSWORD=123456

Такие данные считаются публичными после сборки.


Различие между import.meta.env и process.env

В Vite process.env не является основным механизмом доступа к окружению. Он может присутствовать только в совместимости или через плагины.

Основной стандарт:

import.meta.env.VITE_API_URL

Проблемы использования process.env:

  • отсутствует нативная поддержка в браузере
  • требует полифиллов или трансформаций
  • хуже оптимизируется сборщиком

Поведение в SSR и Node окружении

При серверном рендеринге import.meta.env доступен и на сервере, но его поведение отличается:

  • переменные доступны во время выполнения Node.js
  • отсутствует клиентская подстановка
  • возможны дополнительные серверные переменные без VITE_

Пример:

if (import.meta.env.SSR) {
  console.log('Серверный рендеринг')
}

Встроенные переменные и их роль

Системные переменные играют роль контекста сборки:

MODE

Определяет режим работы:

import.meta.env.MODE

DEV / PROD

import.meta.env.DEV
import.meta.env.PROD

Используются для условной логики:

if (import.meta.env.PROD) {
  enableAnalytics()
}

BASE_URL

import.meta.env.BASE_URL

Используется для корректной работы приложения при размещении не в корне домена.


Практика композиции конфигурации

Обычно конфигурация строится через комбинацию режимов и .env файлов:

.env
VITE_API_URL=http://localhost:3000

.env.production
VITE_API_URL=https://api.prod.com

Код остаётся неизменным:

const api = import.meta.env.VITE_API_URL

Поведение меняется только за счёт режима сборки.


Поведение при изменении переменных

Изменение .env файлов требует перезапуска dev-сервера. Это связано с тем, что переменные читаются на этапе старта процесса и кешируются.


Подстановка в HTML и конфигурации

Переменные import.meta.env могут использоваться не только в JS, но и в HTML через специальные механизмы Vite, включая шаблонизацию и плагины.

Пример в index.html:

<script>
  window.apiBase = "%VITE_API_URL%"
</script>

Особенности работы с JSON и структурами

Все переменные окружения приходят как строки. Даже если значение выглядит как число или булево, оно требует явного преобразования:

const debug = import.meta.env.VITE_DEBUG === 'true'
const port = Number(import.meta.env.VITE_PORT)

Поведение в сборке и tree-shaking

Так как значения подставляются на этапе компиляции, возможен dead code elimination:

if (import.meta.env.DEV) {
  console.log('debug')
}

В production этот блок полностью удаляется из финального бандла.


Влияние на архитектуру приложения

Использование VITE_ и import.meta.env приводит к следующей архитектурной модели:

  • конфигурация отделена от кода
  • окружение определяет поведение приложения
  • секреты вынесены за пределы фронтенда
  • сборка становится детерминированной

Такой подход упрощает мультиокружения (dev, staging, production) без изменения исходного кода.