Webpack 4: Conditionally enabling PostCSS plugins

Option 1. Use webpack merge

With webpack-merge, you can create conditional configurations based on the NODE_ENV and merge them in one single configuration at execution time, the advantage is that you don't create duplication of code and everything can be done in one file, the only disadvantage is using a new package.

const ENV = process.env.NODE_ENV

let Config = {

  //Other shared configurations by production and development

  plugins: [
    new webpack.ProgressPlugin(),
    new CopyWebpackPlugin([
      { from: 'public', to: 'public' },
    ])
  ]

}

if (ENV === 'production') {
  Config = merge(Config, {
    plugins: [
      new MiniCssExtractPlugin({
        filename: "public/styles.css"
      }),
      new OptimizeCSSAssetsPlugin({
        cssProcessor: cssnano,
        cssProcessorOptions: {
          parser: safe,
          discardComments: { removeAll: true }
        }
      })
    ],
    mode: 'production'
  })
}

if (ENV === 'development') {
  Config = merge(Config, {
    devtool: 'source-map',
    mode: 'development',
    plugins: [
      new webpack.HotModuleReplacementPlugin(),
      new webpack.NamedModulesPlugin(),
      new StyleLintPlugin(
        {
          emitErrors: false,
          configFile: '.stylelintrc',
          context: 'src',
          files: '**/*.pcss',
        },
      ),
    ]
  })
}

const WebpackConfig = Config

Option 2. Use different configurations

Two separated files webpack.config.prod.js and webpack.config.dev.js can be created and call them with different npm scripts. The problem with this solution is that there is a duplication of code.


In your postcss.config.js you can do checking for the environment property:

module.exports = ({ env }) => ({
  plugins: [
    require('postcss-import')(),
    require('postcss-url')(),
    require('autoprefixer')(),
    env === 'production' ? require('cssnano')({preset: 'default' })() : false,
  ]
})