vite-plugin-envsubst
raw JSON → 0.3.0 verified Mon Apr 27 auth: no javascript
A Vite plugin that transforms import.meta.env references to globalThis.env placeholders for runtime substitution via envsubst or Caddy's templating engine. Current stable version 0.3.0. Released in April 2025. Solves the problem of environment-specific builds by deferring variable injection to runtime, suitable for Docker/Kubernetes deployments. Key differentiators: only transforms declared variables from vite-env.d.ts, respects Vite's envPrefix, supports both envsubst and Caddy template syntax, and uses sourcemap-preserving transforms with a single runtime dependency (rolldown-string). Unlike other env injection plugins, it enables true build-once-deploy-anywhere without build-time environment knowledge.
Common errors
error SyntaxError: Cannot use import statement outside a module ↓
cause Using require() or ts-node without ESM enabled for this package
fix
Add "type": "module" to package.json or use .mts extension for vite.config.ts
error Error: Plugin envSubstPlugin is missing required option 'vite-env.d.ts' or no variables found ↓
cause ImportMetaEnv interface not declared or empty in vite-env.d.ts
fix
Add interface ImportMetaEnv with readonly string fields in src/vite-env.d.ts
error TypeError: envSubstPlugin is not a function ↓
cause Wrong import style (default import instead of named import)
fix
Use import { envSubstPlugin } from 'vite-plugin-envsubst'
Warnings
gotcha Must declare environment variables in 'vite-env.d.ts' or they will NOT be transformed ↓
fix Add interface ImportMetaEnv with readonly string fields for each variable in src/vite-env.d.ts
gotcha Only variables matching Vite's envPrefix (default VITE_) are transformed by default ↓
fix Set envPrefix in Vite config to include non-VITE_ variables or declare them in vite-env.d.ts (still only VITE_ transformed unless prefix changed)
gotcha envsubst is not included in hardened nginx images like Chainguard's ↓
fix Use Caddy template engine or install envsubst in Docker image explicitly
breaking Plugin only runs during build; dev server uses native import.meta.env (placeholders are not replaced) ↓
fix For dev server, provide actual env vars via .env files or command line. The plugin skips transform in dev mode.
gotcha Importing from 'vite-plugin-envsubst' directly without ESM support can fail; no CommonJS require() ↓
fix Use import syntax and set module resolution to ESM or 'bundler' in tsconfig.json
Install
npm install vite-plugin-envsubst yarn add vite-plugin-envsubst pnpm add vite-plugin-envsubst Imports
- envSubstPlugin wrong
const envSubstPlugin = require('vite-plugin-envsubst')correctimport { envSubstPlugin } from 'vite-plugin-envsubst' - EnvSubstPluginOptions wrong
import { EnvSubstPluginOptions } from 'vite-plugin-envsubst'correctimport type { EnvSubstPluginOptions } from 'vite-plugin-envsubst' - plugin default wrong
import envSubstPlugin from 'vite-plugin-envsubst'correctimport { envSubstPlugin } from 'vite-plugin-envsubst'
Quickstart
// vite.config.ts
import { defineConfig } from 'vite';
import { envSubstPlugin } from 'vite-plugin-envsubst';
export default defineConfig({
plugins: [
envSubstPlugin({
globalObject: 'globalThis',
templateEngine: 'envsubst',
include: [/\.([cm]?[jt]sx?)$/],
exclude: [/node_modules/],
}),
],
});
// src/vite-env.d.ts must declare variables:
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
// src/main.ts
const apiUrl = import.meta.env.VITE_API_URL;
console.log(apiUrl);