Webpack 4: условное включение плагинов PostCSS

Я интегрировал PostCSS в Webpack, используя отдельный файл postcss.config.js.

Я хочу включить cssnano при выполнении производственных сборок и отключить его для сборок разработки. Как я могу это сделать?

Вот мой 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;
}

Вот мой postcss.config.js

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

Во-вторых, рекомендуется ли отдельная postcss.config.js? Я вижу несколько примеров, где плагины PostCSS определены в webpack.config.js, и другие, где все это делается в отдельном файле.


person PeterB    schedule 14.12.2018    source источник


Ответы (2)



Вариант 1. Используйте слияние веб-пакетов

С помощью webpack-merge вы можете создавать условные конфигурации на основе NODE_ENV и объединять их в одна единственная конфигурация во время выполнения, преимущество в том, что вы не создаете дублирование кода и все можно сделать в одном файле, единственный недостаток - использование нового пакета.

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

Вариант 2. Использовать разные конфигурации

Можно создать два отдельных файла webpack.config.prod.js и webpack.config.dev.js и вызывать их с помощью разных сценариев npm. Проблема с этим решением заключается в дублировании кода.

person Daniel Doblado    schedule 16.12.2018
comment
...Или вы также создаете файл webpack.config.base.js, содержащий общий код, а затем импортируете его из файлов webpack.config.dev.js и webpack.config.prod.js. Таким образом, вы получаете детальный контроль над всеми аспектами и при этом не устанавливаете дополнительные пакеты, которые могут оказаться избыточными. - person Adriano; 16.12.2018
comment
Решение, предоставленное @Adriano, также верно, я беспокоился только о его решении, чтобы воспроизвести функциональность пакета webpack-merge, но этот смысл делает это довольно простым решением. gist.github.com/ericclemmons/40a2783313d157d8b448 - person Daniel Doblado; 16.12.2018
comment
Спасибо за ваш ответ. Я не вижу, как это меняет загружаемые плагины PostCSS, поскольку postcss.config.js не затрагивается слиянием конфигураций Webpack? - person PeterB; 17.12.2018
comment
@PeterB postcss.config.js должен загружать ваши плагины, а в файлах конфигурации веб-пакета вы должны условно выбрать, как они используются. В моем примере вы можете видеть, что cssnano используется только для производства. - person Daniel Doblado; 18.12.2018