Skip to content

Webpack Usage

Loren West edited this page May 16, 2023 · 26 revisions

Right now node-config doesn't work with webpack out of the box because it reads the config files at runtime, which can't be done when the code is running on a browser.

Option 1

If you're using Webpack 4, it includes excellent handling for complex config objects with DefinePlugin (as of 2018-05-07). Add the following to your webpack.config.js:

...
plugins: [
    new webpack.DefinePlugin({ CONFIG: JSON.stringify(require("config")) })
]

You can access all fields, including nested fields, under the CONFIG object in your client-side scripts, without exposing your entire config object. Note that you won't have access to get().

This approach does work in Webpack 3, but it inserts your entire config object wherever it is referenced. This is not recommended.

Option 2

Install the config-webpack package and put the following in webpack.config.js:

const ConfigWebpackPlugin = require("config-webpack");
...
plugins: [
    new ConfigWebpackPlugin()
]

This allows you to access your configuration on the client in the global namespace CONFIG.

console.log(CONFIG.server.url)

You can also change the default namespace from CONFIG to something else.

new ConfigWebpackPlugin("myConfigObject")

This method performs direct text replacement of config variables in your code with their values, and it doesn't expose any configs that aren't used.

Option 3

Below is an example of how you can use NODE_ENV at build time to have a static config built into your webpack bundle.

IMPORTANT NOTE
This will publish your entire config file into your front end application. If you have sensitive information you do not want downloaded, see the notes after the example.

// webpack-config.js
const config = require('config')
const fs = require('fs')
const path = require('path');

// This will take the config based on the current NODE_ENV and save it to 'build/client.json'
// Note: If '/build' does not exist, this command will error; alternatively, write to '/config'.
// The webpack alias below will then build that file into the client build.
fs.writeFileSync(path.resolve(__dirname, 'build/client.json'), JSON.stringify(config))

module.exports = {
  // ... other webpack config
  resolve: {
    alias: {
      config: path.resolve(__dirname, 'build/client.json')
    }
  }
}

Both server and client now can happily use import config from 'config'.

If you have things in the config that you do not want to publish to the front end, you may consider making a specific client section of the config, and only publishing that key to the static json file, e.g. import { client } from 'config';

Alternatively you could use lodash pick or omit to control what data is written to the file.

Important Notice for Users of Create-React-App The best option for CRA users is this option. The default webpack config for CRA is only allows you to alias files from '/src/' not '/build'. Make this change and it'll function properly.

Option 4

Another solution is to take advantage of the NODE_CONFIG environment variable with webpack.DefinePlugin. With this method you CAN still use get().

const config = require('config');

const webpackConfig = {
  //webpack plugins config
  plugins: [
    new webpack.DefinePlugin({
      //double stringify because node-config expects this to be a string
      'process.env.NODE_CONFIG': JSON.stringify(JSON.stringify(config)),
    }),
  ],
};

Option 5

If you're using node-config for node.js backend application, you can simply add it to externals, and read the config at the runtime. This will also allow usage of environment variables or local configuration files, if bundling them is not an option for your app. You will have to add the config files and node-config package to the bundle though.

module.exports = {
  // ...
  externals: {
    'config': 'config',
  }
};

Option 6

This plugin hooks into webpacks compilation to replace the config module with its environment equivalent. This eliminates the need to pull config in dynamically at runtime.

Installation

yarn add -D node-config-webpack

Usage

Your typical usage will replace the config module with an environment specific override. For this usage, just import the plugin and add it to webpack.

webpack.config.js

const NodeConfigWebpack = require('node-config-webpack');

module.exports = {
  entry: [
    './src/index.js'
  ],
  plugins: [
    new NodeConfigWebpack()
  ]
}

Options

Env

This option will inject your configuration into process.env automatically. However, it expects a root-level list of key-pair items, similar to an .env file. Additionally all keys will be coerced into uppercase to match process.env convention.

webpack.config.js

const NodeConfigWebpack = require('node-config-webpack');

module.exports = {
  entry: [
    './src/index.js'
  ],
  plugins: [
    new NodeConfigWebpack({
      env: true,
    })
  ]
}

Example:

console.log('Configuration version is', process.env.VERSION);

If you want the config added to process.env without any coercion you can use a string for the env option:

webpack.config.js

const NodeConfigWebpack = require('node-config-webpack');

module.exports = {
  entry: [
    './src/index.js'
  ],
  plugins: [
    new NodeConfigWebpack({
      env: 'CONFIG',
    })
  ]
}

You can then reference your config from process.env.<your_key>.

Example:

console.log('Configuration is', process.env.CONFIG);

Constant

This option will replace any reference to the variable CONFIG with the generated equivalent.

webpack.config.js

const NodeConfigWebpack = require('node-config-webpack');

module.exports = {
  entry: [
    './src/index.js'
  ],
  plugins: [
    new NodeConfigWebpack({
      constant: true,
    })
  ]
}

Example:

console.log('Configuration version is', CONFIG.version);

You can use a custom constant variable by passing a string as the constant value.

webpack.config.js

const NodeConfigWebpack = require('node-config-webpack');

module.exports = {
  entry: [
    './src/index.js'
  ],
  plugins: [
    new NodeConfigWebpack({
      constant: 'customValue',
    })
  ]
}

Example:

console.log('Configuration version is', customValue.version);

Known Conflicts

If you are using webpack-node-externals in your webpack configuration, add config to the allowlist. This will allow node-config-webpack to work as expected.

Example:

const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
const NodeConfigWebpack = require('node-config-webpack');

process.env.NODE_ENV = slsw.lib.serverless.service.provider.environment.NODE_ENV;

module.exports = {
  entry: slsw.lib.entries,
  target: 'node',
  mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
  externals: [nodeExternals({
    allowlist: ['config']
  })],
  plugins: [
    new NodeConfigWebpack(),
  ]
};