Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack 4: Conditionally enabling PostCSS plugins

I've integrated PostCSS into Webpack, using a separate postcss.config.js file.

I want to enable cssnano when doing production builds, and disable it for development builds. How can I do this?

Here is my webpack.config.js

const webpack = require('webpack');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');

const path = require('path');

module.exports = (env, argv) =>
{
    //const isProduction = (process.env.WEBPACK_MODE === 'production')
    const isProduction = argv.mode === 'production' || process.env.NODE_ENV === 'production';

    const config = {
        entry: './src/index.js',
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: '[name].[contenthash].js',
            chunkFilename: '[name].[contenthash].js'
        },
        devtool: 'source-map',
        module: {
            rules: [
                {
                    test: /\.(sa|sc|c)ss$/,
                    use: [
                        // fallback to style-loader in development
                        //process.env.NODE_ENV !== 'production' ? 'style-loader' : MiniCssExtractPlugin.loader,
                        {
                            loader: MiniCssExtractPlugin.loader,
                            options: {
                                sourceMap: true
                            }
                        },
                        //'css-loader?-url',
                        {
                            loader: 'css-loader',
                            options: {
                                minimize: true,
                                sourceMap: true,
                                url: false
                            }
                        },
                        {
                            loader: 'postcss-loader',
                            options: {
                                sourceMap: true
                            }
                        },
                        {
                            loader: 'resolve-url-loader',
                            options: {
                                sourceMap: true,
                                debug: false
                            }
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                sourceMap: true,
                                outputStyle: 'compressed',
                                sourceMapContents: false
                            }
                        }
                    ]
                }
            ]
        },

        plugins: [
            new CleanWebpackPlugin('dist', {
                watch: true
            }),
            new MiniCssExtractPlugin({
                // Options similar to the same options in webpackOptions.output
                // both options are optional
                filename: isProduction ? "live.[contenthash].css" : "live.css",
                chunkFilename: "[name].[contenthash].css"
            }),
            new ManifestPlugin()
        ]
    }

    return config;
}

Here is my postcss.config.js

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

Secondly, is a separate postcss.config.js recommended? I see some examples where the PostCSS plugins are defined in webpack.config.js, and others where it's all done in the separate file.

like image 369
PeterB Avatar asked Dec 14 '18 09:12

PeterB


People also ask

How to install PostCSS in Webpack V4?

For Webpack v4, you have to install postcss-loader v4. To begin, you'll need to install postcss-loader and postcss: npm install --save-dev postcss-loader postcss Then add the plugin to your webpack config.

How to install PostCSS in WordPress with PostCSS?

First of all, you need to install the PostCSS loader and a sensible PostCSS configuration to your dev dependencies: Next, create a postcss.config.js file where you will reference all your PostCSS plugins. In this case, we will use the most commonly used PostCSS plugin called postcss-preset-env which enables sensible defaults:

What is PostCSS-loader in Webpack?

postcss-loader | webpack. webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset. webpack is a module bundler.

What are the dependencies of a Webpack plugin?

The dependencies are necessary for webpack to understand when it needs to run recompilation on the changed files. (Recommended). The plugin may emit messages in result.messages.


1 Answers

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.

like image 109
Daniel Doblado Avatar answered Sep 24 '22 05:09

Daniel Doblado