Skip to content

Vite Environment Variables in vite.config.js

Problem

When configuring a Vite project, developers often need to access environment variables within the vite.config.js file. However, Vite's built-in environment variable handling only exposes VITE_ prefixed variables to client-side code by default, not to the configuration file itself.

A common use case is configuring the development server port based on an environment variable:

env
VITE_NAME=Wheatgrass
VITE_PORT=8080

Solution

Vite provides the loadEnv() function specifically for accessing environment variables in configuration files. This is the recommended approach as it's built into Vite and follows its conventions.

Basic Usage with loadEnv()

javascript
import { defineConfig, loadEnv } from 'vite';

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '');
  
  return {
    server: {
      port: parseInt(env.VITE_PORT) || 3000
    }
  };
});

Configuration Details

The loadEnv() function has the following signature:

javascript
function loadEnv(
  mode: string,
  envDir: string,
  prefixes: string | string[] = 'VITE_'
): Record<string, string>
  • mode: The current mode (e.g., 'development', 'production')
  • envDir: Directory containing your .env files (typically process.cwd())
  • prefixes: Which variable prefixes to load (empty string '' loads all)

Complete Example with Multiple Variables

javascript
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd());
  
  const API_URL = env.VITE_API_URL ?? 'http://localhost:3000';
  const PORT = parseInt(env.VITE_PORT ?? '3000');

  return {
    plugins: [react()],
    server: {
      port: PORT,
      proxy: {
        '/api': API_URL,
      },
    },
    build: {
      outDir: 'dist',
    },
  };
});

Environment Variable Security

Never expose sensitive variables with the VITE_ prefix in client-side code. Use server-side environment variables (without the prefix) for secrets, and only use VITE_ prefixed variables for non-sensitive configuration.

Alternative Approaches

While you can use the dotenv package, this approach is generally not recommended as it bypasses Vite's built-in environment handling:

javascript
import { defineConfig } from 'vite';
import dotenv from 'dotenv';
import react from '@vitejs/plugin-react';

dotenv.config(); // Loads from .env file

export default defineConfig({
  base: process.env.VITE_HOMEPAGE_URL,
  plugins: [react()],
});

Avoid dotenv for Vite Configuration

Using dotenv directly can lead to inconsistencies between build-time and runtime environment variables. Prefer Vite's loadEnv() for better integration with Vite's ecosystem.

Advanced: Custom Environment File Handling

For complex scenarios with multiple environment files:

javascript
import { defineConfig } from 'vite';
import { sveltekit } from '@sveltejs/kit/vite';
import dotenv from 'dotenv';
import fs from 'fs';

export default defineConfig(() => {
  // Load environment based on NODE_ENV
  const envFile = process.env.NODE_ENV === 'production' 
    ? '.env.production' 
    : '.env.development';
  
  const envConfig = dotenv.parse(fs.readFileSync(envFile));
  process.env = { ...process.env, ...envConfig };

  return {
    plugins: [sveltekit()],
  };
});

Common Issues and Solutions

ESLint Errors

If you encounter process is not defined errors in ESLint, update your .eslintrc.cjs:

javascript
module.exports = {
  env: { 
    browser: true, 
    es2020: true, 
    node: true // Add this line
  },
  // Other settings...
};

TypeScript Configuration

For TypeScript projects, ensure your types are correctly defined by creating a env.d.ts file:

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

interface ImportMetaEnv {
  readonly VITE_PORT: string;
  readonly VITE_API_URL: string;
  // more env variables...
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

Best Practices

  1. Use Vite's loadEnv() instead of external dotenv packages
  2. Set fallback values for all environment variables
  3. Type conversion: Remember that environment variables are always strings
  4. Differentiate between server and client variables: Use non-prefixed variables for server-only configuration
  5. Environment-specific files: Use .env.development, .env.production, etc., for mode-specific settings

By following these practices, you'll ensure your Vite configuration properly accesses environment variables while maintaining consistency with Vite's ecosystem and best practices.