Webpack 4:有条件地启用PostCSS插件

8

我已将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中定义的,而其他示例则在单独的文件中完成。
2个回答

4

选项1. 使用webpack-merge

使用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.jswebpack.config.dev.js,并使用不同的npm脚本来调用它们。这种解决方案的问题在于存在代码重复。


1
或者,您还可以创建一个名为webpack.config.base.js的文件,其中包含公共代码,然后从webpack.config.dev.jswebpack.config.prod.js中导入它。通过这种方式,您可以对所有方面进行细粒度控制,同时不安装可能会导致冗余的其他软件包。 - Adriano
@Adriano 提供的解决方案也是有效的,我对他的解决方案唯一的担忧是要复制 webpack-merge 包的功能,但这个代码片段提供了一个相当简单的解决方案。https://gist.github.com/ericclemmons/40a2783313d157d8b448 - Daniel Doblado
谢谢您的回答。我不明白这如何改变加载哪些PostCSS插件,因为postcss.config.js不受合并Webpack配置的影响? - PeterB
@PeterB postcss.config.js 应该加载你的插件,而在 webpack 配置文件中,你应该有条件地选择它们的使用方式。在我的例子中,你可以看到 cssnano 只用于生产环境。 - Daniel Doblado

3
在你的postcss.config.js文件中,你可以进行环境属性的检查
module.exports = ({ env }) => ({
  plugins: [
    require('postcss-import')(),
    require('postcss-url')(),
    require('autoprefixer')(),
    env === 'production' ? require('cssnano')({preset: 'default' })() : false,
  ]
})

如果我想添加一个检查,检查VueJs全局状态是否包含值this,然后执行这个操作,否则执行那个操作,你有什么建议? - Hanzla Habib
似乎webpack插件数组不能包含布尔值:- configuration.plugins [0]应该是以下之一: object { apply, … } | function``` - Titenis
@Titenis 我认为这取决于版本。原始答案是两年前写的,最新版本可能会有所改变。 - sergdenisov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接