How to read mode in webpack.config.js

If you want to cover all build use cases with one webpack.config, at some point, you will want to start tweaking the configuration based on the use case. This short guide will show you how to do it with --mode=production as an example.

Starting point

I start the example with code generated by my degit generator. It comes with no webpack config - it has everything set up to work with the default values.

Objective

First, I want to support two types of build

  • default, with --mode=none, for testing locally unobfuscated code
  • production, with --mode=production, meant for deploying

In the real-world project, you can find yourself with similar requirements - dedicated build for unit or e2e tests, etc.

package.json

The first step is to define 2nd build script in package.json:

{
  ...
  "scripts": {
    ...
    "build": "webpack --mode=none",
    "build:production": "webpack --mode=production"
  },
}

Use case for reading the mode

One of the reasons we would like to differentiate the build is the source map setting controlled by the devtool flag on the configuration object. There are more than 25 possible values described in its documentation, and some are fast & optimized for speed in the development workflow, while others are slower but a better fit for deploying on the production.

Configuration function

Webpack works with many approaches to the configuration file. One of the allowed forms is configuration function. This approach is a bit more complicated than configuration objects, but conveniently it will enable the behavior we want to have here.

webpack.config.js:

module.exports = function (env, argv) {
  return {
    devtool: argv.mode === "production" ? "source-map" : "eval",
  };
};
  • argv is provided with all the values that we have in the webpack call
  • argv.mode is equal "production" when we run npm run build:production" and"none"for the defaultnpm run build
  • "source-map" creates a slow but high-quality source map recommended the production use
  • "eval" is quick but meant for development only

Working code

So in the end, we have:

$  npm run build               

> webpack-starter@1.0.0 build /home/marcin/workspace/github/webpack-read-mode
> webpack --mode=none

asset main.js 1.1 KiB [compared for emit] (name: main)
./src/index.js 23 bytes [built] [code generated]
webpack 5.59.1 compiled successfully in 66 ms

$ ls dist
main.js

big, one file for the local build;

$ npm run build:production

> webpack-starter@1.0.0 build:production /home/marcin/workspace/github/webpack-read-mode
> webpack --mode=production

asset main.js 55 bytes [emitted] [minimized] (name: main) 1 related asset
./src/index.js 23 bytes [built] [code generated]
webpack 5.59.1 compiled successfully in 170 ms

$ ls dist
main.js  main.js.map

And smaller main.js & an additional file with a source map for the production build.

Links

Summary

I hope you find this guide useful for the projects you are working on. If you are interested in the other strategies for managing different build use-case side-to-side, let me know in the comments.