24

I'm building a webpack automated workflow. I completed the development server. All of my development configurations are in webpack.config.js file.

Then, I add it into package.json script via 'dev':'webpack-dev-server'

How would one make a configuration for production in a separate file?

1
  • But what's the real advantage to have so many webpack configs? Commented Apr 1, 2022 at 22:21

5 Answers 5

26

There are some ways to accomplish that. Perhaps the simplest one is specifying the config file to use. Read more about webpack usage with config file.

Add another script in your package.json with:

"build": "webpack --config ./path-to/webpack.config.prod.js"

Place your production config object inside webpack.config.prod.js.


Another way is using the npm lifecycle event. Update your current webpack.config.js script to check the target script and decide which config to use:

const TARGET = process.env.npm_lifecycle_event;
if (TARGET === 'dev') {
   module.exports = require('./path-to/webpack.config.dev.js');
}
if (TARGET === 'build') {
   module.exports = require('./path-to/webpack.config.prod.js');
}

You can find previous approach in this webpack-demo project on GitHub.

Sign up to request clarification or add additional context in comments.

3 Comments

If the files have commonalities, how would one include the commonalities (i.e. a webpack.config.core.js)?
You might extract those commonalities into a third config file as you mentioned (e.g.: webpack.common.js). That script is then referenced and its config is extended with the environment specific parts. Hint: webpack-merge is commonly used for this task. Hope this comment answers part of your question. If not, feel free to create a question with more information and give me a reference to check it out.
But what's the real advantage to have so many webpack configs?
10

The npm module webpack-merge is a confortable way of having multiple configuration files in webpack. It allows to have a common configuration file and several other that "extend" from this one as the following example will show.

Installing

npm install webpack-merge

Common webpack config file

This would be where the common configurations between your other files are.

webpack.common.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  entry: "./src/index.js",
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: "Output Management",
      template: "src/index.html",
    }),
  ],
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
};

Extending files

I decided to use development and production configuration files for the example but any amount can be used.

webpack.dev.js

const path = require("path");

const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common, {
  mode: "development",
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    compress: true,
    port: 9000,
  },
});

webpack.prod.js

const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common, {
  mode: "production",
});

In both you import the merge function and use it to create your files without having to duplicate code. In your scripts you can simply call the extending configuration files like so.

package.json

...
"scripts": {
  "build": "webpack --config webpack.prod.js",
  "dev": "webpack serve --config webpack.dev.js"
},
...

3 Comments

But what's the real advantage to have so many webpack configs?
@Rainning It depends on the complexity of the app you are building. A dev build usually is bigger and heavier but it has better error support and warnings while a production environment is the other way around. You can't have both things the same time
@NeoZoom.lua wouldn't this be useful when trying to bundle the renderer and main side codes of an electron app separately as properties like "target, library, module.rules.exclude, externals and resolve will differ for both sides or am I missing something?
6

A few options:

  1. use webpack-merge

  2. use multiple configurations and choose between them using the --config-name option

  3. If you don't mind changing your webpack config object (module.exports) into a function as described here you could do something like this in your webpack.config.js:

    module.exports = (env, argv) => {
         return {
            //your config here, do something with the mode
               mode: env.mode
            };
        };
    

and pass the mode into your config by invoking webpack with the --env flag:

npx webpack --env mode=development

Or just add it to your package.json like this:

  "scripts": {
      "watch": "webpack --watch --env mode=development",
      "build": "webpack --env mode=production"
    }

Although if all you want is to toggle the mode you could just use the --mode flag

1 Comment

But what's the real advantage to have so many webpack configs?
2

In watch mode you can run webpack with NODE_ENV prefix from package.json, for example:

{
  ...
  "scripts": {
    "watch": "NODE_ENV=development webpack --watch",
    "build": "NODE_ENV=production webpack",
    ...
  }
}

and then use that preset (process.env.NODE_ENV) in webpack.config.js:

const mode = process.env.NODE_ENV;

const config = {
  mode,
  // ... common configuration
};

if (mode === 'development') {
  // update config object for development
} else if (mode === 'production') {
  // update config object for production
}

module.exports = config;

Comments

0

Since webpack config uses regular Node exports, you can import the base configuration, make any modifications, then export the modified version. This is basically the same as the webpack-merge approach, but without any dependencies (you'd have to manage any special merge logic yourself).

Simple example:

webpack.common.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/index.js",
  plugins: [
    new HtmlWebpackPlugin({
      title: "Output Management",
      template: "src/index.html",
    }),
  ],
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
};

webpack.dev.js:

const path = require("path");
const config = require("./webpack.common.js");

config.mode = "development";
config.devServer = {
    contentBase: path.join(__dirname, "dist"),
    compress: true,
    port: 9000,
};

module.exports = config;

... and so on and so forth ...

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.