dotenv-webpack: Multi-variable destructuring breaks when working with webpack 3

Hi, team,

Found an interesting bug:

Issue

Using dotent-webpack@1.5.3 and webpack@3.3.0,

// .env
DB_HOST=127.0.0.1
DB_PASS=foobar
S3_API=mysecretkey

Use the vars in JS:

const { DB_HOST, DB_PASS } = process.env;

Would cause runtime error:

Uncaught (in promise) ReferenceError: process is not defined

Expected

It should replace both vars at compile time.

Possible Root Cause

I believe this issue is caused by https://github.com/webpack/webpack/issues/5215

So I changed the JS to:

const { DB_HOST } = process.env;
const { DB_PASS } = process.env;

It works well as expected.

I debugged the plugin and found that the underlying formatData (https://github.com/mrsteele/dotenv-webpack/blob/master/src/index.js#L63) transferred to webpack.DefinePlugin is:

{
  'process.env.DB_HOST': '"127.0.0.1"',
  'process.env.DB_PASS': '"foobar"',
  'process.env.S3_API': '"mysecretkey"'
}

However the format that recommended in https://github.com/webpack/webpack/issues/5215#issuecomment-314363436 is:

new DefinePlugin({
  "process.env": {
    a: JSON.stringify("a"),
    b: JSON.stringify("b")
  }
})

So I guess a minor fix in dotenv-webpack would solve the issue.

However, I think it ought to be a webpack.DefinePlugin regression bug, since it the current formatData used to work well with webpack 2.

What do you think? Thanks.

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 12
  • Comments: 25 (8 by maintainers)

Commits related to this issue

Most upvoted comments

I’m using

  • dotenv-webpack 1.7.0
  • webpack 4.31.0

Still can not do:

  const { BASE_URL, API_VERSION } = process.env;

But yeah the wordaround mentioned here works.

I just stumbled on the same issue where the line below works:

const { DIRECTUS_ENDPOINT } = process.env;
// You can use `DIRECTUS_ENDPOINT` as expected.

Whereas the line below throws the process is undefined error:

const { DIRECTUS_ENDPOINT, DIRECTUS_ACCESS_TOKEN } = process.env;
// Triggers `process is undefined`

The workaround below does indeed work but doing this mostly defeats the purpose of destructuring:

const { DIRECTUS_ENDPOINT } = process.env;
const { DIRECTUS_ACCESS_TOKEN } = process.env;
// You can use `DIRECTUS_ENDPOINT` and `DIRECTUS_ACCESS_TOKEN` as expected.

Even worse, if you console.log process.env, things work as expected:

const { DIRECTUS_ENDPOINT, DIRECTUS_ACCESS_TOKEN } = process.env;
console.log(process.env);
// You can use `DIRECTUS_ENDPOINT` and `DIRECTUS_ACCESS_TOKEN` as expected.

This seems extremely counter intuitive and confusing from a developer’s perspective and I’m sure this has and will continue to trip up developers because of understandable assumptions. If you want to drive a developer crazy, it looks like you found an effective method. If you can access process.env.DIRECTUS_ENDPOINT that way, you can infer that process.env is an object. It seems fair to then infer that destructuring process.env to get to more than one property would work like it would with any object in JavaScript. Not exposing process.env as an object like the Node runtime does seems non-standard. If you’re not following the standards of the Node runtime, then maybe have the environment variables live in a global variable that does not have the same name as the one used by Node. This way, developers might be more careful about their assumptions (namely, not assumed that it works just like Node), even if not being able to destructure what looks like an object to get two properties is still extremely confusing, especially if using console.log fixes it.

create a config.ts file that has all your process.env like this

export const config = {
    API_URL: process.env.API_URL,
};

always consume process.env from that file, so you can destructure if needed

I do not recommend destructuring

I’m using “webpack”: “5.20.0” Don’t works const { BASE_URL, API_VERSION } = process.env; // undefined undefined