Felix
Felix

Reputation: 5619

webpack config how to change plugins depending on environment

Hi is it possible to make plugins in webpack configuration depending on environement?

plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NamedModulesPlugin(),
        new webpack.LoaderOptionsPlugin({
            debug: true
        }),
        new CopyWebpackPlugin([
            {from: 'src/www/'}
        ])
        // new BundleAnalyzerPlugin(),
        // new CompressionPlugin({
        //     algorithm: 'gzip',
        //     test: /\.js$|\.css$|\.html$/
        // }),
        // new UglifyJsPlugin({
        //     test: /\.js(\?.*)?$/i
        // })
    ]

The commented ones should only be used if I bundle it with NODE_ENV=production

Thanks in advance

Upvotes: 9

Views: 6971

Answers (5)

snnsnn
snnsnn

Reputation: 13600

I would go with rest operator for cleaner look:

const isDev = process.env.NODE_ENV !== 'production';

const plugins = isDev ? [
  new ForkTsCheckerWebpackPlugin(),
] : [
  new BundleAnalyzerPlugin({
    openAnalyzer: process.env.OPEN_ANALYZER === 'true',
  }),
  new webpack.EnvironmentPlugin({
    NODE_ENV: 'production',
    DEBUG_PROD: false,
    START_MINIMIZED: false,
  }),
]

Then inside the configuration file:

plugins: [
     ...plugins,
     new CopyWebpackPlugin({
      patterns: [
        {
          from: 'source',
          to: 'destination',
        },
      ],
    }),
  ],

Now we don't need those nasty comparisons.

Upvotes: 1

Bagaskara
Bagaskara

Reputation: 881

this is how i use plugin only in production

// Load this plugin only when running webpack in a production environment
if (process.env.NODE_ENV == 'production') {
  module.exports.plugins.push(
    new BundleAnalyzerPlugin({
      analyzerPort: 4000
    }),
  );
}

Upvotes: 1

Hyyan Abo Fakher
Hyyan Abo Fakher

Reputation: 3537

You can have A file config per environment

webpack
├── base.config.js
└── prod.config.js
// base.config.js
const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.EnvironmentPlugin([
      'NODE_ENV',
    ]),
  ],
};
// prod.config.js
const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const baseConfig = require('./base.config.js');

module.exports = merge(baseConfig, {
  ....
  plugins: [
    // Minify JS
    new UglifyJsPlugin({
      sourceMap: false,
      compress: true,
    })
  ],
});

then in your package.json

"scripts": {
  "build": "NODE_ENV=production webpack --config webpack/prod.config.js",
  "start": "NODE_ENV=development webpack-dev-server --config webpack/dev.config.js"
}

Upvotes: 1

Joseph
Joseph

Reputation: 692

Based on your requirements, add the plugins if the env is production else return false, and filter the array based on the Boolean, but the preferred way is to create a different file for the different env, it will be much cleaner approach.

plugins: [
    new webpack.HotModuleReplacementPlugin(),
        new webpack.NamedModulesPlugin(),
        new webpack.LoaderOptionsPlugin({
            debug: true
        }),
        new CopyWebpackPlugin([
            {from: 'src/www/'}
        ])
        NODE_ENV==='production' ? new BundleAnalyzerPlugin() : false,
        NODE_ENV==='production' ? new CompressionPlugin({
             algorithm: 'gzip',
             test: /\.js$|\.css$|\.html$/
        }) : false,
        NODE_ENV==='production' ?  new UglifyJsPlugin({
             test: /\.js(\?.*)?$/i
        }) : false
 ].filter(Boolean)

Upvotes: 13

Nick Schmidt
Nick Schmidt

Reputation: 1527

Using your example I would prefer something like this:

plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.LoaderOptionsPlugin({
        debug: true
    }),
    new CopyWebpackPlugin([
        {from: 'src/www/'}
    ])
    NODE_ENV === 'production' && new BundleAnalyzerPlugin(),
    NODE_ENV === 'production' && new CompressionPlugin({
        algorithm: 'gzip',
        test: /\.js$|\.css$|\.html$/
    }),
    NODE_ENV === 'production' && new UglifyJsPlugin({
        test: /\.js(\?.*)?$/i
    })
].filter(n => n)

or if you prefer ES5:

plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.LoaderOptionsPlugin({
        debug: true
    }),
    new CopyWebpackPlugin([
        {from: 'src/www/'}
    ])
    NODE_ENV === 'production' && new BundleAnalyzerPlugin(),
    NODE_ENV === 'production' && new CompressionPlugin({
        algorithm: 'gzip',
        test: /\.js$|\.css$|\.html$/
    }),
    NODE_ENV === 'production' && new UglifyJsPlugin({
        test: /\.js(\?.*)?$/i
    })
].filter(function (plugin) { return plugin; })

What this snippet does is adding a conditional (NODE_ENV === 'production') to the array, which is simply telling the JS compiler to either write false or the right-hand code to the array. The filter function on the other hand is only saying, filter out stuff that is false or false-ish.

Let's assume we are on NODE_ENV = 'development', our plugins would look like this:

[HotModuleReplacementPlugin, NamedModulesPlugin, LoaderOptionsPlugin, CopyWebpackPlugin, false, false, false].filter(...)

after the filter has made it's job, we are having this one:

[HotModuleReplacementPlugin, NamedModulesPlugin, LoaderOptionsPlugin, CopyWebpackPlugin]

If we now assume we are on NODE_ENV = 'production', our plugins would look like this:

[HotModuleReplacementPlugin, NamedModulesPlugin, LoaderOptionsPlugin, CopyWebpackPlugin, BundleAnalyzerPlugin, CompressionPlugin, UglifyJsPlugin].filter(...)

after the filter has made it's job, we are having this one:

[HotModuleReplacementPlugin, NamedModulesPlugin, LoaderOptionsPlugin, CopyWebpackPlugin, BundleAnalyzerPlugin, CompressionPlugin, UglifyJsPlugin]

Upvotes: 2

Related Questions