繁体   English   中英

Webpack:我们如何*有条件地*使用插件?

[英]Webpack: How can we *conditionally* use a plugin?

在 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 上使用条件插件? (除了使用变量?)

您可以使用这种使用扩展运算符的语法

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

我在webpack.config.js给定条件推送到 plugins 数组

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,
        }),
    );
}

如果没有变量,它将如下所示:

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

我认为最干净的方法是设置多个构建。 如果您的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);
});
plugins: [
    new ExtractTextPlugin('styles.css'),
    (TARGET === 'build') && new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        },
        drop_console: true,
    }),
].filter(Boolean)

你可以有一个 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;

请参阅此处以获取完整示例。

您可以在 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: {},
  };
};

可以使用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`)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM