process.env.NODE_ENV always 'development' when building nestjs app with nrwl nx
Asked Answered
C

6

17

My NX application's npm run build:server calls ng build api-server that triggers the @nrwl/node:build builder.

It builds the NestJS application as main.js. Things work except I wanted process.env.NODE_ENV to be evaluated at runtime but I think it was resolved at build time (via Webpack).

Currently, the value is always set to 'development'.

I am new to Nrwl's NX. Any solution this?

Clinkscales answered 25/9, 2019 at 1:42 Comment(0)
F
18

In NestJs/Nodejs app in Nx.Dev workspace process.env.NODE_ENV is replaced during compilation from typescript to javascript very "smart way" to "development" string constant (everything like NODE_ENV is replaced). I don't know why. But only way how can I get real NODE_ENV in runtime is this code:

//process.env.NODE_ENV
process.env['NODE' + '_ENV']
Faceplate answered 18/1, 2020 at 21:43 Comment(4)
I've got the exact same problem with NestJs, and I'm really surprised by your workaround, but it works so thank you ! Do you mind share a link or an explanation about the reasons concerning the override of NODE_ENV ? And I'm really curious about the difference at runtime between process.env.NODE_ENV and process.env['NODE' + '_ENV'] too.Kuo
@ondřej-wagenknecht I tried and it did solve the issue and get the real NODE_ENV. I imagined that the problem was Nx overwriting the variable. I would also want to to know why does this work. Do you have any link or explanation?Lightner
Yeah, that's really interesting why this works - I can only think of nx looking through code and replacing process.env.NODE_ENV occurences and this solution works because splitting it like that doesn't match regex anymoreAtaraxia
This just gave me undefined in React. :(Operate
G
11

The reason you're seeing development is because you're building the app in development mode - it's not best practice to evaluate at runtime because then the builder can't do fancy things to make the build production ready. If you want production, you need to build the app in production mode by adding the --prod flag (just like how you need to build Angular in production mode).

If you need to serve the app in production mode (instead of build) the default config doesn't provide you with a prod mode for serve. You'll need to add the configuration to your angular.json.

So this code:

"serve": {
      "builder": "@nrwl/node:execute",
      "options": {
        "buildTarget": "api-server:build"
      }
    },

Would become

"serve": {
      "builder": "@nrwl/node:execute",
      "options": {
        "buildTarget": "api-server:build"
      },
      "configurations": {
        "production": {
          "buildTarget": "api-server:build:production"
        }
      }
    },

and then you can run

ng serve --project=api-server --prod
Gettysburg answered 2/6, 2020 at 17:27 Comment(0)
S
9

Indeed the nx builder will replace the expression process.env.NODE_ENV in our source code with the current value of the env var (or the nx-mode).

What happens is this:

Since the webpack-define plugin will look for the text process.env.NODE_ENV, it's easy to use a workaround as explained in this answer:

process.env['NODE'+'_ENV']

Warning
When you need to apply this workaround to make your app work, then something is wrong. Since you have compiled your app in production mode, it does not make sense to pass another value for NODE_ENV when you start the (production) app.
The webpack Production page contains some helpful info.

We also had this case, and the issue was, that we relied on the NODE_ENV variable to load different database configs for dev, prod, test, etc.
The solution for our case was to simply use separate env-vars for the database config (e.g. DB_NAME, DB_PORT, ..), so that we can use different db-configs at runtime with any build-variants: dev, prod, test, etc.

Switzer answered 27/2, 2021 at 11:1 Comment(0)
K
0

I recently faced the same problem using Express instead of Nest. What we did to overcome this was adding some file replacements when compiling for any of our environments (development, production, staging, staging-dev). This is done in the angular.json file the same way the environment files are replaced for the Angular app .

Another approach that worked for us, was loading the environment variables only once, and retrieve them from that origin. As our app relies on Express for it's backend the used the Express env variable as:

import express from 'express';

const _app = express();
const _env = _app.get('env');

console.log(_env); // shows the right environment value set on NODE_ENV

To come to this conclusion we checked Express code for the env variable and it does use process.env.NODE_ENV internally.

Hope it helps. Best regards.

Katrinka answered 30/9, 2019 at 20:30 Comment(0)
H
-1

We had the same issue, we eventually used the cross-env package in our package.json:

"prodBuild": "cross-env NODE_ENV=production nx run api-server:build:production", "prodServe": "cross-env NODE_ENV=production nx run api-server:serve:production"

Hun answered 30/10, 2020 at 23:23 Comment(0)
M
-4

process.env is indeed only available at run-time. What is probably happening is that you are not setting this value when running your application. Can I ask how you are running it?

As a trivial example

# The following will read the environment variables that are defined in your shell (run `printenv` to see what those are)
> node main.js

# this will have your variable set
> NODE_ENV=production node main.js

Of course you want to have it actually set in your environment when deploying the app rather then passing it in this way, but if you're doing it locally you can do it like this.

Massif answered 26/9, 2019 at 13:54 Comment(1)
I ran the webpack built app using "NODE_ENV=xxx node main.js". The value of process.env.NODE_ENV is still "development" instead of "xxx".Clinkscales

© 2022 - 2024 — McMap. All rights reserved.