Gathering detailed insights and metrics for webpack-chain
Gathering detailed insights and metrics for webpack-chain
Gathering detailed insights and metrics for webpack-chain
Gathering detailed insights and metrics for webpack-chain
@types/webpack-chain
TypeScript definitions for webpack-chain
markdown-it-chain
A chaining API like webpack-chain but for markdown-it.
webpack-5-chain
[![NPM version][npm-image]][npm-url] [![NPM downloads][npm-downloads]][npm-url] [![CI Status][ci-image]][ci-url]
webpack-chain-5
[![NPM version][npm-image]][npm-url] [![NPM downloads][npm-downloads]][npm-url] [![CI Status][ci-image]][ci-url]
A chaining API to generate and simplify the modification of Webpack configurations.
npm install webpack-chain
Typescript
Module System
Min. Node Version
JavaScript (90.25%)
TypeScript (9.75%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MPL-2.0 License
3,192 Stars
246 Commits
233 Forks
24 Watchers
7 Branches
32 Contributors
Updated on Jul 05, 2025
Latest Version
6.5.1
Package Id
webpack-chain@6.5.1
Size
27.21 kB
Published on
Jul 25, 2020
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
Use a chaining API to generate and simplify the modification of webpack version 2-4 configurations.
This documentation corresponds to v6 of webpack-chain. For previous versions, see:
Note: while webpack-chain is utilized extensively in Neutrino, this package is completely standalone and can be used by any project.
webpack's core configuration is based on creating and modifying a potentially unwieldy JavaScript object. While this is OK for configurations on individual projects, trying to share these objects across projects and make subsequent modifications gets messy, as you need to have a deep understanding of the underlying object structure to make those changes.
webpack-chain
attempts to improve this process by providing a chainable or
fluent API for creating and modifying webpack configurations. Key portions
of the API can be referenced by user-specified names, which helps to
standardize how to modify a configuration across projects.
This is easier explained through the examples following.
webpack-chain
requires Node.js v6.9 and higher. webpack-chain
also
only creates configuration objects designed for use in webpack versions 2, 3,
and 4.
You may install this package using either Yarn or npm (choose one):
Yarn
1yarn add --dev webpack-chain
npm
1npm install --save-dev webpack-chain
Once you have webpack-chain
installed, you can start creating a
webpack configuration. For this guide, our example base configuration will
be webpack.config.js
in the root of our project directory.
1// Require the webpack-chain module. This module exports a single 2// constructor function for creating a configuration API. 3const Config = require('webpack-chain'); 4 5// Instantiate the configuration with a new API 6const config = new Config(); 7 8// Make configuration changes using the chain API. 9// Every API call tracks a change to the stored configuration. 10 11config 12 // Interact with entry points 13 .entry('index') 14 .add('src/index.js') 15 .end() 16 // Modify output settings 17 .output 18 .path('dist') 19 .filename('[name].bundle.js'); 20 21// Create named rules which can be modified later 22config.module 23 .rule('lint') 24 .test(/\.js$/) 25 .pre() 26 .include 27 .add('src') 28 .end() 29 // Even create named uses (loaders) 30 .use('eslint') 31 .loader('eslint-loader') 32 .options({ 33 rules: { 34 semi: 'off' 35 } 36 }); 37 38config.module 39 .rule('compile') 40 .test(/\.js$/) 41 .include 42 .add('src') 43 .add('test') 44 .end() 45 .use('babel') 46 .loader('babel-loader') 47 .options({ 48 presets: [ 49 ['@babel/preset-env', { modules: false }] 50 ] 51 }); 52 53// Create named plugins too! 54config 55 .plugin('clean') 56 .use(CleanPlugin, [['dist'], { root: '/dir' }]); 57 58// Export the completed configuration object to be consumed by webpack 59module.exports = config.toConfig();
Having shared configurations is also simple. Just export the configuration
and call .toConfig()
prior to passing to webpack.
1// webpack.core.js 2const Config = require('webpack-chain'); 3const config = new Config(); 4 5// Make configuration shared across targets 6// ... 7 8module.exports = config; 9 10// webpack.dev.js 11const config = require('./webpack.core'); 12 13// Dev-specific configuration 14// ... 15module.exports = config.toConfig(); 16 17// webpack.prod.js 18const config = require('./webpack.core'); 19 20// Production-specific configuration 21// ... 22module.exports = config.toConfig();
One of the core API interfaces in webpack-chain is a ChainedMap
. A
ChainedMap
operates similar to a JavaScript Map, with some conveniences for
chaining and generating configuration. If a property is marked as being a
ChainedMap
, it will have an API and methods as described below:
Unless stated otherwise, these methods will return the ChainedMap
, allowing
you to chain these methods.
1// Remove all entries from a Map. 2clear()
1// Remove a single entry from a Map given its key. 2// key: * 3delete(key)
1// Fetch the value from a Map located at the corresponding key. 2// key: * 3// returns: value 4get(key)
1// Fetch the value from a Map located at the corresponding key.
2// If the key is missing, the key is set to the result of function fn.
3// key: *
4// fn: Function () -> value
5// returns: value
6getOrCompute(key, fn)
1// Set a value on the Map stored at the `key` location. 2// key: * 3// value: * 4set(key, value)
1// Returns `true` or `false` based on whether a Map as has a value set at a 2// particular key. 3// key: * 4// returns: Boolean 5has(key)
1// Returns an array of all the values stored in the Map. 2// returns: Array 3values()
1// Returns an object of all the entries in the backing Map 2// where the key is the object property, and the value 3// corresponding to the key. Will return `undefined` if the backing 4// Map is empty. 5// This will order properties by their name if the value is 6// a ChainedMap that used .before() or .after(). 7// returns: Object, undefined if empty 8entries()
1// Provide an object which maps its properties and values 2// into the backing Map as keys and values. 3// You can also provide an array as the second argument 4// for property names to omit from being merged. 5// obj: Object 6// omit: Optional Array 7merge(obj, omit)
1// Execute a function against the current configuration context 2// handler: Function -> ChainedMap 3 // A function which is given a single argument of the ChainedMap instance 4batch(handler)
1// Conditionally execute a function to continue configuration 2// condition: Boolean 3// whenTruthy: Function -> ChainedMap 4 // invoked when condition is truthy, given a single argument of the ChainedMap instance 5// whenFalsy: Optional Function -> ChainedMap 6 // invoked when condition is falsy, given a single argument of the ChainedMap instance 7when(condition, whenTruthy, whenFalsy)
Another of the core API interfaces in webpack-chain is a ChainedSet
. A
ChainedSet
operates similar to a JavaScript Set, with some conveniences for
chaining and generating configuration. If a property is marked as being a
ChainedSet
, it will have an API and methods as described below:
Unless stated otherwise, these methods will return the ChainedSet
, allowing
you to chain these methods.
1// Add/append a value to the end of a Set. 2// value: * 3add(value)
1// Add a value to the beginning of a Set. 2// value: * 3prepend(value)
1// Remove all values from a Set. 2clear()
1// Remove a specific value from a Set. 2// value: * 3delete(value)
1// Returns `true` or `false` based on whether or not the 2// backing Set contains the specified value. 3// value: * 4// returns: Boolean 5has(value)
1// Returns an array of values contained in the backing Set. 2// returns: Array 3values()
1// Concatenates the given array to the end of the backing Set. 2// arr: Array 3merge(arr)
1// Execute a function against the current configuration context 2// handler: Function -> ChainedSet 3 // A function which is given a single argument of the ChainedSet instance 4batch(handler)
1// Conditionally execute a function to continue configuration 2// condition: Boolean 3// whenTruthy: Function -> ChainedSet 4 // invoked when condition is truthy, given a single argument of the ChainedSet instance 5// whenFalsy: Optional Function -> ChainedSet 6 // invoked when condition is falsy, given a single argument of the ChainedSet instance 7when(condition, whenTruthy, whenFalsy)
A number of shorthand methods exist for setting a value on a ChainedMap
with the same key as the shorthand method name.
For example, devServer.hot
is a shorthand method, so it can be used as:
1// A shorthand method for setting a value on a ChainedMap 2devServer.hot(true); 3 4// This would be equivalent to: 5devServer.set('hot', true);
A shorthand method is chainable, so calling it will return the original instance, allowing you to continue to chain.
Create a new configuration object.
1const Config = require('webpack-chain'); 2 3const config = new Config();
Moving to deeper points in the API will change the context of what you
are modifying. You can move back to the higher context by either referencing
the top-level config
again, or by calling .end()
to move up one level.
If you are familiar with jQuery, .end()
works similarly. All API calls
will return the API instance at the current context unless otherwise
specified. This is so you may chain API calls continuously if desired.
For details on the specific values that are valid for all shorthand and low-level methods, please refer to their corresponding name in the webpack docs hierarchy.
1Config : ChainedMap
1config 2 .amd(amd) 3 .bail(bail) 4 .cache(cache) 5 .devtool(devtool) 6 .context(context) 7 .externals(externals) 8 .loader(loader) 9 .name(name) 10 .mode(mode) 11 .parallelism(parallelism) 12 .profile(profile) 13 .recordsPath(recordsPath) 14 .recordsInputPath(recordsInputPath) 15 .recordsOutputPath(recordsOutputPath) 16 .stats(stats) 17 .target(target) 18 .watch(watch) 19 .watchOptions(watchOptions)
1// Backed at config.entryPoints : ChainedMap 2config.entry(name) : ChainedSet 3 4config 5 .entry(name) 6 .add(value) 7 .add(value) 8 9config 10 .entry(name) 11 .clear() 12 13// Using low-level config.entryPoints: 14 15config.entryPoints 16 .get(name) 17 .add(value) 18 .add(value) 19 20config.entryPoints 21 .get(name) 22 .clear()
1config.output : ChainedMap
2
3config.output
4 .auxiliaryComment(auxiliaryComment)
5 .chunkFilename(chunkFilename)
6 .chunkLoadTimeout(chunkLoadTimeout)
7 .crossOriginLoading(crossOriginLoading)
8 .devtoolFallbackModuleFilenameTemplate(devtoolFallbackModuleFilenameTemplate)
9 .devtoolLineToLine(devtoolLineToLine)
10 .devtoolModuleFilenameTemplate(devtoolModuleFilenameTemplate)
11 .devtoolNamespace(devtoolNamespace)
12 .filename(filename)
13 .hashFunction(hashFunction)
14 .hashDigest(hashDigest)
15 .hashDigestLength(hashDigestLength)
16 .hashSalt(hashSalt)
17 .hotUpdateChunkFilename(hotUpdateChunkFilename)
18 .hotUpdateFunction(hotUpdateFunction)
19 .hotUpdateMainFilename(hotUpdateMainFilename)
20 .jsonpFunction(jsonpFunction)
21 .library(library)
22 .libraryExport(libraryExport)
23 .libraryTarget(libraryTarget)
24 .path(path)
25 .pathinfo(pathinfo)
26 .publicPath(publicPath)
27 .sourceMapFilename(sourceMapFilename)
28 .sourcePrefix(sourcePrefix)
29 .strictModuleExceptionHandling(strictModuleExceptionHandling)
30 .umdNamedDefine(umdNamedDefine)
1config.resolve : ChainedMap
2
3config.resolve
4 .cachePredicate(cachePredicate)
5 .cacheWithContext(cacheWithContext)
6 .enforceExtension(enforceExtension)
7 .enforceModuleExtension(enforceModuleExtension)
8 .unsafeCache(unsafeCache)
9 .symlinks(symlinks)
1config.resolve.alias : ChainedMap 2 3config.resolve.alias 4 .set(key, value) 5 .set(key, value) 6 .delete(key) 7 .clear()
1config.resolve.modules : ChainedSet 2 3config.resolve.modules 4 .add(value) 5 .prepend(value) 6 .clear()
1config.resolve.aliasFields : ChainedSet 2 3config.resolve.aliasFields 4 .add(value) 5 .prepend(value) 6 .clear()
1config.resolve.descriptionFields : ChainedSet 2 3config.resolve.descriptionFields 4 .add(value) 5 .prepend(value) 6 .clear()
1config.resolve.extensions : ChainedSet 2 3config.resolve.extensions 4 .add(value) 5 .prepend(value) 6 .clear()
1config.resolve.mainFields : ChainedSet 2 3config.resolve.mainFields 4 .add(value) 5 .prepend(value) 6 .clear()
1config.resolve.mainFiles : ChainedSet 2 3config.resolve.mainFiles 4 .add(value) 5 .prepend(value) 6 .clear()
The API for config.resolveLoader
is identical to config.resolve
with
the following additions:
1config.resolveLoader.moduleExtensions : ChainedSet 2 3config.resolveLoader.moduleExtensions 4 .add(value) 5 .prepend(value) 6 .clear()
1config.resolveLoader.packageMains : ChainedSet 2 3config.resolveLoader.packageMains 4 .add(value) 5 .prepend(value) 6 .clear()
1config.performance : ChainedMap
2
3config.performance
4 .hints(hints)
5 .maxEntrypointSize(maxEntrypointSize)
6 .maxAssetSize(maxAssetSize)
7 .assetFilter(assetFilter)
1config.optimization : ChainedMap
2
3config.optimization
4 .concatenateModules(concatenateModules)
5 .flagIncludedChunks(flagIncludedChunks)
6 .mergeDuplicateChunks(mergeDuplicateChunks)
7 .minimize(minimize)
8 .namedChunks(namedChunks)
9 .namedModules(namedModules)
10 .nodeEnv(nodeEnv)
11 .noEmitOnErrors(noEmitOnErrors)
12 .occurrenceOrder(occurrenceOrder)
13 .portableRecords(portableRecords)
14 .providedExports(providedExports)
15 .removeAvailableModules(removeAvailableModules)
16 .removeEmptyChunks(removeEmptyChunks)
17 .runtimeChunk(runtimeChunk)
18 .sideEffects(sideEffects)
19 .splitChunks(splitChunks)
20 .usedExports(usedExports)
1// Backed at config.optimization.minimizers 2config.optimization 3 .minimizer(name) : ChainedMap
NOTE: Do not use new
to create the minimizer plugin, as this will be done for you.
1config.optimization 2 .minimizer(name) 3 .use(WebpackPlugin, args) 4 5// Examples 6 7config.optimization 8 .minimizer('css') 9 .use(OptimizeCSSAssetsPlugin, [{ cssProcessorOptions: { safe: true } }]) 10 11// Minimizer plugins can also be specified by their path, allowing the expensive require()s to be 12// skipped in cases where the plugin or webpack configuration won't end up being used. 13config.optimization 14 .minimizer('css') 15 .use(require.resolve('optimize-css-assets-webpack-plugin'), [{ cssProcessorOptions: { safe: true } }]) 16
1config.optimization 2 .minimizer(name) 3 .tap(args => newArgs) 4 5// Example 6config.optimization 7 .minimizer('css') 8 .tap(args => [...args, { cssProcessorOptions: { safe: false } }])
1config.optimization 2 .minimizer(name) 3 .init((Plugin, args) => new Plugin(...args));
1config.optimization.minimizers.delete(name)
1// Backed at config.plugins 2config.plugin(name) : ChainedMap
NOTE: Do not use new
to create the plugin, as this will be done for you.
1config 2 .plugin(name) 3 .use(WebpackPlugin, args) 4 5// Examples 6 7config 8 .plugin('hot') 9 .use(webpack.HotModuleReplacementPlugin); 10 11// Plugins can also be specified by their path, allowing the expensive require()s to be 12// skipped in cases where the plugin or webpack configuration won't end up being used. 13config 14 .plugin('env') 15 .use(require.resolve('webpack/lib/EnvironmentPlugin'), [{ 'VAR': false }]);
1config 2 .plugin(name) 3 .tap(args => newArgs) 4 5// Example 6config 7 .plugin('env') 8 .tap(args => [...args, 'SECRET_KEY']);
1config 2 .plugin(name) 3 .init((Plugin, args) => new Plugin(...args));
1config.plugins.delete(name)
Specify that the current plugin
context should operate before another named
plugin
. You cannot use both .before()
and .after()
on the same plugin.
1config 2 .plugin(name) 3 .before(otherName) 4 5// Example 6 7config 8 .plugin('html-template') 9 .use(HtmlWebpackTemplate) 10 .end() 11 .plugin('script-ext') 12 .use(ScriptExtWebpackPlugin) 13 .before('html-template');
Specify that the current plugin
context should operate after another named
plugin
. You cannot use both .before()
and .after()
on the same plugin.
1config 2 .plugin(name) 3 .after(otherName) 4 5// Example 6 7config 8 .plugin('html-template') 9 .after('script-ext') 10 .use(HtmlWebpackTemplate) 11 .end() 12 .plugin('script-ext') 13 .use(ScriptExtWebpackPlugin);
1// Backed at config.resolve.plugins 2config.resolve.plugin(name) : ChainedMap
NOTE: Do not use new
to create the plugin, as this will be done for you.
1config.resolve 2 .plugin(name) 3 .use(WebpackPlugin, args)
1config.resolve 2 .plugin(name) 3 .tap(args => newArgs)
1config.resolve 2 .plugin(name) 3 .init((Plugin, args) => new Plugin(...args))
1config.resolve.plugins.delete(name)
Specify that the current plugin
context should operate before another named
plugin
. You cannot use both .before()
and .after()
on the same resolve
plugin.
1config.resolve 2 .plugin(name) 3 .before(otherName) 4 5// Example 6 7config.resolve 8 .plugin('beta') 9 .use(BetaWebpackPlugin) 10 .end() 11 .plugin('alpha') 12 .use(AlphaWebpackPlugin) 13 .before('beta');
Specify that the current plugin
context should operate after another named
plugin
. You cannot use both .before()
and .after()
on the same resolve
plugin.
1config.resolve 2 .plugin(name) 3 .after(otherName) 4 5// Example 6 7config.resolve 8 .plugin('beta') 9 .after('alpha') 10 .use(BetaWebpackTemplate) 11 .end() 12 .plugin('alpha') 13 .use(AlphaWebpackPlugin);
1config.node : ChainedMap 2 3config.node 4 .set('__dirname', 'mock') 5 .set('__filename', 'mock');
1config.devServer : ChainedMap
1config.devServer.allowedHosts : ChainedSet 2 3config.devServer.allowedHosts 4 .add(value) 5 .prepend(value) 6 .clear()
1config.devServer 2 .after(after) 3 .before(before) 4 .bonjour(bonjour) 5 .clientLogLevel(clientLogLevel) 6 .color(color) 7 .compress(compress) 8 .contentBase(contentBase) 9 .disableHostCheck(disableHostCheck) 10 .filename(filename) 11 .headers(headers) 12 .historyApiFallback(historyApiFallback) 13 .host(host) 14 .hot(hot) 15 .hotOnly(hotOnly) 16 .http2(http2) 17 .https(https) 18 .index(index) 19 .info(info) 20 .inline(inline) 21 .lazy(lazy) 22 .mimeTypes(mimeTypes) 23 .noInfo(noInfo) 24 .open(open) 25 .openPage(openPage) 26 .overlay(overlay) 27 .pfx(pfx) 28 .pfxPassphrase(pfxPassphrase) 29 .port(port) 30 .progress(progress) 31 .proxy(proxy) 32 .public(public) 33 .publicPath(publicPath) 34 .quiet(quiet) 35 .setup(setup) 36 .socket(socket) 37 .sockHost(sockHost) 38 .sockPath(sockPath) 39 .sockPort(sockPort) 40 .staticOptions(staticOptions) 41 .stats(stats) 42 .stdin(stdin) 43 .useLocalIp(useLocalIp) 44 .watchContentBase(watchContentBase) 45 .watchOptions(watchOptions) 46 .writeToDisk(writeToDisk)
1config.module : ChainedMap
1config.module : ChainedMap 2 3config.module 4 .noParse(noParse)
1config.module.rules : ChainedMap 2 3config.module 4 .rule(name) 5 .test(test) 6 .pre() 7 .post() 8 .enforce(preOrPost)
1config.module.rules{}.uses : ChainedMap 2 3config.module 4 .rule(name) 5 .use(name) 6 .loader(loader) 7 .options(options) 8 9// Example 10 11config.module 12 .rule('compile') 13 .use('babel') 14 .loader('babel-loader') 15 .options({ presets: ['@babel/preset-env'] });
1config.module 2 .rule(name) 3 .use(name) 4 .tap(options => newOptions) 5 6// Example 7 8config.module 9 .rule('compile') 10 .use('babel') 11 .tap(options => merge(options, { 12 plugins: ['@babel/plugin-proposal-class-properties'] 13 }));
1config.module.rules{}.rules : ChainedMap<Rule> 2 3config.module 4 .rule(name) 5 .rule(name) 6 7// Example 8 9config.module 10 .rule('css') 11 .test(/\.css$/) 12 .use('style') 13 .loader('style-loader') 14 .end() 15 .rule('postcss') 16 .resourceQuery(/postcss/) 17 .use('postcss') 18 .loader('postcss-loader')
Specify that the current rule
context should operate before another named
rule
. You cannot use both .before()
and .after()
on the same rule
.
1config.module.rules{}.rules : ChainedMap<Rule> 2 3config.module 4 .rule(name) 5 .rule(name) 6 .before(otherName) 7 8// Example 9 10config.module 11 .rule('css') 12 .use('style') 13 .loader('style-loader') 14 .end() 15 .rule('postcss') 16 .resourceQuery(/postcss/) 17 .use('postcss') 18 .loader('postcss-loader') 19 .end() 20 .end() 21 .rule('css-loader') 22 .resourceQuery(/css-loader/) 23 .before('postcss') 24 .use('css-loader') 25 .loader('css-loader')
Specify that the current rule
context should operate after another named
rule
. You cannot use both .before()
and .after()
on the same rule
.
1config.module.rules{}.rules : ChainedMap<Rule> 2 3config.module 4 .rule(name) 5 .rule(name) 6 .after(otherName) 7 8// Example 9 10config.module 11 .rule('css') 12 .use('style') 13 .loader('style-loader') 14 .end() 15 .rule('postcss') 16 .resourceQuery(/postcss/) 17 .after('css-loader') 18 .use('postcss') 19 .loader('postcss-loader') 20 .end() 21 .end() 22 .rule('css-loader') 23 .resourceQuery(/css-loader/) 24 .use('css-loader') 25 .loader('css-loader')
1config.module.rules{}.oneOfs : ChainedMap<Rule> 2 3config.module 4 .rule(name) 5 .oneOf(name) 6 7// Example 8 9config.module 10 .rule('css') 11 .oneOf('inline') 12 .resourceQuery(/inline/) 13 .use('url') 14 .loader('url-loader') 15 .end() 16 .end() 17 .oneOf('external') 18 .resourceQuery(/external/) 19 .use('file') 20 .loader('file-loader')
Specify that the current oneOf
context should operate before another named
oneOf
. You cannot use both .before()
and .after()
on the same oneOf
.
1config.module 2 .rule(name) 3 .oneOf(name) 4 .before() 5 6// Example 7 8config.module 9 .rule('scss') 10 .test(/\.scss$/) 11 .oneOf('normal') 12 .use('sass') 13 .loader('sass-loader') 14 .end() 15 .end() 16 .oneOf('sass-vars') 17 .before('normal') 18 .resourceQuery(/\?sassvars/) 19 .use('sass-vars') 20 .loader('sass-vars-to-js-loader')
Specify that the current oneOf
context should operate after another named
oneOf
. You cannot use both .before()
and .after()
on the same oneOf
.
1config.module 2 .rule(name) 3 .oneOf(name) 4 .after() 5 6// Example 7 8config.module 9 .rule('scss') 10 .test(/\.scss$/) 11 .oneOf('vue') 12 .resourceQuery(/\?vue/) 13 .use('vue-style') 14 .loader('vue-style-loader') 15 .end() 16 .end() 17 .oneOf('normal') 18 .use('sass') 19 .loader('sass-loader') 20 .end() 21 .end() 22 .oneOf('sass-vars') 23 .after('vue') 24 .resourceQuery(/\?sassvars/) 25 .use('sass-vars') 26 .loader('sass-vars-to-js-loader')
Specify a resolve configuration to be merged over the default config.resolve
for modules that match the rule.
See "Config resolve" sections above for full syntax.
Note: This option is supported by webpack since 4.36.1.
1config.module 2 .rule(name) 3 .resolve 4 5// Example 6 7config.module 8 .rule('scss') 9 .test(/\.scss$/) 10 .resolve 11 .symlinks(true)
webpack-chain supports merging in an object to the configuration instance which matches a layout similar to how the webpack-chain schema is laid out.
Note: This object does not match the webpack configuration schema exactly
(for example the [name]
keys for entry/rules/plugins), so you may need to transform
webpack configuration objects (such as those output by webpack-chain's .toConfig()
)
to match the layout below prior to passing to .merge()
.
1config.merge({ devtool: 'source-map' }); 2 3config.get('devtool') // "source-map"
1config.merge({ 2 [key]: value, 3 4 amd, 5 bail, 6 cache, 7 context, 8 devtool, 9 externals, 10 loader, 11 mode, 12 parallelism, 13 profile, 14 recordsPath, 15 recordsInputPath, 16 recordsOutputPath, 17 stats, 18 target, 19 watch, 20 watchOptions, 21 22 entry: { 23 [name]: [...values] 24 }, 25 26 plugin: { 27 [name]: { 28 plugin: WebpackPlugin, 29 args: [...args], 30 before, 31 after 32 } 33 }, 34 35 devServer: { 36 [key]: value, 37 38 clientLogLevel, 39 compress, 40 contentBase, 41 filename, 42 headers, 43 historyApiFallback, 44 host, 45 hot, 46 hotOnly, 47 https, 48 inline, 49 lazy, 50 noInfo, 51 overlay, 52 port, 53 proxy, 54 quiet, 55 setup, 56 stats, 57 watchContentBase 58 }, 59 60 node: { 61 [key]: value 62 }, 63 64 optimization: { 65 concatenateModules, 66 flagIncludedChunks, 67 mergeDuplicateChunks, 68 minimize, 69 minimizer: { 70 [name]: { 71 plugin: WebpackPlugin, 72 args: [...args], 73 before, 74 after 75 } 76 }, 77 namedChunks, 78 namedModules, 79 nodeEnv, 80 noEmitOnErrors, 81 occurrenceOrder, 82 portableRecords, 83 providedExports, 84 removeAvailableModules, 85 removeEmptyChunks, 86 runtimeChunk, 87 sideEffects, 88 splitChunks, 89 usedExports, 90 }, 91 92 performance: { 93 [key]: value, 94 95 hints, 96 maxEntrypointSize, 97 maxAssetSize, 98 assetFilter 99 }, 100 101 resolve: { 102 [key]: value, 103 104 alias: { 105 [key]: value 106 }, 107 aliasFields: [...values], 108 descriptionFields: [...values], 109 extensions: [...values], 110 mainFields: [...values], 111 mainFiles: [...values], 112 modules: [...values], 113 114 plugin: { 115 [name]: { 116 plugin: WebpackPlugin, 117 args: [...args], 118 before, 119 after 120 } 121 } 122 }, 123 124 resolveLoader: { 125 [key]: value, 126 127 alias: { 128 [key]: value 129 }, 130 aliasFields: [...values], 131 descriptionFields: [...values], 132 extensions: [...values], 133 mainFields: [...values], 134 mainFiles: [...values], 135 modules: [...values], 136 moduleExtensions: [...values], 137 packageMains: [...values], 138 139 plugin: { 140 [name]: { 141 plugin: WebpackPlugin, 142 args: [...args], 143 before, 144 after 145 } 146 } 147 }, 148 149 module: { 150 [key]: value, 151 152 rule: { 153 [name]: { 154 [key]: value, 155 156 enforce, 157 issuer, 158 parser, 159 resource, 160 resourceQuery, 161 test, 162 163 include: [...paths], 164 exclude: [...paths], 165 166 rules: { 167 [name]: Rule 168 }, 169 170 oneOf: { 171 [name]: Rule 172 }, 173 174 use: { 175 [name]: { 176 loader: LoaderString, 177 options: LoaderOptions, 178 before, 179 after 180 } 181 } 182 } 183 } 184 } 185})
When working with instances of ChainedMap
and ChainedSet
, you can perform
conditional configuration using when
. You must specify an expression to
when()
which will be evaluated for truthiness or falsiness. If the expression
is truthy, the first function argument will be invoked with an instance of the
current chained instance. You can optionally provide a second function to be
invoked when the condition is falsy, which is also given the current chained
instance.
1// Example: Only add minify plugin during production 2config 3 .when(process.env.NODE_ENV === 'production', config => { 4 config 5 .plugin('minify') 6 .use(BabiliWebpackPlugin); 7 });
1// Example: Only add minify plugin during production, 2// otherwise set devtool to source-map 3config 4 .when(process.env.NODE_ENV === 'production', 5 config => config.plugin('minify').use(BabiliWebpackPlugin), 6 config => config.devtool('source-map') 7 );
You can inspect the generated webpack config using config.toString()
. This
will generate a stringified version of the config with comment hints for named
rules, uses and plugins:
1config 2 .module 3 .rule('compile') 4 .test(/\.js$/) 5 .use('babel') 6 .loader('babel-loader'); 7 8config.toString(); 9 10/* 11{ 12 module: { 13 rules: [ 14 /* config.module.rule('compile') */ 15 { 16 test: /\.js$/, 17 use: [ 18 /* config.module.rule('compile').use('babel') */ 19 { 20 loader: 'babel-loader' 21 } 22 ] 23 } 24 ] 25 } 26} 27*/
By default the generated string cannot be used directly as real webpack config
if it contains objects and plugins that need to be required. In order to
generate usable config, you can customize how objects and plugins are
stringified by setting a special __expression
property on them:
1const sass = require('sass'); 2sass.__expression = `require('sass')`; 3 4class MyPlugin {} 5MyPlugin.__expression = `require('my-plugin')`; 6 7function myFunction () {} 8myFunction.__expression = `require('my-function')`; 9 10config 11 .plugin('example') 12 .use(MyPlugin, [{ fn: myFunction, implementation: sass, }]); 13 14config.toString(); 15 16/* 17{ 18 plugins: [ 19 new (require('my-plugin'))({ 20 fn: require('my-function'), 21 implementation: require('sass') 22 }) 23 ] 24} 25*/
Plugins specified via their path will have their require()
statement generated
automatically:
1config 2 .plugin('env') 3 .use(require.resolve('webpack/lib/ProvidePlugin'), [{ jQuery: 'jquery' }]) 4 5config.toString(); 6 7/* 8{ 9 plugins: [ 10 new (require('/foo/bar/src/node_modules/webpack/lib/EnvironmentPlugin.js'))( 11 { 12 jQuery: 'jquery' 13 } 14 ) 15 ] 16} 17*/
You can also call toString
as a static method on Config
in order to
modify the configuration object prior to stringifying.
1Config.toString({ 2 ...config.toConfig(), 3 module: { 4 defaultRules: [ 5 { 6 use: [ 7 { 8 loader: 'banner-loader', 9 options: { prefix: 'banner-prefix.txt' }, 10 }, 11 ], 12 }, 13 ], 14 }, 15})
{
plugins: [
/* config.plugin('foo') */
new TestPlugin()
],
module: {
defaultRules: [
{
use: [
{
loader: 'banner-loader',
options: {
prefix: 'banner-prefix.txt'
}
}
]
}
]
}
}
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 10/16 approved changesets -- score normalized to 6
Reason
project is archived
Details
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
28 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More