In webpack 2 and 3, this can be configured much more cleanly.
Loaders can be passed to an array of loader objects. Each loader object can specify an options object, which acts as a webpack 1 query for this particular loader.
For example, using react-hot-loader and babel-loader , with babel-loader configured with some options in webpack 2/3
module: { rules: [{ test: /\.js$/, exclude: /node_modules/, use: [{ loader: 'react-hot-loader' }, { loader: 'babel-loader', options: { babelrc: false, presets: [ 'es2015-native-modules' 'stage-0', 'react' ] } }] }] }
For comparison, here is the same configuration in webpack 1 using the query string method.
module: { rules: [{ test: /\.js$/, exclude: /node_modules/, loaders: [ 'react-hot', 'babel-loader?' + 'babelrc=false,' + 'presets[]=es2015,' + 'presets[]=stage-0,' + 'presets[]=react' ] }] }
Notice the changed property names throughout the chain.
Also note that I changed the es2015 to es2015-native-modules in the babel-loader setup. This has nothing to do with the options specification, it's just that, including the es6 modules, you can use the webpack tree insert function introduced in v2. It can be left alone, and it will still work, but the answer will seem incomplete without indicating an obvious update :-)
Disclaimer: this is the same as my answer to a similar question , but this question has similar votes / views / google ratings, so I will post the answer here too.