Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

env variables not accessible in vite.config.js #1930

Closed
jmheretik opened this issue Feb 7, 2021 · 12 comments · Fixed by #7180
Closed

env variables not accessible in vite.config.js #1930

jmheretik opened this issue Feb 7, 2021 · 12 comments · Fixed by #7180
Labels
enhancement New feature or request has workaround

Comments

@jmheretik
Copy link

Describe the bug

Variables from .env* files are accessible only during development/build but not already in vite.config.js.

Im not sure if this behaviour was omitted on purpose because it doesn't align with vite's design or it was simply forgotten, but when I was using vue-cli I got used to having the env variables available already in vue.config.js. I find it super convenient to be able to setup the vue/vite configuration parameters based on the values provided by the .env* files (instead of checking the mode and conditionally setting the parameters to the same values which are already in my .env* files.

My current workaround is to use dotenv-flow package to imitate the same behaviour as in vue cli and put this on top of my vite.config.js: require('dotenv-flow').config().

Reproduction

  1. create .env with some variable: e.g. VITE_BASE_URL=/example/
  2. put console.log(process.env.VITE_BASE_URL) or console.log(import.meta.env.VITE_BASE_URL) somewhere in your vite.config.js
  3. its undefined

System Info

  • vite version: 2.0.0-beta.65
  • Operating System: Windows 10 64bit
  • Node version: v12.20.1
  • Package manager (npm/yarn/pnpm) and version: npm 6.14.10
@yyx990803 yyx990803 added enhancement New feature or request and removed pending triage labels Feb 8, 2021
@yyx990803
Copy link
Member

There's a chicken-egg problem here: Vite expects to resolve .env files from project root, but project root can be made different by the config file.

So if we resolve .env before resolving the config file, we can only resolve it from CWD, which would then break the case where the user puts .env files in a nested root specified via config.

@guillenotfound
Copy link
Contributor

This also applies to postcss file, on v1.x I was able to use variables from .env files, but seems like from v2.x those are not being injected until a later point.

Let me know if you need a repository with reproduction 👍

@pionxzh
Copy link

pionxzh commented Feb 13, 2021

we use a simple trick to do this in our project

export default ({ mode }) => {
    require('dotenv').config({ path: `./.env.${mode}` });
    // now you can access config with process.env.{configName}

    return defineConfig({
        /* ... */
    })
}

@jonjanisch
Copy link

For my use case I wanted to set the base property conditionally. I thought I could do this via env variables in vite.config.ts and ran into the same problem.

@pionxzh I may be wrong but should that be simply:

export default defineConfig(({mode}) => {
  require('dotenv').config({ path: `./.env.${mode}` });
  return {
    /* ... */
  }
});

The type definitions for defineConfig show that it accepts either the config object or a function that returns the config object:

export declare function defineConfig(config: UserConfigExport): UserConfigExport;

export declare type UserConfigExport = UserConfig | UserConfigFn;

export declare type UserConfigFn = (env: ConfigEnv) => UserConfig;

export declare interface ConfigEnv {
    command: 'build' | 'serve';
    mode: string;
}

@pionxzh
Copy link

pionxzh commented Feb 18, 2021

For my use case I wanted to set the base property conditionally. I thought I could do this via env variables in vite.config.ts and ran into the same problem.

@pionxzh I may be wrong but should that be simply:

export default defineConfig(({mode}) => {
  require('dotenv').config({ path: `./.env.${mode}` });
  return {
    /* ... */
  }
});

@jonjanisch
Ye, I think this way should be better, I didn't notice that defineConfig provide a function interface.
Thanks for the information 👍

@jmheretik
Copy link
Author

jmheretik commented Feb 22, 2021

found another trick in an older issue (#1096 (comment)), that is also nice and seems to cover .env.*.local files too:

import { loadEnv } from 'vite'

export default ({ mode }) => {
  Object.assign(process.env, loadEnv(mode, process.cwd()))
  ...
}

@sknightq
Copy link

Thanks for the code of @jmheretik. I'm using this in postcss.config.js.
I want to change the URL of the CSS background in postcss.config.js. However, the URL prefix is set in .env file. And postcss.config.js can't get variables from import.env(vite export)

module.export = ctx => {
  const {loadEnv} = require('vite')
  const {MY_VARIABLE} = loadEnv(ctx.env, process.cwd)
  return {
   ....
  }
}

@oliverpool
Copy link
Contributor

I think this behavior could be documented on https://vitejs.dev/guide/env-and-mode.html, shall I craft a PR?

@Pentadome
Copy link

if the .env files are not in the root folder, the following workaround worked for me.

const envDir = path.resolve(__dirname, "environment");

// see: https://github.com/vitejs/vite/issues/1930#issuecomment-783747858
const loadEnvVariables = (mode: string): void => {
    Object.assign(process.env, loadEnv(mode, envDir, ""));
    console.debug("process.env contains: \n" + JSON.stringify(process.env, undefined, 2));
};

// https://vitejs.dev/config/
export default defineConfig((init) => {
    loadEnvVariables(init.mode);
    return {
    .....

Compared to the other answers, I had to provide an empty string to the 3rd parameter of loadEnv. I am not sure why,

@Psycarlo
Copy link

Psycarlo commented Dec 4, 2021

This did not work for me:
Object.assign(process.env, loadEnv(mode, process.cwd()))

But this did:
Object.assign(process.env, loadEnv(mode, process.cwd(), ''))

chme added a commit to chme/forked-daapd that referenced this issue Jan 1, 2022
Proxying based on .env.development does not really work.
There are some workarounds:
- <https://stackoverflow.com/questions/66389043/how-can-i-use-vite-env-variables-in-vite-config-js>
- <vitejs/vite#1930>

Not sure if it is worth it ...
@carvalhoviniciusluiz
Copy link

This work for me:

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

  const processEnvValues = {
    'process.env': Object.entries(env).reduce(
      (prev, [key, val]) => {
        return {
          ...prev,
          [key]: val,
        }
      },
      {},
    )
  }

  return {
    plugins: [react()],
    define: processEnvValues
  }
}

chme added a commit to chme/forked-daapd that referenced this issue Feb 12, 2022
Proxying based on .env.development does not really work.
There are some workarounds:
- <https://stackoverflow.com/questions/66389043/how-can-i-use-vite-env-variables-in-vite-config-js>
- <vitejs/vite#1930>

Not sure if it is worth it ...
@wobedi
Copy link

wobedi commented Mar 2, 2022

Another workaround: Just use dotenv and then put the following at the top of your vite config/sveltekit config:

import 'dotenv/config';

@github-actions github-actions bot locked and limited conversation to collaborators Mar 20, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request has workaround
Projects
None yet
Development

Successfully merging a pull request may close this issue.