title: Upgrade of Webpack 1 to 4 got so complicated
body: <p>I have been stuck with this upgrade since 2 days and I have made some progress.
  It is an old project and I have to take it a bit forward.</p>
  
  <p>This is my <code>webpack.config.js</code> file:</p>
  
  <pre><code>const path = require('path');
  const webpack = require('webpack');
  const HtmlWebpackPlugin = require('html-webpack-plugin');
  const ExtractTextPlugin = require('extract-text-webpack-plugin');
  const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
  const CleanWebpackPlugin = require('clean-webpack-plugin');
  //const validate = require('webpack-validator');
  const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
  
  const PATHS = {
    app: path.join(__dirname, 'src/js'),
    build: path.join(__dirname, 'build'),
    public: path.join(__dirname, 'src/public'),
    assets: path.join(__dirname, 'src/assets'),
    styles: [
      path.join(__dirname, 'src/assets/css/bootstrap.min.css'),
      path.join(__dirname, 'src/assets/css/font-awesome.min.css'),
      path.join(__dirname, 'src/assets/css/bootstrap-grid-rtl.css'),
      path.join(__dirname, 'src/assets/css/main.css'),
      path.join(__dirname, 'src/assets/css/PrintStyle.css'),
      path.join(__dirname, 'node_modules/react-dates/lib/css/_datepicker.css'),
      path.join(__dirname, 'node_modules/flag-icon-css/css/flag-icon.css'),
      path.join(__dirname, 'src/assets/css/react-datepicker.css'),
      path.join(__dirname, 'src/assets/css/tracker.css'),
  
    ]
  };
  
  const isDebug = !process.argv.includes('--release');
  
  module.exports = {
    optimization: {
      minimizer: [
        new UglifyJsPlugin({
          cache: true,
          parallel: true,
          uglifyOptions: {
            compress: false,
            ecma: 6,
            mangle: true
          },
          sourceMap: true
        })
      ], 
      splitChunks: {
        cacheGroups: {
            commons: {
                test: /[\\/]node_modules[\\/]/,
                name: 'vendor',
                chunks: 'all'
            }
        }
    }
    },
    entry: {
      app: ['babel-polyfill',PATHS.app],
      style: PATHS.styles
    },
    output: {
      path: PATHS.build,
      filename: 'js/[name].js',
    },
    resolve: {
      extensions: ['', '.js', '.jsx']
    },
  
    module: {
      rules: [
        {
          test: /\.jsx?$/,
          use: 
            {
              loader: 'babel-loader'
            }
          ,
          include: [
            path.resolve(__dirname, PATHS.app),
          ],
          query: {
            cacheDirectory: isDebug,
            babelrc: true,
            presets: ['latest', 'react',
              ...isDebug ? [] : [
                'react-optimize',
              ],
            ],
            plugins: [
              'transform-object-rest-spread',
              'transform-object-assign',
              [
                'react-intl', {
                  'messagesDir': './build/messages',
                  'enforceDescriptions': false
                }
              ]
            ]
          },
        },
        {
          test: /\.css$/,
          use: 
            {
              loader: ExtractTextPlugin.extract(
                'style-loader',
                `css-loader?${JSON.stringify({
                  importLoaders: 1,
                  sourceMap: true,
                  modules: true,
                  localIdentName: isDebug ? '[name]-[local]-[hash:base64:5]' : '[hash:base64:5]',
                  discardComments: { removeAll: true },
                })}`,
                'resolve-url-loader',
                'postcss-loader?pack=default'
              )
            }
          ,
          exclude: PATHS.styles,
        },
        {
          test: /\.css$/,
          use: [
            {
            loader:
              ExtractTextPlugin.extract(
                'style-loader',
                `css-loader?${JSON.stringify({
                  localIdentName: isDebug ? '[name]-[local]-[hash:base64:5]' : '[hash:base64:5]',
                  minimize: true,
                  discardComments: { removeAll: true },
                })}`,
                'resolve-url-loader'
              )
            }
          ],
          exclude: PATHS.app,
          include: PATHS.styles
        },
        {
          test: /\.sss$/,
          use: [
            {
              loader: 'style-loader'
            },
            {
              loader: 'css-loader'
            }
          ]
        },
        {
          test: /\.json$/,
          use: [
            {
              loader: 'json-loader'
            }
          ]
        },
        {
          test: /\.(eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
          use: [
            {
              loader:
                `file-loader?${JSON.stringify({
                  name: isDebug ? '/[path][name].[ext]?[hash:8]' : '/fonts/[hash:8].[ext]',
                })}`
            }
          ]
        },
        {
          test: /\.(ico|jpg|jpeg|png|gif)(\?.*)?$/,
          use: [
            {
              loader:
                `file-loader?${JSON.stringify({
                  name: isDebug ? '/[path][name].[ext]?[hash:8]' : '/images/[hash:8].[ext]'
                })}`
            }
          ]
        },
      ],
    },
  
    plugins: [
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
        'process.env.BROWSER': true,
        __DEV__: isDebug,
      }),
      new ExtractTextPlugin('[name].css', {allChunks: true}),
  
      new OptimizeCssAssetsPlugin({
        cssProcessorOptions: { discardComments: {removeAll: true } },
      }),
      new HtmlWebpackPlugin({
        title: 'GACA Portal',
        template: path.join(PATHS.public, 'index.ejs'),
        favicon:  path.join(PATHS.assets, 'images/favicon.ico'),
      }),
  
      ...isDebug? [
        new webpack.HotModuleReplacementPlugin({
          multiStep: true
        }),
  
      ] : [
        new CleanWebpackPlugin(PATHS.build, {
          root: process.cwd()
        }),
        new webpack.optimize.OccurrenceOrderPlugin(true),
        new webpack.optimize.DedupePlugin()
  
    ] //else ends
  ],
  
  // Don't attempt to continue if there are any errors.
  bail: !isDebug,
  cache: false,
  
  stats: {
    colors: true,
    reasons: isDebug,
    timings: true,
  },
  
  devtool: isDebug ? 'cheap-module-source-map' : false,
  devServer: {
    historyApiFallback: true,
    hot: true,
    inline: true,
    stats: 'errors-only',
    port: 3000,
    host: '0.0.0.0',
    publicPath: '/',
    contentBase: PATHS.build,
    proxy: {
      '/api/**': {
        target: 'http://localhost:8080',
        secure: false
      }
    }
  },
  
  /*postcss: [
    require('postcss-partial-import')(),
    require('postcss-url')(),
    require('postcss-custom-properties')(),
    require('postcss-custom-media')(),
    require('postcss-media-minmax')(),
    require('postcss-custom-selectors')(),
    require('autoprefixer')({
      browsers: [
        '&gt;1%',
        'last 4 versions',
        'Firefox ESR',
        'not ie &lt; 9', // React doesn't support IE8 anyway
      ],
    })
  ]*/
  
  };
  </code></pre>
  
  <p>Now I am trying to <code>npm start</code> but I still getting this error:</p>
  
  <pre><code>× ｢wds｣: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
   - configuration.module.rules[2].use should be one of these:
     non-empty string | function | object { ident?, loader?, options?, query? } | function | [non-empty string | function | object { ident?, loader?, options?, query? }]
     -&gt; Modifiers applied to the module when rule is matched
     Details:
      * configuration.module.rules[1].use should be a string.
      * configuration.module.rules[1].use should be an instance of function
      * configuration.module.rules[1].use.loader should be a string.
      * configuration.module.rules[1].use should be an instance of function
      * configuration.module.rules[1].use should be an array:
        [non-empty string | function | object { ident?, loader?, options?, query? }]
      * configuration.module.rules[2].use should be a string.
      * configuration.module.rules[2].use should be an instance of function
      * configuration.module.rules[2].use should be an object.
      * configuration.module.rules[2].use should be an instance of function
      * configuration.module.rules[2].use[0] should be a string.
      * configuration.module.rules[2].use[0] should be an instance of function
      * configuration.module.rules[2].use[0].loader should be a string.
   - configuration.resolve.extensions[0] should not be empty.
  </code></pre>
  
  <p>Any help would be very helpful</p>