nx icon indicating copy to clipboard operation
nx copied to clipboard

Disable loading .env files

Open dschnare opened this issue 2 years ago • 17 comments

Description

Be able to opt out of loading .env files.

Motivation

When attempting to migrate our monorepo to use Nx, we have encountered a challenge where our existing .env files are causing tests to fail because they are loaded when we originally didn't intend them to load during tests.

Suggested Implementation

If an environment variable is present like NX_LOAD_DOT_ENV_FILES and set to "false" then no .env files will be loaded.

Another possibility is to check if an env file has been ignored in the .nxignore file. This would allow removing all or only a few env files from the load hierarchy.

dschnare avatar Dec 23 '22 22:12 dschnare

I tried investigating the source, and the runOne() function (defined in the command-line namespace) seems to have a extraOptions.loadDotEnvFiles: boolean it accepts, but I tried hardcoding it to false and the env files are still loaded when running a command like nx run my-proj:test.

dschnare avatar Dec 23 '22 23:12 dschnare

Narrowed it down to two methods ForkedProcessTaskRunner#getDotenvVariablesForForkedProcess and ForkedProcessTaskRunner#getDotenvVariablesForTask. However, I tried hardcoding those methods to each return {} and the root .env file is still loaded.

My test so far has been to install Nx locally and run a dummy command like ./node_modules/.bin/nx run dummy:jump.

Project.json:

{
  "name": "dummy",
  "targets": {
    "jump": {
      "executor": "nx:run-commands",
      "options": {
        "commands": ["echo $MY_VAR"]
      }
    }
  }
}

Root level .env:

MY_VAR=hello

What I am after in this test is when echoing I should see nothing, not the env var loaded from the .env file.

dschnare avatar Dec 24 '22 14:12 dschnare

Got it. PR incoming.

dschnare avatar Dec 24 '22 15:12 dschnare

+1. This completely breaks Vite's env setup since Vite doesn't override existing env variables. So nx loads the default .env and then when Vite goes to load the mode specific and local .env.mode and .env.mode.local files, it doesn't overwrite the base since nx has already loaded something and put it in process.env. I even tried @nrwl/vite and it still doesn't work properly.

The only solution for now I think is to rename my start script to development and even then it would only load .env.development and not .env.development.local

mattrunyon avatar Jan 25 '23 03:01 mattrunyon

I think what we might want to do is add an option in nx.json (e.g. loadDotentFile), and when generating a Vite app we can set it to false.

That way, users generating a Vite project will have this set and handled for them automatically. The environment variable can still be added and documented here https://nx.dev/reference/environment-variables#environment-variables for users who may need the behavior for some projects in their workspace.

jaysoo avatar Jan 25 '23 19:01 jaysoo

Another option I could think of is nx only loading NX_ env variables. It seems to be loading all which is causing the conflict w/ Vite.

I think the current setup would also conflict w/ Create React App, but seems that's getting left behind so not a big deal there

mattrunyon avatar Jan 25 '23 19:01 mattrunyon

Loading a subset of .env file isn't supported by dotenv AFAIK.

jaysoo avatar Jan 25 '23 20:01 jaysoo

Loading only a subset would also be a pretty major breaking change when compared to the functionality thats been around for a long time now

AgentEnder avatar Jan 25 '23 21:01 AgentEnder

are there any workarounds to avoid nx loading .env into global environments? While using Vite this behavior makes .env take into first place before .env.test

edikdeisling avatar May 02 '23 16:05 edikdeisling

+1, this even breaks one of the Nx recipes to build your own executor to compose executors: https://nx.dev/plugins/recipes/compose-executors because when the executor is executed also loads the env vars for .env and .env.local files.

lucasvieirasilva avatar Jul 10 '23 15:07 lucasvieirasilva

are there any workarounds to avoid nx loading .env into global environments? While using Vite this behavior makes .env take into first place before .env.test

AFAIK you can't avoid loading .env by nx yet but you can undo what nx loaded (before running vite) by

unset ${!VITE_*}

mpacholec avatar Aug 02 '23 16:08 mpacholec

Hi! I just switched from vite -> nx/vite and environment variables loading is quiet broken, loading order is inversed and some files are not loaded at all (.env.development.local). Another problem is that variables replacement does not work anymore (dotenv extended is probably not used)

Is there some quick temporary solution to run on the vite.config.js file? Maybe resetting the env before loading the new one? Thanks!

apocaliss92 avatar Aug 22 '23 11:08 apocaliss92

This seems to be fixed, but it is not well documented https://github.com/nrwl/nx/pull/12602

