Advanced Webpack Configuration Techniques and Tips

The article presents advanced Webpack configuration strategies—including programmatic Node‑API builds, streamlined loader setups, global module injection and environment definitions, commons chunk extraction, DLL bundling, on‑demand code splitting, UglifyJS minification, and server‑side bundling—to help developers efficiently manage complex projects.

Tencent Music Tech Team
Tencent Music Tech Team
Tencent Music Tech Team
Advanced Webpack Configuration Techniques and Tips

The article shares practical tips and key configurations accumulated from using Webpack in projects, aiming to help developers avoid dealing with module organization, loading, transformation, merging, minification, and compatibility issues.

1. Complex project configuration (Node API)

For complex projects (e.g., isomorphic apps) you can generate configurations programmatically using the Node API instead of static config files. A typical build script looks like this:

var webpack = require('webpack');
var configGen = require("./config.generator");
// Generate custom config from command‑line arguments
var config = configGen(options);
var compiler = webpack(config);
compiler.run(function(err, stats) {
  if (err) {
    console.err(err);
  } else {
    console.log(stats.toString({
      colors: true
    }));
  }
});

Then add a script entry in package.json:

{
  "scripts": {
    "build": "node ./build.js"
  }
}

Run it with npm run build. You can also use webpack-dev-server for a local development server.

2. Loader configuration

Place common loaders in the configuration to keep source code clean. Example for handling .jsx files with Babel:

module: {
  loaders: [
    {
      test: /\.jsx$/,
      include: path.resolve(__dirname, "lib"),
      loader: "babel-loader",
      query: {
        presets: ["react", "es2015"],
        plugins: ["syntax-object-rest-spread", "transform-object-rest-spread"],
        cacheDirectory: true
      }
    }
  ]
}

If a loader must run before others, use module.preLoaders. To alias custom loaders, configure resolveLoader.alias:

resolveLoader: {
  alias: {
    "seajs-loader": path.resolve(__dirname, "./web_modules/seajs-loader.js")
  }
}

When loaders are located outside the project root, set resolveLoader.root to the default location:

resolveLoader: {
  // specify default loader path
  root: path.resolve(__dirname, "./node_modules")
}

3. Global modules and environment variables

Use ProvidePlugin to automatically inject modules like jQuery:

plugins: [
  new webpack.ProvidePlugin({
    $: "jquery",
    jQuery: "jquery"
  })
]

Use DefinePlugin to embed static constants or environment‑specific values at compile time:

plugins: [
  new webpack.DefinePlugin({
    "process.env": {
      NODE_ENV: JSON.stringify(options.dev ? 'development' : 'production')
    },
    "__SERVER__": isServer ? true : false
  })
]

4. Common chunk extraction

For multi‑entry projects, extract shared libraries with CommonsChunkPlugin:

entry: {
  a: "./a.js",
  b: "./b.js",
  common1: [
    "./lib/common.js",
    "react",
    "react-dom",
    "redux",
    "react-redux",
    "redux-thunk",
    "react-router",
    "react-router-redux"
  ]
},
plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    names: ['common1'],
    minChunks: Infinity
  })
]

5. DllPlugin and DllReferencePlugin

Separate rarely‑changed third‑party libraries into a DLL bundle:

var webpack = require('webpack');
var path = require('path');
module.exports = {
  entry: {
    vendor: ["react", "react-dom", "redux", "react-redux", "redux-thunk", "react-router", "react-router-redux"]
  },
  output: {
    filename: '[name].dll.js',
    path: path.resolve(__dirname, './output/dll'),
    library: "[name]"
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.resolve(__dirname, './output/dll/[name]-manifest.json'),
      name: "[name]"
    }),
    new webpack.optimize.UglifyJsPlugin({ minimize: true, output: { comments: false } })
  ]
};

Build it with webpack --config=config.dll.js. In the main project, reference the DLL via DllReferencePlugin:

plugins: [
  new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: require('./output/dll/vendor-manifest.json')
  })
]

6. Code splitting / on‑demand loading

Use require.ensure to create split chunks that are loaded only when needed:

require.ensure(["./c"], function(require) {
  var bbb = require("./b");
  console.log(bbb.foo);
}, 'chunk-one');

Only modules listed in the dependencies array are fetched; they are not executed until required. The complementary require.include can preload a module without executing it.

7. UglifyJS plugin

Configure minification and compression options:

plugins: [
  new webpack.optimize.UglifyJsPlugin({
    compress: { warnings: false },
    except: [],
    output: { comments: true }
  })
]

8. Server‑side bundling

When targeting Node, set target: "node", export with libraryTarget: "commonjs2", and exclude external modules via externals:

// Example snippet
target: "node",
externals: [/node_modules/],
output: {
  libraryTarget: "commonjs2",
  pathinfo: true
}

These settings keep native Node modules as require calls and prevent them from being bundled.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptConfigurationNode.jswebpackbuild toolsCode SplittingPlugins
Tencent Music Tech Team
Written by

Tencent Music Tech Team

Public account of Tencent Music's development team, focusing on technology sharing and communication.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.