yarn run v1.22.10 $ eslint --cache --max-warnings 0 --format codeframe . The codeframe formatter is no longer part of core ESLint. Install it manually with `npm install -D eslint-formatter-codeframe` Co-authored-by: Renovate Bot <[email protected]> Co-authored-by: Ed Morley <[email protected]> da73fab

Git stats

Config resolveLoader Config resolveLoader moduleExtensions Config resolveLoader packageMains Config performance: shorthand methods Configuring optimizations: shorthand methods Config optimization minimizers Config optimization minimizers: adding Config optimization minimizers: modify arguments Config optimization minimizers: modify instantiation Config optimization minimizers: removing Config plugins Config plugins: adding Config plugins: modify arguments Config plugins: modify instantiation Config plugins: removing Config plugins: ordering before Config plugins: ordering after Config resolve plugins Config resolve plugins: adding Config resolve plugins: modify arguments Config resolve plugins: modify instantiation Config resolve plugins: removing Config resolve plugins: ordering before Config resolve plugins: ordering after Config node Config devServer Config devServer allowedHosts Config devServer: shorthand methods Config module Config module: shorthand methods Config module rules: shorthand methods Config module rules uses (loaders): creating Config module rules uses (loaders): modifying options Config module rules nested rules: Config module rules nested rules: ordering before Config module rules nested rules: ordering after Config module rules oneOfs (conditional rules): Config module rules oneOfs (conditional rules): ordering before Config module rules oneOfs (conditional rules): ordering after Config module rules resolve Merging Config Conditional configuration Inspecting generated configuration

Use a chaining API to generate and simplify the modification of webpack 4 configurations.

