【问题标题】:Webpack: How can we *conditionally* use a plugin?Webpack:我们如何*有条件地*使用插件?
【发布时间】:2016-03-24 16:56:25
【问题描述】:

在 Webpack 中,我有以下插件:

plugins: [
        new ExtractTextPlugin('styles.css'),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            drop_console: true,
        }),
    ]

我想将UglifyJsPlugin 仅应用于特定目标,所以我尝试使用我想要的条件:

plugins: [
        new ExtractTextPlugin('styles.css'),
        (TARGET === 'build') && new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            drop_console: true,
        }),
    ]

但是,这失败了,显示以下错误消息:

E:\myProject\node_modules\tapable\lib\Tapable.js:164
            arguments[i].apply(this);
                         ^

TypeError: arguments[i].apply is not a function

请注意,上面的代码类似于在plugins 数组末尾添加false(发出相同的错误):

plugins: [
        new ExtractTextPlugin('styles.css'),
        false
    ]

所以,问题是: 有没有办法在 Webpack 上有条件插件? (除了使用变量?)

【问题讨论】:

    标签: javascript webpack


    【解决方案1】:

    您可以使用这种使用the spread operator的语法

    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].css'
        }),
        ...(prod ? [] : [new BundleAnalyzerPlugin()]),
    ],
    

    【讨论】:

    • 使用 BundleAnalyzerPlugin,您可以有条件地将analyzerMode 设置为disabled,即。 new BundleAnalyzerPlugin({ analyzerMode: process.env.BUNDLE_ANALYZE ? 'server' : 'disabled' })
    【解决方案2】:

    给定我的webpack.config.js 中的条件,我推入插件数组

    const webpack = require('webpack');
    const ExtractTextPlugin = require("extract-text-webpack-plugin");
    
    module.exports = {
        entry: {
            ...
        },
        output: {
            ...
        },
        module: {
            rules: [
                ...
            ]
        },
        plugins: [
            new ExtractTextPlugin('styles.css'),
        ]
    };
    
    
    if (TARGET === 'build') {
        module.exports.plugins.push(
            new webpack.optimize.UglifyJsPlugin({
                compress: {
                    warnings: false
                },
                drop_console: true,
            }),
        );
    }
    

    【讨论】:

      【解决方案3】:

      没有变量它看起来像这样:

          plugins: [
              new ExtractTextPlugin('styles.css'),
              (TARGET === 'build') && new webpack.optimize.UglifyJsPlugin({
                  compress: {
                      warnings: false
                  },
                  drop_console: true,
              }),
          ].filter(function(plugin) { return plugin !== false; })
      

      【讨论】:

      【解决方案4】:

      你可以使用noop-webpack-plugin(noop表示没有操作):

      const isProd = process.env.NODE_ENV === 'production';
      const noop = require('noop-webpack-plugin');
      // ...
      plugins: [
          isProd ? new Plugin() : noop(),
      ]
      

      或没有额外模块的更好/推荐的解决方案:

      const isProd = process.env.NODE_ENV === 'production';
      // ...
      plugins: [
          isProd ? new Plugin() : false,
      ].filter(Boolean)
      // filter(Boolean) removes items from plugins array which evaluate to
      // false (so you can use e.g. 0 instead of false: `new Plugin() : 0`)
      

      【讨论】:

      • 大声笑,webpack 有一个适用于所有东西的插件 :)
      【解决方案5】:
      plugins: [
          new ExtractTextPlugin('styles.css'),
          (TARGET === 'build') && new webpack.optimize.UglifyJsPlugin({
              compress: {
                  warnings: false
              },
              drop_console: true,
          }),
      ].filter(Boolean)
      

      【讨论】:

        【解决方案6】:

        我认为最简洁的方法是设置多个构建。如果你的 webpack.config.js 导出一个配置对象数组而不是单个对象,webpack 会自动为每个对象进行构建。我有几个不同的构建,所以我将共享配置定义为变量,循环遍历构建之间变化的因素,并在循环中使用条件来检查它是哪个构建。例如:

        let allConfigs = [];
        let buildTypes = ['dev', 'optimized'];
        buildTypes.forEach( (type) => {
          let buildConfig = {};
          // ... other config
          buildConfig.plugins = [];
          if (type === 'optimized') {
            // add Uglify to plugins array
          }
          // ...other config
          allConfigs.push(buildConfig);
        });
        

        【讨论】:

          【解决方案7】:

          你可以有一个 webpack 配置,建立在另一个之上,并在后一个中添加一些插件(和/或更改输出名称等):

          这个webpack.release.config.js使用了一个webpack.config(开发版),但是使用了更多的插件...

          process.env.NODE_ENV = 'release';
          
          const config = require('./webpack.config'),
              webpack = require('webpack');
          
          config.output.filename = 'app.min.js';
          // use another plugin, compare to the basic version ←←←
          config.plugins.push(new webpack.optimize.UglifyJsPlugin({
              minimize: true
          }));
          
          module.exports = config;
          

          还有一个完整的例子see here

          【讨论】:

            【解决方案8】:

            您可以在 webpack 中使用 mode 参数将 development/production 值传递给 webpack 配置,然后有条件地加载插件。

            NPM 脚本:

            "start": "webpack --watch --mode=development",
            "build": "webpack --mode=production",
            

            webpack.config.js:

            module.exports = (env, argv) => {
              console.log("mode: ", argv.mode);
            
              const isDev = argv.mode === "development";
            
              const pluginsArr = [new CleanWebpackPlugin()];
            
              // load plugin only in development mode
              if (isDev) {
                pluginsArr.push(new ExtensionReloader({}));
              }
              return {
                entry: {},
                devtool: isDev ? "inline-source-map" : "", // generate source code only in development mode
            
                plugins: pluginsArr,
                output: {},
              };
            };
            

            【讨论】:

              猜你喜欢
              • 2019-05-15
              • 2016-04-09
              • 2018-07-22
              • 1970-01-01
              • 2021-02-25
              • 2013-01-12
              • 2019-01-03
              • 2020-01-07
              • 1970-01-01
              相关资源
              最近更新 更多