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:
VITE_NAME=Wheatgrass
VITE_PORT=8080Solution
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()
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:
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
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
Using dotenv (Not Recommended)
While you can use the dotenv package, this approach is generally not recommended as it bypasses Vite's built-in environment handling:
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:
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:
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:
/// <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
- Use Vite's
loadEnv()instead of external dotenv packages - Set fallback values for all environment variables
- Type conversion: Remember that environment variables are always strings
- Differentiate between server and client variables: Use non-prefixed variables for server-only configuration
- 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.