How to Set Up Vite + Environment Variables in React 18

Learn how to properly configure environment variables in a Vite + React 18 app with best practices for dev, staging, and production environments.

If you're working with React 18 and Vite, configuring environment variables correctly is essential for separating secrets, toggling feature flags, or managing endpoints across environments. Luckily, Vite offers an ergonomic and type-safe approach.

Why use environment variables?

You don’t want to hardcode API keys or base URLs into your app. Environment variables let you inject values at build time safely and flexibly.

#Prerequisites

  • A React 18 project using Vite (v4+ recommended).
  • Basic familiarity with .env files.

#Vite Environment Variable Conventions

Vite loads environment variables from .env files based on your current mode. It automatically replaces import.meta.env variables during build time.

Vite recognizes the following files by default:

.env
.env.local
.env.development
.env.production
.env.[mode].local

Only variables prefixed with VITE_ will be exposed to your frontend code.

Info

This is a security feature. Vite will ignore any variable not prefixed with VITE_ to prevent accidental exposure of sensitive keys.

#Example .env File Setup

Here’s a basic .env setup you can use for development:

.env
VITE_API_BASE_URL=https://api.dev.myapp.com
VITE_FEATURE_CHAT=true

You can override these in .env.production for production builds:

.env.production
VITE_API_BASE_URL=https://api.myapp.com
VITE_FEATURE_CHAT=false

#Accessing Variables in Your Code

You can access the values using import.meta.env:

src/config.ts
export const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
export const FEATURE_CHAT_ENABLED = import.meta.env.VITE_FEATURE_CHAT === "true";
Tip

Vite replaces import.meta.env.* with their actual values at build time — there's no runtime process.env like in Create React App.

#Vite Config File: Custom Modes & Define

You can also pass custom defines or switch modes in vite.config.ts:

vite.config.ts
import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), "");

  return {
    plugins: [react()],
    define: {
      __APP_VERSION__: JSON.stringify(env.npm_package_version),
    },
  };
});
Info

You can use loadEnv() to read values in vite.config.ts, including ones without VITE_ prefix, since this file runs in Node.

#Custom Modes for Staging

You can add a staging mode easily:

vite build --mode staging

Add a .env.staging file with staging-specific values:

.env.staging
VITE_API_BASE_URL=https://api.staging.myapp.com

#Tips for Deployment

  • Never check .env.local into version control.
  • Use a .env.example file to document required variables.
  • In hosting platforms (like Vercel or Netlify), set your VITE_ vars in the UI or CLI.
Using runtime envs?

Vite builds the environment into your JavaScript bundle. If you want to support runtime configuration (e.g., via window globals or external config JSON), you'll need a custom solution.

#Final Thoughts

Vite’s environment variable system is simple but powerful. Prefix your variables correctly, use different .env.[mode] files for different environments, and leverage import.meta.env directly in your code.

For more advanced configuration patterns, see Vite’s official docs.