Pitfalls of `process.env` every React developer should know

arnelenero

Arnel Enero

Posted on September 14, 2022

Pitfalls of `process.env` every React developer should know

Pitfall #1: It does not exist in the browser

Unlike in Node.js, there is no such thing as process.env object in the browser. One neat webpack trick, however, allows us to "emulate" this construct right in our React app.

Webpack's DefinePlugin injects environment variables by token replacement of process.env.SOME_ENV_VAR. The final compiled JS will not have any reference to process.env because, remember, it does not exist in the browser. So if we have something like this:

console.log(process.env.SOME_ENV_VAR);
Enter fullscreen mode Exit fullscreen mode

webpack will compile that to something like this:

console.log('value of SOME_ENV_VAR');
Enter fullscreen mode Exit fullscreen mode

Pitfall #2: We cannot assign values to it in React code

This one is really just a natural side-effect of pitfall #1. Since process.env will not exist in the compiled JS code, it follows that it doesn't make sense to try overriding environment variables inside our React app like this:

process.env.REACT_APP_ENV_VAR = 'cannot do this';
Enter fullscreen mode Exit fullscreen mode

Pitfall #3: It may get compiled in a way you didn't expect

There is one significant pitfall that we need to be wary of: We need to make sure that all environment variables referenced in our source code are defined in our .env files or elsewhere.

If DefinePlugin cannot find a referenced env var's value, it will not token-replace any references with undefined. For example, if we have not defined REACT_APP_NOT_FOUND anywhere, but we have this code:

console.log(process.env.REACT_APP_NOT_FOUND);
Enter fullscreen mode Exit fullscreen mode

will not translate to this:

console.log(undefined);
Enter fullscreen mode Exit fullscreen mode

Instead, webpack will string-replace just the process.env part of the token with the entire key-value mapping of env vars. So the translation is actually something like this (even after minification):

console.log(
  {
    NODE_ENV: development,
    REACT_APP_NAME: My App,
    REACT_APP_ID: 232809283923,

    // ... possibly a long list of other values
  }.REACT_APP_NOT_FOUND
);
Enter fullscreen mode Exit fullscreen mode

Now imagine if we have lots of checks like this throughout our code:

if (process.env.REACT_APP_SOME_OPTIONAL_FLAG) { 
  /* . . . */ 
}
Enter fullscreen mode Exit fullscreen mode

and we only define env vars in our .env file for flags that are true, thinking it’s fine because the logic above only cares about the existence of the flag, not its value.

But take the above compiled code containing the entire env vars object literal, and multiply it by who knows how many possibly-undefined env vars... for sure it’s going to hurt our bundle size.

NOTE: The above behavior is based on how process.env is typically configured with DefinePlugin, such as in Create React App. YMMV.

💖 💪 🙅 🚩
arnelenero
Arnel Enero

Posted on September 14, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related