Webpack: Как мы можем * условно использовать плагин?

В 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

Обратите внимание, что приведенный выше код похож на false в конце массива plugins (который испускает ту же ошибку):

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

Итак, вопрос: есть ли способ иметь условные плагины на Webpack? (кроме использования переменных?)

Ответы

Ответ 1

Я нажимаю на массив плагинов, учитывая условие в своем webpack.config.js

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

Ответ 2

Без переменных это будет выглядеть так:

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

Ответ 3

Я думаю, что самый чистый способ - создать несколько сборок. Если ваш 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);
});

Ответ 4

У вас может быть одна конфигурация 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;

Также см. Здесь полный пример.