Tutorial: Manejo de Variables de Entorno en Vite
Cuando un proyecto comienza a crecer, tarde o temprano aparece el mismo problema: hay valores que cambian dependiendo del entorno donde se ejecuta la aplicación. Durante el desarrollo probablemente consumas una API local, mientras que en producción utilizarás otra URL completamente distinta.
Copiar y pegar esas direcciones cada vez que haces un despliegue funciona... hasta que alguien olvida hacerlo y termina publicando una versión que sigue apuntando al servidor de pruebas.
Las variables de entorno existen precisamente para evitar ese tipo de situaciones. Vite incorpora un sistema bastante sencillo para administrarlas y, una vez que entiendes cómo funciona, prácticamente no vuelves a modificar configuraciones directamente en el código.
Crear el primer archivo .env
En la raíz del proyecto crea un archivo llamado:
.env
Dentro puedes definir todas las variables que necesite tu aplicación.
VITE_APP_NAME=Mi Aplicación
VITE_API_URL=https://jsonplaceholder.typicode.com
VITE_APP_VERSION=1.0.0
Una característica de Vite es que únicamente expone al navegador las variables que comienzan con VITE_.
Por ejemplo, esta variable estará disponible desde el frontend:
VITE_API_URL=https://api.midominio.com
Mientras que esta otra no:
API_URL=https://api.midominio.com
Al intentar acceder desde JavaScript obtendrás:
console.log(import.meta.env.API_URL)
undefined
Este comportamiento evita que información privada termine expuesta accidentalmente en el navegador.
Acceder a las variables desde la aplicación
En Vite todas las variables se leen mediante import.meta.env.
Por ejemplo:
function App() {
return (
<>
<h1>{import.meta.env.VITE_APP_NAME}</h1>
<p>Versión {import.meta.env.VITE_APP_VERSION}</p>
<p>{import.meta.env.VITE_API_URL}</p>
</>
)
}
export default App
A diferencia de proyectos creados con Create React App, aquí no se utiliza process.env.
Si vienes de Webpack es un cambio pequeño, pero bastante común olvidar el nuevo formato durante los primeros días.
Consumir una API usando variables de entorno
Uno de los usos más habituales consiste en almacenar la URL base de una API.
Sin variables:
fetch("https://api.midominio.com/users")
Con variables:
const API = import.meta.env.VITE_API_URL
fetch(`${API}/users`)
También puedes encapsular la URL en un pequeño cliente HTTP.
const API = import.meta.env.VITE_API_URL
export async function getUsers() {
const response = await fetch(`${API}/users`)
if (!response.ok) {
throw new Error("No fue posible obtener los usuarios")
}
return response.json()
}
Con este enfoque, si la dirección del servidor cambia únicamente será necesario modificar el archivo .env.
Variables para diferentes ambientes
En proyectos pequeños suele existir un único archivo .env, pero cuando la aplicación pasa por distintos entornos normalmente aparecen varios archivos.
.env
.env.local
.env.development
.env.production
.env.test
Cada uno tiene una función distinta.
Por ejemplo, durante el desarrollo podrías trabajar con una API local.
.env.development
VITE_API_URL=http://localhost:3000
Mientras que producción utilizaría otro servidor.
.env.production
VITE_API_URL=https://api.midominio.com
Cuando ejecutas:
npm run dev
Vite carga automáticamente:
.env.env.development
Al generar el build:
npm run build
utilizará:
.env.env.production
Esto permite mantener configuraciones independientes sin tocar una sola línea del código fuente.
Variables locales que no deberían subirse al repositorio
Hay ocasiones donde cada desarrollador necesita una configuración diferente.
Por ejemplo, una IP distinta para acceder al backend.
En esos casos resulta útil crear:
.env.local
Ejemplo:
VITE_API_URL=http://192.168.1.100:3000
Ese archivo normalmente se agrega al .gitignore.
.env.local
Así cada integrante del equipo puede tener su propia configuración sin afectar al resto.
Variables incorporadas por Vite
Además de las variables que defines manualmente, Vite expone información útil sobre el entorno de ejecución.
console.log(import.meta.env.MODE)
console.log(import.meta.env.DEV)
console.log(import.meta.env.PROD)
console.log(import.meta.env.BASE_URL)
Durante el desarrollo el resultado suele ser parecido a esto:
MODE = development
DEV = true
PROD = false
Y después del build:
MODE = production
DEV = false
PROD = true
Estas variables resultan útiles para habilitar herramientas de depuración únicamente durante el desarrollo.
if (import.meta.env.DEV) {
console.log("Modo desarrollo")
}
Centralizar la configuración
Cuando una aplicación empieza a tener muchas variables es recomendable no acceder directamente a import.meta.env desde cualquier componente.
Una alternativa sencilla consiste en crear un archivo de configuración.
// src/config/env.js
export const env = {
api: import.meta.env.VITE_API_URL,
appName: import.meta.env.VITE_APP_NAME,
version: import.meta.env.VITE_APP_VERSION
}
Después simplemente importas ese objeto.
import { env } from "./config/env"
console.log(env.api)
Además de mantener el código más limpio, facilita futuras modificaciones si decides cambiar la forma de obtener la configuración.
Trabajar con TypeScript
Si utilizas TypeScript puedes definir los tipos para evitar errores y obtener autocompletado.
Crea el archivo:
src/vite-env.d.ts
Contenido:
interface ImportMetaEnv {
readonly VITE_API_URL: string
readonly VITE_APP_NAME: string
readonly VITE_APP_VERSION: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
Ahora TypeScript mostrará un error si intentas acceder a una variable inexistente.
import.meta.env.VITE_APPI_URL
Property 'VITE_APPI_URL' does not exist.
Ese tipo de validaciones ahorra bastante tiempo cuando el proyecto crece.
Reiniciar Vite después de modificar un .env
Algo que suele confundir a quienes comienzan con Vite es que modificar un archivo .env no actualiza automáticamente las variables.
Después de agregar una nueva variable debes detener el servidor.
CTRL + C
Y volver a iniciarlo.
npm run dev
Si olvidas hacerlo, probablemente pienses que la variable no funciona cuando en realidad Vite todavía está utilizando la configuración anterior.
Información sensible
Uno de los errores más comunes consiste en asumir que un archivo .env siempre es privado.
En aplicaciones frontend eso no es cierto.
Todo lo que empiece con VITE_ termina formando parte del código JavaScript generado durante el build.
Eso significa que cualquier usuario puede verlo utilizando las herramientas del navegador.
Por esa razón nunca deberían almacenarse datos como:
VITE_DATABASE_PASSWORD=123456
VITE_SECRET_KEY=abc123
VITE_JWT_SECRET=mi_clave_privada
Las contraseñas, claves privadas, tokens de acceso o credenciales de bases de datos pertenecen al servidor, nunca al cliente.
Las variables de Vite están pensadas para información pública como:
- URL de una API
- Nombre de la aplicación
- Versión
- Configuración visual
- IDs públicos de servicios externos
Ejemplo completo
Archivo .env
VITE_APP_NAME=Blog Vite
VITE_API_URL=https://jsonplaceholder.typicode.com
Componente:
import { useEffect, useState } from "react"
function App() {
const [posts, setPosts] = useState([])
useEffect(() => {
async function loadPosts() {
const response = await fetch(
`${import.meta.env.VITE_API_URL}/posts?_limit=5`
)
const data = await response.json()
setPosts(data)
}
loadPosts()
}, [])
return (
<main>
<h1>{import.meta.env.VITE_APP_NAME}</h1>
<ul>
{posts.map(post => (
<li key={post.id}>
{post.title}
</li>
))}
</ul>
</main>
)
}
export default App
El componente no depende de una URL fija. Cambiar de entorno únicamente requiere modificar el archivo correspondiente.
Errores comunes
Olvidar el prefijo VITE_
API_URL=http://localhost:3000
Debe ser:
VITE_API_URL=http://localhost:3000
Usar process.env
Incorrecto:
process.env.API_URL
Correcto:
import.meta.env.VITE_API_URL
No reiniciar el servidor
Si agregaste una variable nueva y aparece como undefined, reinicia Vite antes de seguir buscando el problema.
npm run dev
Guardar secretos en el frontend
Las variables públicas nunca deben contener:
- Contraseñas
- Claves privadas
- Tokens de administrador
- Credenciales de bases de datos
Si el navegador puede acceder a esa información, cualquier usuario también podrá hacerlo.
Acceder directamente a import.meta.env desde todo el proyecto
En aplicaciones pequeñas no representa un inconveniente, pero cuando el código comienza a crecer es más cómodo centralizar la configuración en un único archivo. Además de mejorar la organización, evita modificar decenas de componentes cuando cambia el nombre de una variable o se incorpora una nueva configuración.