Use JS/TS files for environment variables over .env files.
- JS/TS as env files — write environment variables in JavaScript or TypeScript with full type safety and IntelliSense.
- Runtime config — enable dynamic configuration after deployment; edit a JSON file on the server without rebuilding.
Install the plugin:
npm install -D vite-plugin-typenvAdd it to your Vite config:
// vite.config.js
import { defineConfig } from 'vite'
import typenv from 'vite-plugin-typenv'
export default defineConfig({
plugins: [
typenv(),
],
})The plugin will load additional environment variables from the following files in your environment directory:
env.js # loaded in all cases
env.local.js # loaded in all cases, ignored by git
env.[mode].js # only loaded in specified mode
env.[mode].local.js # only loaded in specified mode, ignored by git
To get TypeScript IntelliSense, create an vite-env.d.ts in src directory, and augment UserDefinedEnvVariables (instead of ImportMetaEnv, see Intellisense for TypeScript for more details):
// src/vite-env.d.ts
interface UserDefinedEnvVariables {
/**
* App title
*/
readonly VITE_APP_TITLE: string
// more env variables...
}Then add vite/client and vite-plugin-typenv/client to your tsconfig.json:
// tsconfig.json
{
"compilerOptions": {
"types": ["vite/client", "vite-plugin-typenv/client"]
}
}
Using triple-slash directive
Alternatively, you can add the following directive to your vite-env.d.ts file:
// src/vite-env.d.ts
/// <reference types="vite/client" />
/// <reference types="vite-plugin-typenv/client" />Note
After doing this, import.meta.env will also be typed.
Replace your original .env files with env.js or env.ts files, and use the defineDefaultVariables function to define env variables:
// env.js
import { defineDefaultVariables } from 'vite-plugin-typenv'
export default defineDefaultVariables({
VITE_APP_TITLE: 'Vite App', // Now fully type-safe with IntelliSense
})Local env files and mode-specific env files are also supported, use the defineVariables function to define env variables:
// env.local.js
import { defineVariables } from 'vite-plugin-typenv'
export default defineVariables({
VITE_APP_TITLE: 'Vite App Local', // All env variables here are optional
})Note
By default, only variables prefixed with VITE_ are exposed to your Vite-processed code. You can customize this behavior by setting the envPrefix option.
Also, variables expansion is supported and enabled by default. The core logic is directly copied from dotenv-expand, refer to their docs to learn more about the syntax.
Note that if you want to use $ in your env variables, you need to escape it with \.
// env.local.js
import { defineVariables } from 'vite-plugin-typenv'
export default defineVariables({
VITE_USERNAME: 'keroz',
VITE_MESSAGE: 'Hello $VITE_USERNAME', // Hello keroz
VITE_ESCAPED_MESSAGE: '\\$foo', // $foo
})Note
env.*.local.js/tsfiles are local-only and can contain sensitive variables. You should add*.local.js/tsto your.gitignoreto avoid them being checked into git.- Since any variables exposed to your Vite source code will end up in your client bundle,
VITE_*variables should not contain any sensitive information.
To use environment variables in Vite config file, you can use loadEnv helper function:
// vite.config.js
import { defineConfig } from 'vite'
import { loadEnv } from 'vite-plugin-typenv'
export default defineConfig(async ({ mode }) => {
const env = await loadEnv(mode)
return {
base: env.VITE_BASE_URL
}
})See also Using Environment Variables in Config in Vite docs.
When you deploy your app to a server, you may want to change some configuration without rebuilding. This plugin writes a config.json file to the output directory during build, which can be modified on the server at any time.
Enable it in your Vite config:
// vite.config.js
import { defineConfig } from 'vite'
import typenv from 'vite-plugin-typenv'
export default defineConfig({
plugins: [
typenv({
runtimeEnv: {
enabled: true,
name: 'config', // default, produces config.json
include: ['VITE_API_URL', 'VITE_APP_TITLE'], // optional: limit which keys are runtime-editable
},
}),
],
})During vite build, all resolved environment variables are written to the output directory (e.g., dist/config.json), making it available at the root of your deployed site.
To access the config at runtime, import the virtual module virtual:typenv/runtime:
// main.ts or any component
import env from 'virtual:typenv/runtime'
// In dev: values from env files (loaded by loadEnv).
// In production: values from /config.json on the server.
console.log(env.VITE_APP_TITLE)