tawreon
tawreon

Reputation: 184

webpack plugins loading depending on environment

I want to load two plugins to webpack: extract-text-webpack-plugin and babel-minify-webpack-plugin.babel-minify-webpack-plugin should be only loaded if the environment is in production. Currently I'm creating envPlugin array and pushing plugins, depending on the environment flag.

module.exports = (env) => {

  const isProduction = env === 'production';
  const CSSExtract = new ExtractTextPlugin('styles.css');
  const bundleJSMinifier = new MinifyPlugin();

  let envPlugins = [CSSExtract];

  if (isProduction) {
      envPlugins.push(bundleJSMinifier);
  }

  return {
    entry: ['babel-polyfill', './src/app.js'],
    output: {
      path: path.join(__dirname, 'public', 'dist'),
      filename: 'bundle.js'
    },
    module: {
      rules: [...]
    },
    plugins: envPlugins,
    devtool: isProduction ? 'source-map' : 'inline-source-map',
    devServer: {...}
  };
};

The question is there a better way to load plugins to webpack depending on environment I'm currently in.

Upvotes: 1

Views: 1026

Answers (1)

Bruno Paulino
Bruno Paulino

Reputation: 5780

You can split your production and development configuration in different files, put the common settings in a common file and use webpack-merge plugin to merge them in each env like this:

webpack.common.js

const webpack = require('webpack');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  mode: 'development',
  entry: __dirname + '/admin/app/frontend/entry.js',
  output: {
    path: __dirname + '/admin/public/compiled',
    filename: 'bundle.js'
  },
  resolve: {
      extensions: ['.js', '.jsx']
  },
  module: {
    rules: [

      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        include: __dirname + '/admin/app/frontend/',
        use: {
          loader: 'babel-loader'
        }
      },

      {
        test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
        loader: 'file-loader?name=fonts/[name].[ext]'
      },

      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader',
        ],
      },


      {
        test: /\.png$/,
        loader: "url-loader?mimetype=image/png"
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "styles.css",
    }),
    new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en|de)$/)
  ]

};

webpack.dev.js:

const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
    devtool: 'inline-source-map',
});

webpack.prod.js

const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production',
  plugins: [
      new UglifyJSPlugin({
          sourceMap: true
      })
  ]
});

and in my package.json I have specific commands for each env. npm watch for development and npm build for production. each of them points to the correct env file:

{
  "name": "my-app",
  "version": "1.0.0",
  "description": "my app desc",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "watch": "webpack --config webpack.dev.js --watch",
    "build": "webpack --config webpack.prod.js"
  },
  "repository": {
    "type": "git",
    "url": "https://repo-url"
  },
  "keywords": [
    "bpaulino",
    "bruno"
  ],
  "engines": {
    "node": "8.5.0"
  },
  "author": "Bruno Paulino",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "babel-plugin-react-transform": "^2.0.2",
    "babel-plugin-transform-es2015-destructuring": "^6.23.0",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-plugin-transform-react-display-name": "^6.5.0",
    "babel-polyfill": "^6.7.4",
    "babel-preset-env": "^1.6.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    ...
    "webpack": "^4.16.5",
    "webpack-cli": "^3.1.0",
    "webpack-merge": "^4.1.0"
  },
  "dependencies": {
    "axios": "^0.16.2",
    "babel-plugin-prismjs": "^1.0.2",
    "bootstrap-sass": "^3.3.7",
    "history": "^4.6.3",
    "lodash": "^4.17.4",
    "marked": "^0.5.0",
    "moment": "2.22.2",
    "node-uuid": "^1.4.8",
    "normalizr": "^3.2.3",
    "npm": "^6.2.0",
    "prismjs": "^1.15.0",
    "prop-types": "^15.6.2",
    "react": "^16.4.1",
    ...
  }
}

using the webpack-merge plugin you can override any settings defined in the common configuration.

Upvotes: 1

Related Questions