Search code examples
node.jsangular-clinrwlnrwl-nx

Using environment variables in nx based nodejs app


I've setup a project with several nodejs and angular apps inside a nrwl/nx workspace.

I'm trying to work with the environment files inside the nodejs apps.

I've setup the import like this: import {environment} from './environments/environment';

Then I ran ng serve my-node-app and it shows the environment for non production.

Now I tried to do ng serve my-node-app --prod to see how the app works with a production setup - but I get the error:

Configuration 'production' could not be found in project my-node-app.

Here's the project's angular.json config:

"ui-server": {
      "root": "apps/ui/server",
      "sourceRoot": "apps/ui/server/src",
      "projectType": "application",
      "prefix": "ui-server",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@nrwl/builders:node-build",
          "options": {
            "outputPath": "dist/apps/ui/server",
            "main": "apps/ui/server/src/main.ts",
            "tsConfig": "apps/ui/server/tsconfig.app.json",
            "assets": ["apps/ui/server/src/assets"]
          },
          "configurations": {
            "production": {
              "optimization": true,
              "extractLicenses": true,
              "fileReplacements": [
                {
                  "replace": "apps/ui/server/src/environments/environment.ts",
                  "with": "apps/ui/server/src/environments/environment.prod.ts"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@nrwl/builders:node-execute",
          "options": {
            "buildTarget": "ui-server:build"
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "apps/ui/server/tsconfig.app.json",
              "apps/ui/server/tsconfig.spec.json"
            ],
            "exclude": ["**/node_modules/**"]
          }
        },
        "test": {
          "builder": "@nrwl/builders:jest",
          "options": {
            "jestConfig": "apps/ui/server/jest.config.js",
            "tsConfig": "apps/ui/server/tsconfig.spec.json"
          }
        }
      }
    }

Am I missing something?


Solution

  • I've found this post when I was looking how to fetch the environmental variables defined in .env file.

    process.env.ENVIRONMENTAL_VARIABLES in frontend part can be accessed when rendering on the server (e.g. Angular Universal), having .env in the root of Nrwl monorepo and webpack properties, such as:

    const dotenv = require('dotenv-webpack');
    
    module.exports = {
      plugins: [
        new dotenv(),
      ],
    };
    

    Don't forget to change your angular.json:

    ...
    "architect": {
      "build": {
         "builder": "@angular-builders/custom-webpack:browser",
           "options": {
             "customWebpackConfig": {
               "path": "./webpack.browser.config.js",
               "replaceDuplicatePlugins": true
              },
              ...
    

    I've named the custom webpack as webpack.browser.config.js.

    Now, let say you have a server/..., which you're using for some backend stuff, then you won't have them accessible there. You need to install dotenv package and in the server/main.ts, let say that's your server's root, require this package, that way:

    require('dotenv').config();
    

    Note: until Angular 8 we were able to set up also webpack-server related logic, in a file such as webpack.server.config.js. Therefore, it was doable to apply basically same code related to dotenv, which was in webpack.browser.config.js. However, it doesn't work anymore. Angular CLI Builders are being used to build & server SSR apps instead.

    Deploying to Firebase/using Cloud Functions for Firebase (and possibly other Serverless/FaaS)?

    Then in your functions folder you need to paste the .env file as well. I assume here that from functions you're deploying.

    For debugging I'd advise:

    console.log(require('dotenv').config({ debug: true }));
    

    Might save you a lot of time.