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

Posted

技术标签:

【中文标题】Webpack 4:有条件地启用 PostCSS 插件【英文标题】:Webpack 4: Conditionally enabling PostCSS plugins 【发布时间】:2019-05-15 13:28:09 【问题描述】:

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

【问题讨论】:

【参考方案1】:

选项 1. 使用 webpack 合并

使用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 脚本调用它们。这个解决方案的问题是代码重复。

【讨论】:

...或者,您还创建一个包含公共代码的webpack.config.base.js 文件,然后从webpack.config.dev.jswebpack.config.prod.js 导入它。通过这种方式,您可以对所有方面进行精细控制,并且仍然不会安装可能导致冗余的额外软件包。 @Adriano 提供的解决方案也是有效的,我唯一担心他的解决方案是复制包 webpack-merge 的功能,但这个要点提供了一个非常简单的解决方案。 gist.github.com/ericclemmons/40a2783313d157d8b448 感谢您的回答。我没有看到这会如何改变 PostCSS 插件的加载,因为 postcss.config.js 不受合并 Webpack 配置的影响? @PeterB postcss.config.js 应该加载您的插件,并且在 webpack 配置文件中您应该有条件地选择它们的使用方式,在我的示例中,您可以看到 cssnano 仅用于生产。 【参考方案2】:

在你的postcss.config.js中你可以checking for the environment property:

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

【讨论】:

如果我想添加检查,检查 VueJs 全局状态是否包含值,你有什么建议,然后执行此操作,否则执行此操作等 看起来 webpack 插件数组不能包含布尔值:ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema. - configuration.plugins[0] should be one of these: object apply, … | function @Titenis 我认为这取决于版本。最初的答案是 2 年前写的,最新版本可能会有所变化。

以上是关于Webpack 4:有条件地启用 PostCSS 插件的主要内容,如果未能解决你的问题,请参考以下文章

带有 IE 11 后备的 css 模块、postcss + webpack

无法让 PostCSS 与 Webpack 一起使用

使用 React 的 className 属性和 PostCSS 有条件地在三元组中添加多个类

在 webpack 中从 cssnext 转换为 postcss-cssnext

深入浅出的webpack构建工具---PostCss

Webpack postcss loader,它的目的是啥?