Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 962
kctang Avatar asked Sep 25 '19 01:09

kctang


People also ask

Where does process env NODE_ENV come from?

Node. js exposes the current process's environment variables to the script as an object called process. env. From there, the Express web server framework popularized using an environment variable called NODE_ENV as a flag to indicate whether the server should be running in “development” mode vs “production” mode.

What does NODE_ENV default to?

We see that it in fact reads NODE_ENV and defaults to 'development' if it isn't set. This variable is exposed to applications via 'app.

What is process env NODE_ENV === development?

process. env is a reference to your environment, so you have to set the variable there. To set an environment variable in Windows: SET NODE_ENV=development. on macOS / OS X or Linux: export NODE_ENV=development. Follow this answer to receive notifications.

What is env NODE_ENV?

NODE_ENV is an environment variable that stands for node environment in express server. The NODE_ENV environment variable specifies the environment in which an application is running (usually, development or production).


3 Answers

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']
like image 193
Ondřej Wagenknecht Avatar answered Oct 07 '22 13:10

Ondřej Wagenknecht


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:

  • the build command executes the nx builder which creates a configuration for web-pack
  • this configuration instructions for the webpack-define plugin to replace the text process.env.NODE_ENV during compilation with the actual value of the env-var (or the nx-mode):
    see nx-code getClientEnvironment()

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.

like image 37
TmTron Avatar answered Oct 07 '22 15:10

TmTron


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
like image 28
William Neely Avatar answered Oct 07 '22 15:10

William Neely