13

In Grunt or Gulp, I used to define all the requirements myself, like: stuff should be minified only for production, livereload should be enabled only in dev server.

Webpack handles this on its own, via its -d and -p options, that toggle the loaders' minimize mode (most loaders ship with their relevant minifiers), the devtool and similar stuff (I don't know what exactly). Most of that "just works".

But on the other hand, there are some libraries that have a development and production mode. For example, React looks at process.NODE_ENV, and if it's production, it disables the propTypes checking (which will be later stripped off by minifier as dead code, thus reducing bundle size). In Webpack, a common way to do this is to use the DefinePlugin.

The problem is, that this plugin should be enabled only in the production build. Some people go as far as having 2 separate webpack configs because of that. This seems overkill, since most of the job is already done by webpack. I'd like to avoid this.

To find some better solution, I'd like to understand what exactly changes when I use the -d or -p option, and how does it affect all the loaders and plugins. I didn't find it documented anywhere. The existing documentation just mentions "debug mode" or "watch mode" without explaining what does it actually mean.

Note that I'm not asking for a do-this-and-that answer. A good, detailed explanation would be appreciated.

mik01aj
  • 11,928
  • 15
  • 76
  • 119

1 Answers1

14

Shortcuts

Like you said, -d is a shortcut for --debug --devtool source-map --output-pathinfo where:

  1. --debug activates debug mode for loaders and its behaviour depends on each loader. You can activate it via param { debug: true } in your webpack.config.js
  2. --devtool is basically allow to select type of sourcemaps for your files via param { devtool: "sourcemap" } or if you use webpack@2: { devtool: 'eval-cheap-module-source-map' }(See all options)
  3. --output-pathinfo will write original filepath into webpack's requires like this: __webpack_require__(/* ./src/containers/App/App.js */15).
    You can activate it via: { output: { pathinfo: true } }

Second shortcut, -p stands for --optimize-minimize --optimize-occurence-order where:

  1. --optimize-minimize will add webpack.optimize.UglifyJsPlugin into your module plugins which will minify your code (remove spaces, mangle variable names and other optimizations)
  2. --optimize-occurence-order will add webpack.optimize.OccurenceOrderPlugin to plugin list which will assign your most used dependencies lower ids, so code will be smaller.

    For example: you have imported react in every file and webpack will try to require it like that __webpack_require__(1); instead of __webpack_require__(1266);

Putting all together

So, in your case if you have webpack.config.js, you can change it like this:

var webpack = require('webpack');
var webpackConfig = {
   // here goes your base config
};

// -d shortcut analogue
if (process.env.NODE_ENV === 'development') {
  webpackConfig.debug = true;
  webpackConfig.devtool = 'sourcemap';
  webpackConfig.output.pathinfo = true;
}

// -p shortcut analogue
if (process.env.NODE_ENV === 'production') {
  webpackConfig.plugins.push(new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify('production')
  }));
  webpackConfig.plugins.push(new webpack.optimize.UglifyJsPlugin());
  webpackConfig.plugins.push(new webpack.optimize.OccurenceOrderPlugin());
}

module.exports = webpackConfig;

If you want to look at actual parsing of these params, look at https://github.com/webpack/webpack/blob/master/bin/convert-argv.js#L19

Alex Khorin
  • 341
  • 2
  • 4
  • Thank you. I have a few doubts, though: I see that [the `-p` flag sets `process.env.NODE_ENV`](https://github.com/webpack/webpack/blob/master/bin/convert-argv.js#L28), but how about `-d`? I also don't see `--optimize-occurence-order` in that source file. – mik01aj May 18 '16 at 08:25
  • Yeah, you right. They've removed `OccurenceOrderPlugin` for `-p` in webpack@2 and added new minimize mechanism through [`webpack.LoaderOptionsPlugin`](https://git.io/vr8CG). Defining `process.env.NODE_ENV` for development is a bit overhead on processing files since it replace variables in place with strings. Also it allows you to use NODE_ENV different from 'development' so you can mock/stub something for `NODE_ENV='test'` – Alex Khorin May 18 '16 at 10:29