This documentation corresponds to v7 of webpack-chain. For previous versions, see:

  • v6 docs
  • v5 docs
  • v4 docs
  • v3 docs
  • v2 docs
  • v1 docs
  • Note: while webpack-chain is utilized extensively in Neutrino, this package is completely standalone and can be used by any project.

    Chinese docs(中文文档)

    Introduction

    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.

    Installation

    webpack-chain requires Node.js 12 or higher. webpack-chain also only creates configuration objects designed for use with webpack 4.

    You may install this package using either Yarn or npm (choose one):

    yarn add --dev webpack-chain
    npm install --save-dev webpack-chain

    Getting Started

    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.

    // Require the webpack-chain module. This module exports a single
    // constructor function for creating a configuration API.
    const Config = require('webpack-chain');
    // Instantiate the configuration with a new API
    const config = new Config();
    // Make configuration changes using the chain API.
    // Every API call tracks a change to the stored configuration.
    config
      // Interact with entry points
      .entry('index')
        .add('src/index.js')
        .end()
      // Modify output settings
      .output
        .path('dist')
        .filename('[name].bundle.js');
    // Create named rules which can be modified later
    config.module
      .rule('lint')
        .test(/\.js$/)
        .pre()
        .include
          .add('src')
          .end()
        // Even create named uses (loaders)
        .use('eslint')
          .loader('eslint-loader')
          .options({
            rules: {
              semi: 'off'
          });
    config.module
      .rule('compile')
        .test(/\.js$/)
        .include
          .add('src')
          .add('test')
          .end()
        .use('babel')
          .loader('babel-loader')
          .options({
            presets: [
              ['@babel/preset-env', { modules: false }]
          });
    // Create named plugins too!
    config
      .plugin('clean')
        .use(CleanPlugin, [['dist'], { root: '/dir' }]);
    // Export the completed configuration object to be consumed by webpack
    module.exports = config.toConfig();

    Having shared configurations is also simple. Just export the configuration and call .toConfig() prior to passing to webpack.

    // webpack.core.js
    const Config = require('webpack-chain');
    const config = new Config();
    // Make configuration shared across targets
    // ...
    module.exports = config;
    // webpack.dev.js
    const config = require('./webpack.core');
    // Dev-specific configuration
    // ...
    module.exports = config.toConfig();
    // webpack.prod.js
    const config = require('./webpack.core');
    // Production-specific configuration
    // ...
    module.exports = config.toConfig();

    ChainedMap

    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.

    // Remove all entries from a Map.
    clear()
    // Remove a single entry from a Map given its key.
    // key: *
    delete(key)
    // Fetch the value from a Map located at the corresponding key.
    // key: *
    // returns: value
    get(key)
    // Fetch the value from a Map located at the corresponding key.
    // If the key is missing, the key is set to the result of function fn.
    // key: *
    // fn: Function () -> value
    // returns: value
    getOrCompute(key, fn)
    // Set a value on the Map stored at the `key` location.
    // key: *
    // value: *
    set(key, value)
    // Returns `true` or `false` based on whether a Map as has a value set at a
    // particular key.
    // key: *
    // returns: Boolean
    has(key)
    // Returns an array of all the values stored in the Map.
    // returns: Array
    values()
    // Returns an object of all the entries in the backing Map
    // where the key is the object property, and the value
    // corresponding to the key. Will return `undefined` if the backing
    // Map is empty.
    // This will order properties by their name if the value is
    // a ChainedMap that used .before() or .after().
    // returns: Object, undefined if empty
    entries()
    // Provide an object which maps its properties and values
    // into the backing Map as keys and values.
    // You can also provide an array as the second argument
    // for property names to omit from being merged.
    // obj: Object
    // omit: Optional Array
    merge(obj, omit)
    // Execute a function against the current configuration context
    // handler: Function -> ChainedMap
      // A function which is given a single argument of the ChainedMap instance
    batch(handler)
    // Conditionally execute a function to continue configuration
    // condition: Boolean
    // whenTruthy: Function -> ChainedMap
      // invoked when condition is truthy, given a single argument of the ChainedMap instance
    // whenFalsy: Optional Function -> ChainedMap
      // invoked when condition is falsy, given a single argument of the ChainedMap instance
    when(condition, whenTruthy, whenFalsy)

    ChainedSet

    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.

    // Add/append a value to the end of a Set.
    // value: *
    add(value)
    // Add a value to the beginning of a Set.
    // value: *
    prepend(value)
    // Remove all values from a Set.
    clear()
    // Remove a specific value from a Set.
    // value: *
    delete(value)
    // Returns `true` or `false` based on whether or not the
    // backing Set contains the specified value.
    // value: *
    // returns: Boolean
    has(value)
    // Returns an array of values contained in the backing Set.
    // returns: Array
    values()
    // Concatenates the given array to the end of the backing Set.
    // arr: Array
    merge(arr)
    // Execute a function against the current configuration context
    // handler: Function -> ChainedSet
      // A function which is given a single argument of the ChainedSet instance
    batch(handler)
    // Conditionally execute a function to continue configuration
    // condition: Boolean
    // whenTruthy: Function -> ChainedSet
      // invoked when condition is truthy, given a single argument of the ChainedSet instance
    // whenFalsy: Optional Function -> ChainedSet
      // invoked when condition is falsy, given a single argument of the ChainedSet instance
    when(condition, whenTruthy, whenFalsy)

    Shorthand methods

    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:

    // A shorthand method for setting a value on a ChainedMap
    devServer.hot(true);
    // This would be equivalent to:
    devServer.set('hot', true);

    A shorthand method is chainable, so calling it will return the original instance, allowing you to continue to chain.

    Config

    Create a new configuration object.

    const Config = require('webpack-chain');
    const 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 .

    Config : ChainedMap

    Config shorthand methods

    config
      .amd(amd)
      .bail(bail)
      .cache(cache)
      .devtool(devtool)
      .context(context)
      .externals(externals)
      .loader(loader)
      .name(name)
      .mode(mode)
      .parallelism(parallelism)
      .profile(profile)
      .recordsPath(recordsPath)
      .recordsInputPath(recordsInputPath)
      .recordsOutputPath(recordsOutputPath)
      .stats(stats)
      .target(target)
      .watch(watch)
      .watchOptions(watchOptions)

    Config entryPoints

    // Backed at config.entryPoints : ChainedMap
    config.entry(name) : ChainedSet
    config
      .entry(name)
        .add(value)
        .add(value)
    config
      .entry(name)
        .clear()
    // Using low-level config.entryPoints:
    config.entryPoints
      .get(name)
        .add(value)
        .add(value)
    config.entryPoints
      .get(name)
        .clear()

    Config output: shorthand methods

    config.output : ChainedMap
    config.output
      .auxiliaryComment(auxiliaryComment)
      .chunkFilename(chunkFilename)
      .chunkLoadTimeout(chunkLoadTimeout)
      .crossOriginLoading(crossOriginLoading)
      .devtoolFallbackModuleFilenameTemplate(devtoolFallbackModuleFilenameTemplate)
      .devtoolLineToLine(devtoolLineToLine)
      .devtoolModuleFilenameTemplate(devtoolModuleFilenameTemplate)
      .devtoolNamespace(devtoolNamespace)
      .filename(filename)
      .hashFunction(hashFunction)
      .hashDigest(hashDigest)
      .hashDigestLength(hashDigestLength)
      .hashSalt(hashSalt)
      .hotUpdateChunkFilename(hotUpdateChunkFilename)
      .hotUpdateFunction(hotUpdateFunction)
      .hotUpdateMainFilename(hotUpdateMainFilename)
      .jsonpFunction(jsonpFunction)
      .library(library)
      .libraryExport(libraryExport)
      .libraryTarget(libraryTarget)
      .path(path)
      .pathinfo(pathinfo)
      .publicPath(publicPath)
      .sourceMapFilename(sourceMapFilename)
      .sourcePrefix(sourcePrefix)
      .strictModuleExceptionHandling(strictModuleExceptionHandling)
      .umdNamedDefine(umdNamedDefine)

    Config resolve: shorthand methods

    config.resolve : ChainedMap
    config.resolve
      .cachePredicate(cachePredicate)
      .cacheWithContext(cacheWithContext)
      .enforceExtension(enforceExtension)
      .enforceModuleExtension(enforceModuleExtension)
      .unsafeCache(unsafeCache)
      .symlinks(symlinks)

    Config resolve alias

    config.resolve.alias : ChainedMap
    config.resolve.alias
      .set(key, value)
      .set(key, value)
      .delete(key)
      .clear()

    Config resolve modules

    config.resolve.modules : ChainedSet
    config.resolve.modules
      .add(value)
      .prepend(value)
      .clear()

    Config resolve aliasFields

    config.resolve.aliasFields : ChainedSet
    config.resolve.aliasFields
      .add(value)
      .prepend(value)
      .clear()

    Config resolve descriptionFields

    config.resolve.descriptionFields : ChainedSet
    config.resolve.descriptionFields
      .add(value)
      .prepend(value)
      .clear()

    Config resolve extensions

    config.resolve.extensions : ChainedSet
    config.resolve.extensions
      .add(value)
      .prepend(value)
      .clear()

    Config resolve mainFields

    config.resolve.mainFields : ChainedSet
    config.resolve.mainFields
      .add(value)
      .prepend(value)
      .clear()

    Config resolve mainFiles

    config.resolve.mainFiles : ChainedSet
    config.resolve.mainFiles
      .add(value)
      .prepend(value)
      .clear()

    Config resolveLoader

    The API for config.resolveLoader is identical to config.resolve with the following additions:

    Config resolveLoader moduleExtensions

    config.resolveLoader.moduleExtensions : ChainedSet
    config.resolveLoader.moduleExtensions
      .add(value)
      .prepend(value)
      .clear()

    Config resolveLoader packageMains

    config.resolveLoader.packageMains : ChainedSet
    config.resolveLoader.packageMains
      .add(value)
      .prepend(value)
      .clear()

    Config performance: shorthand methods

    config.performance : ChainedMap
    config.performance
      .hints(hints)
      .maxEntrypointSize(maxEntrypointSize)
      .maxAssetSize(maxAssetSize)
      .assetFilter(assetFilter)

    Configuring optimizations: shorthand methods

    config.optimization : ChainedMap
    config.optimization
      .concatenateModules(concatenateModules)
      .flagIncludedChunks(flagIncludedChunks)
      .mergeDuplicateChunks(mergeDuplicateChunks)
      .minimize(minimize)
      .namedChunks(namedChunks)
      .namedModules(namedModules)
      .nodeEnv(nodeEnv)
      .noEmitOnErrors(noEmitOnErrors)
      .occurrenceOrder(occurrenceOrder)
      .portableRecords(portableRecords)
      .providedExports(providedExports)
      .removeAvailableModules(removeAvailableModules)
      .removeEmptyChunks(removeEmptyChunks)
      .runtimeChunk(runtimeChunk)
      .sideEffects(sideEffects)
      .splitChunks(splitChunks)
      .usedExports(usedExports)

    Config optimization minimizers

    // Backed at config.optimization.minimizers
    config.optimization
      .minimizer(name) : ChainedMap

    Config optimization minimizers: adding

    NOTE: Do not use new to create the minimizer plugin, as this will be done for you.

    config.optimization
      .minimizer(name)
      .use(WebpackPlugin, args)
    // Examples
    config.optimization
      .minimizer('css')
      .use(OptimizeCSSAssetsPlugin, [{ cssProcessorOptions: { safe: true } }])
    // Minimizer plugins can also be specified by their path, allowing the expensive require()s to be
    // skipped in cases where the plugin or webpack configuration won't end up being used.
    config.optimization
      .minimizer('css')
      .use(require.resolve('optimize-css-assets-webpack-plugin'), [{ cssProcessorOptions: { safe: true } }])

    Config optimization minimizers: modify arguments

    config.optimization
      .minimizer(name)
      .tap(args => newArgs)
    // Example
    config.optimization
      .minimizer('css')
      .tap(args => [...args, { cssProcessorOptions: { safe: false } }])

    Config optimization minimizers: modify instantiation

    config.optimization
      .minimizer(name)
      .init((Plugin, args) => new Plugin(...args));

    Config optimization minimizers: removing

    config.optimization.minimizers.delete(name)

    Config plugins

    // Backed at config.plugins
    config.plugin(name) : ChainedMap

    Config plugins: adding

    NOTE: Do not use new to create the plugin, as this will be done for you.

    config
      .plugin(name)
      .use(WebpackPlugin, args)
    // Examples
    config
      .plugin('hot')
      .use(webpack.HotModuleReplacementPlugin);
    // Plugins can also be specified by their path, allowing the expensive require()s to be
    // skipped in cases where the plugin or webpack configuration won't end up being used.
    config
      .plugin('env')
      .use(require.resolve('webpack/lib/EnvironmentPlugin'), [{ 'VAR': false }]);

    Config plugins: modify arguments

    config
      .plugin(name)
      .tap(args => newArgs)
    // Example
    config
      .plugin('env')
      .tap(args => [...args, 'SECRET_KEY']);

    Config plugins: modify instantiation

    config
      .plugin(name)
      .init((Plugin, args) => new Plugin(...args));

    Config plugins: removing

    config.plugins.delete(name)

    Config plugins: ordering before

    Specify that the current plugin context should operate before another named plugin . You cannot use both .before() and .after() on the same plugin.

    config
      .plugin(name)
        .before(otherName)
    // Example
    config
      .plugin('html-template')
        .use(HtmlWebpackTemplate)
        .end()
      .plugin('script-ext')
        .use(ScriptExtWebpackPlugin)
        .before('html-template');

    Config plugins: ordering after

    Specify that the current plugin context should operate after another named plugin . You cannot use both .before() and .after() on the same plugin.

    config
      .plugin(name)
        .after(otherName)
    // Example
    config
      .plugin('html-template')
        .after('script-ext')
        .use(HtmlWebpackTemplate)
        .end()
      .plugin('script-ext')
        .use(ScriptExtWebpackPlugin);

    Config resolve plugins

    // Backed at config.resolve.plugins
    config.resolve.plugin(name) : ChainedMap

    Config resolve plugins: adding

    NOTE: Do not use new to create the plugin, as this will be done for you.

    config.resolve
      .plugin(name)
      .use(WebpackPlugin, args)

    Config resolve plugins: modify arguments

    config.resolve
      .plugin(name)
      .tap(args => newArgs)

    Config resolve plugins: modify instantiation

    config.resolve
      .plugin(name)
      .init((Plugin, args) => new Plugin(...args))

    Config resolve plugins: removing

    config.resolve.plugins.delete(name)

    Config resolve plugins: ordering before

    Specify that the current plugin context should operate before another named plugin . You cannot use both .before() and .after() on the same resolve plugin.

    config.resolve
      .plugin(name)
        .before(otherName)
    // Example
    config.resolve
      .plugin('beta')
        .use(BetaWebpackPlugin)
        .end()
      .plugin('alpha')
        .use(AlphaWebpackPlugin)
        .before('beta');

    Config resolve plugins: ordering after

    Specify that the current plugin context should operate after another named plugin . You cannot use both .before() and .after() on the same resolve plugin.

    config.resolve
      .plugin(name)
        .after(otherName)
    // Example
    config.resolve
      .plugin('beta')
        .after('alpha')
        .use(BetaWebpackTemplate)
        .end()
      .plugin('alpha')
        .use(AlphaWebpackPlugin);

    Config node

    config.node : ChainedMap
    config.node
      .set('__dirname', 'mock')
      .set('__filename', 'mock');

    Config devServer

    config.devServer : ChainedMap

    Config devServer allowedHosts

    config.devServer.allowedHosts : ChainedSet
    config.devServer.allowedHosts
      .add(value)
      .prepend(value)
      .clear()

    Config devServer: shorthand methods

    config.devServer
      .after(after)
      .before(before)
      .bonjour(bonjour)
      .clientLogLevel(clientLogLevel)
      .color(color)
      .compress(compress)
      .contentBase(contentBase)
      .disableHostCheck(disableHostCheck)
      .filename(filename)
      .headers(headers)
      .historyApiFallback(historyApiFallback)
      .host(host)
      .hot(hot)
      .hotOnly(hotOnly)
      .http2(http2)
      .https(https)
      .index(index)
      .info(info)
      .inline(inline)
      .lazy(lazy)
      .mimeTypes(mimeTypes)
      .noInfo(noInfo)
      .open(open)
      .openPage(openPage)
      .overlay(overlay)
      .pfx(pfx)
      .pfxPassphrase(pfxPassphrase)
      .port(port)
      .progress(progress)
      .proxy(proxy)
      .public(public)
      .publicPath(publicPath)
      .quiet(quiet)
      .setup(setup)
      .socket(socket)
      .sockHost(sockHost)
      .sockPath(sockPath)
      .sockPort(sockPort)
      .staticOptions(staticOptions)
      .stats(stats)
      .stdin(stdin)
      .useLocalIp(useLocalIp)
      .watchContentBase(watchContentBase)
      .watchOptions(watchOptions)
      .writeToDisk(writeToDisk)

    Config module

    config.module : ChainedMap

    Config module: shorthand methods

    config.module : ChainedMap
    config.module
      .noParse(noParse)

    Config module rules: shorthand methods

    config.module.rules : ChainedMap
    config.module
      .rule(name)
        .test(test)
        .pre()
        .post()
        .enforce(preOrPost)

    Config module rules uses (loaders): creating

    config.module.rules{}.uses : ChainedMap
    config.module
      .rule(name)
        .use(name)
          .loader(loader)
          .options(options)
    // Example
    config.module
      .rule('compile')
        .use('babel')
          .loader('babel-loader')
          .options({ presets: ['@babel/preset-env'] });

    Config module rules uses (loaders): modifying options

    config.module
      .rule(name)
        .use(name)
          .tap(options => newOptions)
    // Example
    config.module
      .rule('compile')
        .use('babel')
          .tap(options => merge(options, {
            plugins: ['@babel/plugin-proposal-class-properties']
          }));

    Config module rules nested rules:

    config.module.rules{}.rules : ChainedMap<Rule>
    config.module
      .rule(name)
        .rule(name)
    // Example
    config.module
      .rule('css')
        .test(/\.css$/)
        .use('style')
          .loader('style-loader')
          .end()
        .rule('postcss')
          .resourceQuery(/postcss/)
          .use('postcss')
            .loader('postcss-loader')

    Config module rules nested rules: ordering before

    Specify that the current rule context should operate before another named rule . You cannot use both .before() and .after() on the same rule .

    config.module.rules{}.rules : ChainedMap<Rule>
    config.module
      .rule(name)
        .rule(name)
          .before(otherName)
    // Example
    config.module
      .rule('css')
        .use('style')
          .loader('style-loader')
          .end()
        .rule('postcss')
          .resourceQuery(/postcss/)
          .use('postcss')
            .loader('postcss-loader')
            .end()
          .end()
        .rule('css-loader')
          .resourceQuery(/css-loader/)
          .before('postcss')
          .use('css-loader')
            .loader('css-loader')

    Config module rules nested rules: ordering after

    Specify that the current rule context should operate after another named rule . You cannot use both .before() and .after() on the same rule .

    config.module.rules{}.rules : ChainedMap<Rule>
    config.module
      .rule(name)
        .rule(name)
          .after(otherName)
    // Example
    config.module
      .rule('css')
        .use('style')
          .loader('style-loader')
          .end()
        .rule('postcss')
          .resourceQuery(/postcss/)
          .after('css-loader')
          .use('postcss')
            .loader('postcss-loader')
            .end()
          .end()
        .rule('css-loader')
          .resourceQuery(/css-loader/)
          .use('css-loader')
            .loader('css-loader')

    Config module rules oneOfs (conditional rules):

    config.module.rules{}.oneOfs : ChainedMap<Rule>
    config.module
      .rule(name)
        .oneOf(name)
    // Example
    config.module
      .rule('css')
        .oneOf('inline')
          .resourceQuery(/inline/)
          .use('url')
            .loader('url-loader')
            .end()
          .end()
        .oneOf('external')
          .resourceQuery(/external/)
          .use('file')
            .loader('file-loader')

    Config module rules oneOfs (conditional rules): ordering before

    Specify that the current oneOf context should operate before another named oneOf . You cannot use both .before() and .after() on the same oneOf .

    config.module
      .rule(name)
        .oneOf(name)
          .before()
    // Example
    config.module
      .rule('scss')
        .test(/\.scss$/)
        .oneOf('normal')
          .use('sass')
            .loader('sass-loader')
            .end()
          .end()
        .oneOf('sass-vars')
          .before('normal')
          .resourceQuery(/\?sassvars/)
          .use('sass-vars')
            .loader('sass-vars-to-js-loader')

    Config module rules oneOfs (conditional rules): ordering after

    Specify that the current oneOf context should operate after another named oneOf . You cannot use both .before() and .after() on the same oneOf .

    config.module
      .rule(name)
        .oneOf(name)
          .after()
    // Example
    config.module
      .rule('scss')
        .test(/\.scss$/)
        .oneOf('vue')
          .resourceQuery(/\?vue/)
          .use('vue-style')
            .loader('vue-style-loader')
            .end()
          .end()
        .oneOf('normal')
          .use('sass')
            .loader('sass-loader')
            .end()
          .end()
        .oneOf('sass-vars')
          .after('vue')
          .resourceQuery(/\?sassvars/)
          .use('sass-vars')
            .loader('sass-vars-to-js-loader')

    Config module rules resolve

    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.

    config.module
      .rule(name)
        .resolve
    // Example
    config.module
      .rule('scss')
        .test(/\.scss$/)
        .resolve
          .symlinks(true)

    Merging Config

    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() .

    config.merge({ devtool: 'source-map' });
    config.get('devtool') // "source-map"
    config.merge({
      [key]: value,
      amd,
      bail,
      cache,
      context,
      devtool,
      externals,
      loader,
      mode,
      parallelism,
      profile,
      recordsPath,
      recordsInputPath,
      recordsOutputPath,
      stats,
      target,
      watch,
      watchOptions,
      entry: {
        [name]: [...values]
      plugin: {
        [name]: {
          plugin: WebpackPlugin,
          args: [...args],
          before,
          after
      devServer: {
        [key]: value,
        clientLogLevel,
        compress,
        contentBase,
        filename,
        headers,
        historyApiFallback,
        host,
        hot,
        hotOnly,
        https,
        inline,
        lazy,
        noInfo,
        overlay,
        port,
        proxy,
        quiet,
        setup,
        stats,
        watchContentBase
      node: {
        [key]: value
      optimization: {
        concatenateModules,
        flagIncludedChunks,
        mergeDuplicateChunks,
        minimize,
        minimizer: {
          [name]: {
            plugin: WebpackPlugin,
            args: [...args],
            before,
            after
        namedChunks,
        namedModules,
        nodeEnv,
        noEmitOnErrors,
        occurrenceOrder,
        portableRecords,
        providedExports,
        removeAvailableModules,
        removeEmptyChunks,
        runtimeChunk,
        sideEffects,
        splitChunks,
        usedExports,
      performance: {
        [key]: value,
        hints,
        maxEntrypointSize,
        maxAssetSize,
        assetFilter
      resolve: {
        [key]: value,
        alias: {
          [key]: value
        aliasFields: [...values],
        descriptionFields: [...values],
        extensions: [...values],
        mainFields: [...values],
        mainFiles: [...values],
        modules: [...values],
        plugin: {
          [name]: {
            plugin: WebpackPlugin,
            args: [...args],
            before,
            after
      resolveLoader: {
        [key]: value,
        alias: {
          [key]: value
        aliasFields: [...values],
        descriptionFields: [...values],
        extensions: [...values],
        mainFields: [...values],
        mainFiles: [...values],
        modules: [...values],
        moduleExtensions: [...values],
        packageMains: [...values],
        plugin: {
          [name]: {
            plugin: WebpackPlugin,
            args: [...args],
            before,
            after
      module: {
        [key]: value,
        rule: {
          [name]: {
            [key]: value,
            enforce,
            issuer,
            parser,
            resource,
            resourceQuery,
            test,
            include: [...paths],
            exclude: [...paths],
            rules: {
              [name]: Rule
            oneOf: {
              [name]: Rule
            use: {
              [name]: {
                loader: LoaderString,
                options: LoaderOptions,
                before,
                after
    

    Conditional configuration

    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.

    // Example: Only add minify plugin during production
    config
      .when(process.env.NODE_ENV === 'production', config => {
        config
          .plugin('minify')
          .use(BabiliWebpackPlugin);
      });
    // Example: Only add minify plugin during production,
    // otherwise set devtool to source-map
    config
      .when(process.env.NODE_ENV === 'production',
        config => config.plugin('minify').use(BabiliWebpackPlugin),
        config => config.devtool('source-map')
    

    Inspecting generated configuration

    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:

    config
      .module
        .rule('compile')
          .test(/\.js$/)
          .use('babel')
            .loader('babel-loader');
    config.toString();
      module: {
        rules: [
          /* config.module.rule('compile') */
            test: /\.js$/,
            use: [
              /* config.module.rule('compile').use('babel') */
                loader: 'babel-loader'
    

    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:

    const sass = require('sass');
    sass.__expression = `require('sass')`;
    class MyPlugin {}
    MyPlugin.__expression = `require('my-plugin')`;
    function myFunction () {}
    myFunction.__expression = `require('my-function')`;
    config
      .plugin('example')
        .use(MyPlugin, [{ fn: myFunction, implementation: sass, }]);
    config.toString();
      plugins: [
        new (require('my-plugin'))({
          fn: require('my-function'),
          implementation: require('sass')
    

    Plugins specified via their path will have their require() statement generated automatically:

    config
      .plugin('env')
        .use(require.resolve('webpack/lib/ProvidePlugin'), [{ jQuery: 'jquery' }])
    config.toString();
      plugins: [
        new (require('/foo/bar/src/node_modules/webpack/lib/EnvironmentPlugin.js'))(
            jQuery: 'jquery'
    

    You can also call toString as a static method on Config in order to modify the configuration object prior to stringifying.

    Config.toString({
      ...config.toConfig(),
      module: {
        defaultRules: [
            use: [
                loader: 'banner-loader',
                options: { prefix: 'banner-prefix.txt' },
      plugins: [
        /* config.plugin('foo') */
        new TestPlugin()
      module: {
        defaultRules: [
            use: [
                loader: 'banner-loader',
                options: {
                  prefix: 'banner-prefix.txt'