question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unset env variables are not properly embedded

See original GitHub issue

Describe the bug

Variables like REACT_APP_FOO are hard-baked into the code if they were present in the environment during build-time. Referencing a variable that did not exist during build time results in rather useless code that cannot be minified:

process.env.REACT_APP_FOO

->

Object({
    NODE_ENV: "production",
    PUBLIC_URL: "",
    WDS_SOCKET_HOST: void 0,
    WDS_SOCKET_PATH: void 0,
    WDS_SOCKET_PORT: void 0
}).REACT_APP_FOO

This will neither cause an error, not is it minified into a constant expression.

Full example further below.

Did you try recovering your dependencies?

Problem is reproducible on a fresh install. > npm --version: 6.14.4

Which terms did you search for in User Guide?

This behaviour is not documented on https://create-react-app.dev/docs/adding-custom-environment-variables/

Environment

Environment Info:

  current version of create-react-app: 3.4.1

  [Tested on multiple systems, everything else is irrelevant]

Steps to reproduce

> npx create-react-app test
> cd test
> $EDITOR src/index.js

index.js:

if (process.env.REACT_APP_FOO) {
	console.log('Foo is enabled');
}
else {
	console.log('Foo is disabled');
}
> npm run build
> cat build/static/js/main*.js

main*.js (prettified):

(this.webpackJsonptest = this.webpackJsonptest || []).push([
    [0],
    [function(o, s, e) {
        o.exports = e(1)
    }, function(o, s) {
        Object({
            NODE_ENV: "production",
            PUBLIC_URL: "",
            WDS_SOCKET_HOST: void 0,
            WDS_SOCKET_PATH: void 0,
            WDS_SOCKET_PORT: void 0
        }).REACT_APP_FOO ? console.log("Foo is enabled") : console.log("Foo is disabled")
    }],
    [
        [0, 1]
    ]
]);

Expected behavior

  • Preferred: the build emits a warning or an error when referencing a missing variable. It’s most likely either a typo in the variable name, or a broken build configuration.
  • Alternatively, the variable is replaced with undefined or void 0 or '' or some other sensible default value.
  • Alternatively, this behaviour is at least documented with a warning on the corresponding page.

The workaround is to define a default value for every used variable in .env and commit the file, but that doesn’t protect against mistyped identifiers in the code.

Actual behavior

See above for actual output. The output contains both '"Foo is enabled"' and "Foo is disabled", even though one of them is dead code.

Reproducible demo

See above.

I am not sure how best to resolve the issue.

Replacing with undefined or '' isn’t easy:

  • It’s not a bug in terser - the code could evaluate to something other than undefined if someone sets Object.prototype.REACT_APP_FOO, so terser is not allowed to minify here. Playing around with terser’s repl, I was unable to find a different construct for process.env that would allow minification here.
  • webpack’s DefinePlugin does not allow regexps for replacements; substituting REACT_APP_.* is not possible.

Emitting an error isn’t easy:

  • scanning the build output for remaining process.env.REACT_APP_ won’t work, and scanning for the whole code snippet above seems really fragile.

This could be solved by moving the replacement logic from DefinePlugin into a custom babel plugin (similar to this one). Considering that cra only supports replacing with strings, and not with arbitrary javascript code, that might work. Is babel guaranteed to be run on every source file, including typescript?

If all else fails, I think it deserves at least a warning in the documentation.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:15

github_iconTop GitHub Comments

2reactions
cauthmanncommented, May 5, 2020

@abumalick: That looks like a different issue. I’m not concerned that a list of ENV variables appears in the output - it’s likely intended behaviour to account for code like:

let x = process.env;
let foo = x.REACT_APP_FOO;

Those variables shouldn’t contain anything sensitive, and I’m sure some code somewhere relies on this working.

What concerns me (and what I consider a bug) is that referencing a variable that wasn’t defined does not result in a constant expression. If env vars are used for feature gating, then this will prevent dead code elimination of the gated features.

As you can see above, both "Foo is enabled" and "Foo is disabled" appear in the output; both branches would presumably contain a lot of code, and one of them is dead code.

I’ve edited the issue to clarify.

0reactions
xMartincommented, Dec 2, 2022

Still an issue with the latest version.

Read more comments on GitHub >

github_iconTop Results From Across the Web

envsubst: default values for unset variables - Stack Overflow
According to man envsubst , envsubst will only ever replace references to environment variables in the form of ${VAR} or $VAR .
Read more >
Sys.setenv: Set or Unset Environment Variables - Rdrr.io
On Unix-alikes, if Sys.unsetenv is not supported, it will at least try to set the value of the environment variable to "" ,...
Read more >
Analyzing the Hidden Danger of Environment Variables for ...
The use of environment variables is a common practice in the DevOps community as it provides easy access to configuration properties.
Read more >
Problems with Environment Variables
If the error message states that the environment variable is not set, IT MEANS PRECISELY THAT ! The most likely reason is that...
Read more >
Environment.SetEnvironmentVariable Method (System)
If the value argument is not empty (see the discussion of deleting an environment variable later in this section for the definition of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found