Skip to content

Instantly share code, notes, and snippets.

@alexilyaev
Last active March 7, 2023 09:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexilyaev/5c73dcdbcb429a1e0c081627548b7ca3 to your computer and use it in GitHub Desktop.
Save alexilyaev/5c73dcdbcb429a1e0c081627548b7ca3 to your computer and use it in GitHub Desktop.
.env vs. node-config

.env vs. node-config

Pros

  • Very simple to setup.
  • Automatically assigns configured values on top of process.env.
  • Automatically supports overriding configured values via Environment Variables.
  • Promotes best practices (FAQ):
    • Have only one config file.
    • Don't commit the file to version control.
  • Supported by Create React App out of the box.

Cons

  • Can't use dynamic values. e.g.:
    • Referencing other variables (can use dotenv-expand for that).
    • Importing constants from another file.
    • Setting a value by running a JavaScript expression like Date.now().
  • All values are translated into strings.
    • That's just how process.env behaves when assigning values on it. e.g.:
      process.env.ENABLED = true;
      process.env.NUM = 3;
      console.log(process.env.ENABLED, process.env.NUM);
      // 'true' '3'

Pros

  • Very flexible.
  • Can use any data structure.
  • Supports overriding configured values via Environment Variables (although requires a mapping config).
  • Supports multi deployment/instance configs out of the box.

Cons

  • Doesn't automatically map config values on process.env.
    • That's because it takes a different approach to configs.
  • Environment Variables overrides require a non trivial mapping config (Custom Environment Variables).
  • Doesn't support ES Modules syntax (although TypeScript is supported).
@alexilyaev
Copy link
Author

alexilyaev commented Jan 21, 2021

Tips

Create React App

  • Supports .env out of the box.
  • For node-config, can use react-app-rewired with a config-overrides.js file:
  const appConfig = require('config');

  module.exports = {
    webpack(config) {
      config.plugins.push(
        /**
         * Expose environment variables to webpack so they can be used
         * inside the app under `process.env` Object;
         * The defined values below are defaults and can be overwritten externally.
         * For more info, see:
         * https://webpack.js.org/plugins/environment-plugin/
         */
        new webpack.EnvironmentPlugin(appConfig)
      );

      return config;
    },

    jest(config) {
      /**
       * Since Webpack doesn't run during tests, we must map our config on top of
       * `process.env`, similar to how `webpack.EnvironmentPlugin` works.
       * All config values will be casted into strings.
       * This is due to how `process.env` works in Node.js.
       */
      Object.assign(process.env, appConfig);

      return config;
    },
  };

Usage in Frontend Projects

For both solutions, Webpack's EnvironmentPlugin can be used to map the config values on top of process.env to be available in the client side code.

// webpack.config.js
const appConfig = require('config');

// Or...
// const appConfig = require('dotenv').config();
// const appConfig = require('dotenv/config');

module.exports = {
  plugins: [
    /**
     * Expose environment variables to webpack so they can be used
     * inside the app under `process.env` Object;
     * The defined values below are defaults and can be overwritten externally.
     * For more info, see:
     * https://webpack.js.org/plugins/environment-plugin/
     */
    new webpack.EnvironmentPlugin(appConfig),
  ],
}

EnvironmentPlugin Notes

  • Values pass though JSON.stringify and then JSON.parse so non-string values are supported (if using node-config).
  • This is because Webpack creates it's own global Object process.env in the client and that Object behaves like regular JS and not limited to how process.env works in Node.js.

Jest Configuration

Requires additional configuration since Webpack doesn't run when running Jest.

// jest.config.js
const appConfig = require('config');

/**
 * Since Webpack doesn't run during tests, we must map our config on top of
 * `process.env`, similar to how `webpack.EnvironmentPlugin` works.
 * All config values will be casted into strings.
 * This is due to how `process.env` works in Node.js.
 */
Object.assign(process.env, appConfig);

module.exports = {
  // ...
};

Config Setup Before Startup

Both solutions can be executed before the target process runs.

.env preload

node -r dotenv/config server.js

node-config

node -r config server.js

This will require custom-environment-variables.js to be configured.

Running before Jest

node -r dotenv/config node_modules/.bin/jest

@alexilyaev
Copy link
Author

Conclusion

Prefer using .env as it's much simpler to setup and covers most use cases, especially for Frontend projects.
Use node-config only if you need complex or multi deployment/instance configs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment