How to read mode in webpack.config.js
Tags: webpack, javascript
Published: 2021-10-22 16:58:36

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](https://how-to.dev/how-to-quickly-start-a-webpack-project). 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`:

```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](https://webpack.js.org/configuration/devtool/#devtool), 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](https://webpack.js.org/configuration/configuration-types/#exporting-a-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`:
```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 default `npm 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:
```SH
$  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;
```SH
$ 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
* [source code repo](https://github.com/how-to-js/webpack-read-mode)
* [my webpack video course](https://bit.ly/webpack-course-read-mode)

# 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.