Passing command line arguments to webpack.config.js

Viewed 48538

I have a simple webpack.config.js

module.exports = {
  entry: "./app.js",
  output: {
    filename: "bundle.js"
  },
}

And I want to pass the values for entryand output through command line arguments. Is that possible and how would I do that?

7 Answers

You can provide custom parameters by passing environment variables on the command line. The syntax for this has changed between version 4 and 5 of Webpack. For this example, you would call:

For Webpack 5:

webpack --env entry='./app.js' --env output='bundle.js'

For Webpack 4:

webpack --env.entry='./app.js' --env.output='bundle.js'

For both versions, you can then access the environment variables in your Webpack config by doing

module.exports = env => ({
  entry: env.entry,
  output: {
    filename: env.output
  },
});

You can also pass multiple key-value pairs to you config using --env=key=value:

webpack --env=mode=production --env=branch=develop

or (for development with webpack-dev-server):

webpack serve --env=mode=production --env=branch=develop

webpack.config.js would look like this:

module.exports = (env) => {
  const mode = env.mode === 'prod' ? 'dev';
  const branch = env.branch ? env.branch : 'develop';

  return {
    entry: mode === 'prod' ? './app.js': 'app-dev.js',
    output: {
      filename: 'bundle.js',
      path: 'dist/' + branch),
    },
  }
}

All values passed this way are available as an object in the config which makes it easy to use them.

{ 
  WEBPACK_BUNDLE: true,
  mode: 'production',
  branch: 'feature-x',
  foo: 'bar'
}

You can use the --env CLI argument to pass arbitrary parameters to the config.

For example, the following command:

webpack --env entry=./entry.js --env output=./output.js

Will produce the following env object:

{entry: './entry.js', output: './output.js'}

Which you can then use in your config like so:

module.exports = env => ({
  entry: env.entry,
  output: {
    filename: env.output
  },
});

Read more here: Webpack - Environment Variables

The easiest way, in my opinion, to pass arguments is to use Node. Webpack being the one receiving the arguments, you can save your command line arguments in a dedicated environment variable (which exists only within the session):

// webpack.config.js 
process.env.MY_APPLICATION_NAME_ARGS = JSON.stringify(process.argv)

export default {
...

Then in your main.js (anywhere where you want to parse them), you retrieve your command line arguments from your dedicated environment variable.

// main.js
const myArgs = JSON.parse(env.MY_APPLICATION_NAME_ARGS )

As you'll be retrieving all of the arguments you passed to Webpack, using this, you'll be able to use any node modules (like yargs for instance) painlessly to parse them (or do it manually of course).

So you'll be able to do things like these without any issues:

webpack ... --opt1 the_value --custom1 something
yarn run dev --opt1 the_value --custom1 something

etc.

I have a solution for those using ES Modules for Webpack configuration. When we log process.argv there is a array of arguments which we can check if the one we needed there or not.

For example:

{
  "scripts": {
    "watch:foo": "webpack --watch --env foo"
  },
}

So for the command above, all we need to do is check if process.argv has the argument we pass:

const isFoo = process.argv.indexOf('foo') > -1;
Related