KarnerTh avatar Sep 06 '23 07:09 KarnerTh

NX_LOAD_DOT_ENV_FILES not work for me nx affected still loads the .env file even with NX_LOAD_DOT_ENV_FILES set "false". Maybe because true is hardcoded there https://github.com/nrwl/nx/blob/d5f87f79bda0ff1efdf97639c83e1d25a9e265eb/packages/nx/src/command-line/affected/affected.ts#L115

The only option I found is to patch nx with pnpm and replace all loadDotEnvFiles: true with loadDotEnvFiles: false

edikdeisling avatar Sep 14 '23 20:09 edikdeisling

What the current state looks like:

  • NX_LOAD_DOT_ENV_FILES defines whether the various .env files are read source
  • NX_LOAD_DOT_ENV_FILES is set depending on extraOptions.loadDotEnvFiles property source
  • extraOptions is param, where loadDotEnvFiles defaults to true in run-one, run-many, affected
  • extraOptions are never passed to the methods runOne and runMany
  • Since the params are not provided, defaults are used ({ excludeTaskDependencies: false, loadDotEnvFiles: true }), overriding the provided NX_LOAD_DOT_ENV_FILES flag.
  • In Lerna the --load-env-files='false' cli options works because it passes the extraOptions for runOne, runMany (related topics: lerna issue #3371, lerna pull #3375)
  • In discord one result popped up regarding NX_LOAD_DOT_ENV_FILES, but I'm unsure what to do with that, as I'm fairly new to nx image

Essentially it seems that the reason for the flag not working is because where this flag should be provided, it is not.

When this issue gets fixed, this flag should be described in the docs

Currently resolved it for myself similarly to @edikdeisling, where I replaced the default loadDotEnvFiles default values to false in my node_modules nx/src/command-line/run-one/run-one.js and nx/src/command-line/run-many/run-many.js. But this is guaranteed to break after re-installing deps / upgrading nx version

jantoodre avatar Nov 06 '23 12:11 jantoodre

Any news regarding this issue? Will it be worked on after NX 18 (crystal) has been launched?

I recently migrated a monorepo with a few Serverless (Framework) projects. They rely on the .env.${STAGE} resolution from it (https://www.serverless.com/framework/docs/environment-variables) but these projects also contain .env (with no stage) for fallback stages. (e.g. ephemeral dev environments).

When running the deploy command via e.g. "nx deploy" it would never succeed because .env is always there already.

What I did (not future proof as mentioned before) is patching loadDotEnvFiles as follows:

--- a/bin/nx.js
+++ b/bin/nx.js
@@ -88,6 +88,8 @@ function main() {
  * - .env.local
  */
 function loadDotEnvFiles() {
+    if (process.env.NX_LOAD_DOT_ENV_FILES !== 'true') return;
+    
     for (const file of ['.local.env', '.env.local', '.env']) {
         const myEnv = (0, dotenv_1.config)({
             path: file,

--- a/src/tasks-runner/run-command.js
+++ b/src/tasks-runner/run-command.js
@@ -93,7 +93,7 @@ async function runCommand(projectsToRun, projectGraph, { nxJson }, nxArgs, overr
             lifeCycle,
             nxJson,
             nxArgs,
-            loadDotEnvFiles: extraOptions.loadDotEnvFiles,
+            loadDotEnvFiles: false,
             initiatingProject,
         });
         await renderIsDone;
@@ -112,9 +112,9 @@ function setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles) {
     if (nxArgs.outputStyle == 'stream-without-prefixes') {
         process.env.NX_STREAM_OUTPUT = 'true';
     }
-    if (loadDotEnvFiles) {
-        process.env.NX_LOAD_DOT_ENV_FILES = 'true';
-    }
+    // if (loadDotEnvFiles) {
+    //     process.env.NX_LOAD_DOT_ENV_FILES = 'true';
+    // }
 }
 async function invokeTasksRunner({ tasks, projectGraph, taskGraph, lifeCycle, nxJson, nxArgs, loadDotEnvFiles, initiatingProject, }) {
     setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles);

NX_LOAD_DOT_ENV_FILES could be an option, but setEnvVarsBasedOnArgs always sets it to true and extraOptions is not available to configure anywhere.

sergioflores-j avatar Mar 07 '24 13:03 sergioflores-j

The env variable NX_LOAD_DOT_ENV_FILES should be functional since version 19.0.4 : https://github.com/nrwl/nx/releases/tag/19.0.4

Thank you @xiongemi !

Gnucki avatar May 17 '24 17:05 Gnucki