Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 919
Felix Avatar asked May 20 '19 13:05

Felix


People also ask

Does webpack set Node_env?

NODE_ENV is not set to 'production' within the build script webpack.

Is webpack configuration based?

Webpack can be configured by a config file. Plugins modify and extend the webpack build process. Loaders instruct webpack how to handle different file types. The clean-webpack-plugin can be used to remove old build artifacts from the dist directory.


3 Answers

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)
like image 164
Joseph Avatar answered Oct 07 '22 17:10

Joseph


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]
like image 3
Nick Schmidt Avatar answered Oct 07 '22 18:10

Nick Schmidt


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"
}
like image 1
Hyyan Abo Fakher Avatar answered Oct 07 '22 18:10

Hyyan Abo Fakher