diff options
Diffstat (limited to 'node_modules/webpack-chain/README.md')
| -rw-r--r-- | node_modules/webpack-chain/README.md | 1288 |
1 files changed, 1288 insertions, 0 deletions
diff --git a/node_modules/webpack-chain/README.md b/node_modules/webpack-chain/README.md new file mode 100644 index 00000000..0dd025ad --- /dev/null +++ b/node_modules/webpack-chain/README.md @@ -0,0 +1,1288 @@ +# webpack-chain + +Use a chaining API to generate and simplify the modification of +webpack version 2-4 configurations. + +This documentation corresponds to v4 of webpack-chain. + +* [v3 docs](https://github.com/neutrinojs/webpack-chain/tree/v3) +* [v2 docs](https://github.com/neutrinojs/webpack-chain/tree/v2) +* [v1 docs](https://github.com/neutrinojs/webpack-chain/tree/v1.4.3) + +_Note: while webpack-chain is utilized extensively in Neutrino, this package is +completely standalone and can be used by any project._ + +## 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 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** + +```bash +yarn add --dev webpack-chain +``` + +**npm** + +```bash +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. + +```js +// 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. + +```js +// 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.** + +```js +// Remove all entries from a Map. +clear() +``` + +```js +// Remove a single entry from a Map given its key. +// key: * +delete(key) +``` + +```js +// Fetch the value from a Map located at the corresponding key. +// key: * +// returns: value +get(key) +``` + +```js +// 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) +``` + +```js +// Set a value on the Map stored at the `key` location. +// key: * +// value: * +set(key, value) +``` + +```js +// Returns `true` or `false` based on whether a Map as has a value set at a +// particular key. +// key: * +// returns: Boolean +has(key) +``` + +```js +// Returns an array of all the values stored in the Map. +// returns: Array +values() +``` + +```js +// 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() +```` + +```js +// 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) +``` + +```js +// 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) +``` + +```js +// 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.** + +```js +// Add/append a value to the end of a Set. +// value: * +add(value) +``` + +```js +// Add a value to the beginning of a Set. +// value: * +prepend(value) +``` + +```js +// Remove all values from a Set. +clear() +``` + +```js +// Remove a specific value from a Set. +// value: * +delete(value) +``` + +```js +// Returns `true` or `false` based on whether or not the +// backing Set contains the specified value. +// value: * +// returns: Boolean +has(value) +``` + +```js +// Returns an array of values contained in the backing Set. +// returns: Array +values() +``` + +```js +// Concatenates the given array to the end of the backing Set. +// arr: Array +merge(arr) +``` + +```js +// 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) +``` + +```js +// 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: + +```js +// 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. + +```js +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](https://webpack.js.org/configuration/). + +```js +Config : ChainedMap +``` + +#### Config shorthand methods + +```js +config + .amd(amd) + .bail(bail) + .cache(cache) + .devtool(devtool) + .context(context) + .externals(externals) + .loader(loader) + .mode(mode) + .parallelism(parallelism) + .profile(profile) + .recordsPath(recordsPath) + .recordsInputPath(recordsInputPath) + .recordsOutputPath(recordsOutputPath) + .stats(stats) + .target(target) + .watch(watch) + .watchOptions(watchOptions) +``` + +#### Config entryPoints + +```js +// 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 + +```js +config.output : ChainedMap + +config.output + .auxiliaryComment(auxiliaryComment) + .chunkFilename(chunkFilename) + .chunkLoadTimeout(chunkLoadTimeout) + .crossOriginLoading(crossOriginLoading) + .devtoolFallbackModuleFilenameTemplate(devtoolFallbackModuleFilenameTemplate) + .devtoolLineToLine(devtoolLineToLine) + .devtoolModuleFilenameTemplate(devtoolModuleFilenameTemplate) + .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 + +```js +config.resolve : ChainedMap + +config.resolve + .cachePredicate(cachePredicate) + .cacheWithContext(cacheWithContext) + .enforceExtension(enforceExtension) + .enforceModuleExtension(enforceModuleExtension) + .unsafeCache(unsafeCache) + .symlinks(symlinks) +``` + +#### Config resolve alias + +```js +config.resolve.alias : ChainedMap + +config.resolve.alias + .set(key, value) + .set(key, value) + .delete(key) + .clear() +``` + +#### Config resolve modules + +```js +config.resolve.modules : ChainedSet + +config.resolve.modules + .add(value) + .prepend(value) + .clear() +``` + +#### Config resolve aliasFields + +```js +config.resolve.aliasFields : ChainedSet + +config.resolve.aliasFields + .add(value) + .prepend(value) + .clear() +``` + +#### Config resolve descriptionFields + +```js +config.resolve.descriptionFields : ChainedSet + +config.resolve.descriptionFields + .add(value) + .prepend(value) + .clear() +``` + +#### Config resolve extensions + +```js +config.resolve.extensions : ChainedSet + +config.resolve.extensions + .add(value) + .prepend(value) + .clear() +``` + +#### Config resolve mainFields + +```js +config.resolve.mainFields : ChainedSet + +config.resolve.mainFields + .add(value) + .prepend(value) + .clear() +``` + +#### Config resolve mainFiles + +```js +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 + +```js +config.resolveLoader.moduleExtensions : ChainedSet + +config.resolveLoader.moduleExtensions + .add(value) + .prepend(value) + .clear() +``` + +#### Config resolveLoader packageMains + +```js +config.resolveLoader.packageMains : ChainedSet + +config.resolveLoader.packageMains + .add(value) + .prepend(value) + .clear() +``` + +#### Config performance: shorthand methods + +```js +config.performance : ChainedMap + +config.performance + .hints(hints) + .maxEntrypointSize(maxEntrypointSize) + .maxAssetSize(maxAssetSize) + .assetFilter(assetFilter) +``` + +#### Configuring optimizations: shorthand methods + +```js +config.optimization : ChainedMap + +config.optimization + .concatenateModules(concatenateModules) + .flagIncludedChunks(flagIncludedChunks) + .mergeDuplicateChunks(mergeDuplicateChunks) + .minimize(minimize) + .minimizer(minimizer) + .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 plugins + +```js +// 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._ + +```js +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 + +```js +config + .plugin(name) + .tap(args => newArgs) + +// Example +config + .plugin('env') + .tap(args => [...args, 'SECRET_KEY']); +``` + +#### Config plugins: modify instantiation + +```js +config + .plugin(name) + .init((Plugin, args) => new Plugin(...args)); +``` + +#### Config plugins: removing + +```js +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. + +```js +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. + +```js +config + .plugin(name) + .after(otherName) + +// Example + +config + .plugin('html-template') + .after('script-ext') + .use(HtmlWebpackTemplate) + .end() + .plugin('script-ext') + .use(ScriptExtWebpackPlugin); +``` + +#### Config resolve plugins + +```js +// 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._ + +```js +config.resolve + .plugin(name) + .use(WebpackPlugin, args) +``` + +#### Config resolve plugins: modify arguments + +```js +config.resolve + .plugin(name) + .tap(args => newArgs) +``` + +#### Config resolve plugins: modify instantiation + +```js +config.resolve + .plugin(name) + .init((Plugin, args) => new Plugin(...args)) +``` + +#### Config resolve plugins: removing + +```js +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. + +```js +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. + +```js +config.resolve + .plugin(name) + .after(otherName) + +// Example + +config.resolve + .plugin('beta') + .after('alpha') + .use(BetaWebpackTemplate) + .end() + .plugin('alpha') + .use(AlphaWebpackPlugin); +``` + +#### Config node + +```js +config.node : ChainedMap + +config.node + .set('__dirname', 'mock') + .set('__filename', 'mock'); +``` + +#### Config devServer + +```js +config.devServer : ChainedMap +``` + +#### Config devServer allowedHosts + +```js +config.devServer.allowedHosts : ChainedSet + +config.devServer.allowedHosts + .add(value) + .prepend(value) + .clear() +``` + +#### Config devServer: shorthand methods + +```js +config.devServer + .bonjour(bonjour) + .clientLogLevel(clientLogLevel) + .color(color) + .compress(compress) + .contentBase(contentBase) + .disableHostCheck(disableHostCheck) + .filename(filename) + .headers(headers) + .historyApiFallback(historyApiFallback) + .host(host) + .hot(hot) + .hotOnly(hotOnly) + .https(https) + .inline(inline) + .info(info) + .lazy(lazy) + .noInfo(noInfo) + .open(open) + .openPage(openPage) + .overlay(overlay) + .pfx(pfx) + .pfxPassphrase(pfsPassphrase) + .port(port) + .progress(progress) + .proxy(proxy) + .public(public) + .publicPath(publicPath) + .quiet(quiet) + .setup(setup) + .socket(socket) + .staticOptions(staticOptions) + .stats(stats) + .stdin(stdin) + .useLocalIp(useLocalIp) + .watchContentBase(watchContentBase) + .watchOptions(watchOptions) +``` + +#### Config module + +```js +config.module : ChainedMap +``` + +#### Config module: shorthand methods + +```js +config.module : ChainedMap + +config.module + .noParse(noParse) +``` + +#### Config module rules: shorthand methods + +```js +config.module.rules : ChainedMap + +config.module + .rule(name) + .test(test) + .pre() + .post() + .enforce(preOrPost) +``` + +#### Config module rules uses (loaders): creating + +```js +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 + +```js +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 oneOfs (conditional rules): + +```js +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') +``` + +--- + +### 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 that +this is not a webpack configuration object, but you may transform a webpack +configuration object before providing it to webpack-chain to match its layout. + +```js +config.merge({ devtool: 'source-map' }); + +config.get('devtool') // "source-map" +``` + +```js +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 + }, + + optimizations: { + concatenateModules, + flagIncludedChunks, + mergeDuplicateChunks, + minimize, + minimizer, + 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], + + 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. + +```js +// Example: Only add minify plugin during production +config + .when(process.env.NODE_ENV === 'production', config => { + config + .plugin('minify') + .use(BabiliWebpackPlugin); + }); +``` + +```js +// 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: + +``` js +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 functions and plugins that need to be required. In order to +generate usable config, you can customize how functions and plugins are +stringified by setting a special `__expression` property on them: + +``` js +class MyPlugin {} +MyPlugin.__expression = `require('my-plugin')`; + +function myFunction () {} +myFunction.__expression = `require('my-function')`; + +config + .plugin('example') + .use(MyPlugin, [{ fn: myFunction }]); + +config.toString(); + +/* +{ + plugins: [ + new (require('my-plugin'))({ + fn: require('my-function') + }) + ] +} +*/ +``` + +Plugins specified via their path will have their `require()` statement generated +automatically: + +``` js +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. + +```js +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' + } + } + ] + } + ] + } +} +*/ +``` |
