How to Use Vite Env Files to Load Environment Variables

Vite automatically loads environment variables from .env files in your project root and exposes only prefixed variables to client code via import.meta.env, with the core logic implemented in src/node/env.ts and integrated during config resolution in src/node/config.ts.

Vite provides a built-in mechanism for loading environment variables from .env files without requiring additional plugins. According to the vitejs/vite source code, the framework automatically discovers and parses these files using the loadEnv function when the dev server starts or a production build begins.

How Vite Loads Environment Variables

The environment variable resolution logic lives in [src/node/env.ts](https://github.com/vitejs/vite/blob/main/packages/vite/src/node/env.ts). This module exports the loadEnv function, which Vite calls internally during configuration resolution in [src/node/config.ts](https://github.com/vitejs/vite/blob/main/packages/vite/src/node/config.ts) using the line:

const userEnv = loadEnv(mode, envDir, resolveEnvPrefix(config))

The loadEnv function searches for files matching the pattern .env[.<mode>] in your project directory, parses them with the dotenv library, and filters variables based on the configured prefix. The public API is also exposed from [src/node/index.ts](https://github.com/vitejs/vite/blob/main/packages/vite/src/node/index.ts), allowing you to import loadEnv and resolveEnvPrefix directly in custom scripts or plugins.

Environment File Naming and Loading Order

Vite follows a specific naming convention and loading priority for environment files. Files are loaded in the following order, with later files overwriting earlier ones:

  1. .env (loaded in all modes)
  2. .env.<mode> (e.g., .env.development or .env.production)
  3. .env.<mode>.local (e.g., .env.development.local)
  4. .env.local (loaded in all modes, but ignored by git by default)

The .env file is always loaded first, making it ideal for default values shared across environments. Mode-specific files allow you to override values for development, production, or custom modes you define.

Configuring the Vite Env Prefix

By default, Vite exposes only environment variables that begin with VITE_ to client-side code. This prevents accidental exposure of sensitive credentials to the browser bundle.

Using the Default VITE_ Prefix

Create a .env file in your project root:

VITE_API_URL=https://api.example.com
VITE_FEATURE_FLAG=true

Access these values in your application code using import.meta.env:

// src/main.ts
console.log(import.meta.env.VITE_API_URL) // "https://api.example.com"
console.log(import.meta.env.VITE_FEATURE_FLAG) // "true"

Customizing the Env Prefix

To use a different prefix, modify the envPrefix option in vite.config.ts:

// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  envPrefix: 'APP_'
})

Now variables starting with APP_ will be available in your client code:


# .env

APP_CLIENT_ID=abc123
// src/main.ts
console.log(import.meta.env.APP_CLIENT_ID) // "abc123"

Customizing the Environment Directory

By default, Vite looks for .env files in the project root. To load them from a different location, use the envDir configuration option:

// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  envDir: './config'  // Vite will look for .env files in the config/ directory
})

Place your .env files inside the specified directory (e.g., config/.env), and Vite will load them during startup.

Accessing Environment Variables in Server-Side Code

While client code uses import.meta.env, server-side code such as vite.config.ts or custom plugins can access raw environment variables by calling loadEnv directly:

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => {
  // Load all env variables (no prefix filtering)
  const env = loadEnv(mode, process.cwd())
  
  return {
    define: {
      __APP_VERSION__: JSON.stringify(env.npm_package_version)
    }
  }
})

This pattern is useful when you need to access variables that don't match your client-side prefix or when configuring plugins based on environment values.

Type Safety for Vite Env Variables

Vite ships with TypeScript definitions for import.meta.env that include the default VITE_ variables. To add type definitions for custom variables, create or modify vite-env.d.ts:

/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_CUSTOM_KEY: string
  // Add more env variables as needed
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

Summary

  • Vite automatically loads .env files using the loadEnv function implemented in src/node/env.ts and called during config resolution in src/node/config.ts.
  • Files load in priority order: .env → .env.<mode> → .env.<mode>.local → .env.local.
  • Only variables matching the envPrefix (default VITE_) are exposed to client code via import.meta.env.
  • Use the envDir option to specify a custom directory for environment files.
  • Import loadEnv from vite to access raw variables in vite.config.ts or plugins.

Frequently Asked Questions

What is the default env prefix in Vite?

The default prefix is VITE_. Only environment variables starting with this string are exposed to client-side code through import.meta.env. You can change this behavior using the envPrefix configuration option in vite.config.ts.

How do I load env variables in vite.config.ts?

Import the loadEnv function from the vite package and call it with the current mode and directory. According to the source code in src/node/index.ts, loadEnv returns an object containing all parsed environment variables, allowing you to access them during configuration.

Can I use .env files outside the project root?

Yes. Set the envDir option in your vite.config.ts to point to any directory relative to your project root. Vite will search for .env files in that location instead of the default project root.

Why are my environment variables undefined in the browser?

Ensure your variable names start with the correct prefix (default VITE_). Variables without this prefix are filtered out by the resolveEnvPrefix logic in src/node/config.ts and will not be available in import.meta.env. Also verify that your .env file is located in the correct directory (project root or your specified envDir).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →