You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1558 lines
32 KiB

3 months ago
  1. # webpack-chain
  2. [![NPM version][npm-image]][npm-url]
  3. [![NPM downloads][npm-downloads]][npm-url]
  4. [![Build Status][travis-image]][travis-url]
  5. Use a chaining API to generate and simplify the modification of
  6. webpack version 2-4 configurations.
  7. This documentation corresponds to v6 of webpack-chain. For previous versions, see:
  8. * [v5 docs](https://github.com/neutrinojs/webpack-chain/tree/v5)
  9. * [v4 docs](https://github.com/neutrinojs/webpack-chain/tree/v4)
  10. * [v3 docs](https://github.com/neutrinojs/webpack-chain/tree/v3)
  11. * [v2 docs](https://github.com/neutrinojs/webpack-chain/tree/v2)
  12. * [v1 docs](https://github.com/neutrinojs/webpack-chain/tree/v1)
  13. _Note: while webpack-chain is utilized extensively in Neutrino, this package is
  14. completely standalone and can be used by any project._
  15. **[Chinese docs(中文文档)](https://github.com/Yatoo2018/webpack-chain/tree/zh-cmn-Hans)**
  16. ## Introduction
  17. webpack's core configuration is based on creating and modifying a
  18. potentially unwieldy JavaScript object. While this is OK for configurations
  19. on individual projects, trying to share these objects across projects and
  20. make subsequent modifications gets messy, as you need to have a deep
  21. understanding of the underlying object structure to make those changes.
  22. `webpack-chain` attempts to improve this process by providing a chainable or
  23. fluent API for creating and modifying webpack configurations. Key portions
  24. of the API can be referenced by user-specified names, which helps to
  25. standardize how to modify a configuration across projects.
  26. This is easier explained through the examples following.
  27. ## Installation
  28. `webpack-chain` requires Node.js v6.9 and higher. `webpack-chain` also
  29. only creates configuration objects designed for use in webpack versions 2, 3,
  30. and 4.
  31. You may install this package using either Yarn or npm (choose one):
  32. **Yarn**
  33. ```bash
  34. yarn add --dev webpack-chain
  35. ```
  36. **npm**
  37. ```bash
  38. npm install --save-dev webpack-chain
  39. ```
  40. ## Getting Started
  41. Once you have `webpack-chain` installed, you can start creating a
  42. webpack configuration. For this guide, our example base configuration will
  43. be `webpack.config.js` in the root of our project directory.
  44. ```js
  45. // Require the webpack-chain module. This module exports a single
  46. // constructor function for creating a configuration API.
  47. const Config = require('webpack-chain');
  48. // Instantiate the configuration with a new API
  49. const config = new Config();
  50. // Make configuration changes using the chain API.
  51. // Every API call tracks a change to the stored configuration.
  52. config
  53. // Interact with entry points
  54. .entry('index')
  55. .add('src/index.js')
  56. .end()
  57. // Modify output settings
  58. .output
  59. .path('dist')
  60. .filename('[name].bundle.js');
  61. // Create named rules which can be modified later
  62. config.module
  63. .rule('lint')
  64. .test(/\.js$/)
  65. .pre()
  66. .include
  67. .add('src')
  68. .end()
  69. // Even create named uses (loaders)
  70. .use('eslint')
  71. .loader('eslint-loader')
  72. .options({
  73. rules: {
  74. semi: 'off'
  75. }
  76. });
  77. config.module
  78. .rule('compile')
  79. .test(/\.js$/)
  80. .include
  81. .add('src')
  82. .add('test')
  83. .end()
  84. .use('babel')
  85. .loader('babel-loader')
  86. .options({
  87. presets: [
  88. ['@babel/preset-env', { modules: false }]
  89. ]
  90. });
  91. // Create named plugins too!
  92. config
  93. .plugin('clean')
  94. .use(CleanPlugin, [['dist'], { root: '/dir' }]);
  95. // Export the completed configuration object to be consumed by webpack
  96. module.exports = config.toConfig();
  97. ```
  98. Having shared configurations is also simple. Just export the configuration
  99. and call `.toConfig()` prior to passing to webpack.
  100. ```js
  101. // webpack.core.js
  102. const Config = require('webpack-chain');
  103. const config = new Config();
  104. // Make configuration shared across targets
  105. // ...
  106. module.exports = config;
  107. // webpack.dev.js
  108. const config = require('./webpack.core');
  109. // Dev-specific configuration
  110. // ...
  111. module.exports = config.toConfig();
  112. // webpack.prod.js
  113. const config = require('./webpack.core');
  114. // Production-specific configuration
  115. // ...
  116. module.exports = config.toConfig();
  117. ```
  118. ## ChainedMap
  119. One of the core API interfaces in webpack-chain is a `ChainedMap`. A
  120. `ChainedMap` operates similar to a JavaScript Map, with some conveniences for
  121. chaining and generating configuration. If a property is marked as being a
  122. `ChainedMap`, it will have an API and methods as described below:
  123. **Unless stated otherwise, these methods will return the `ChainedMap`, allowing
  124. you to chain these methods.**
  125. ```js
  126. // Remove all entries from a Map.
  127. clear()
  128. ```
  129. ```js
  130. // Remove a single entry from a Map given its key.
  131. // key: *
  132. delete(key)
  133. ```
  134. ```js
  135. // Fetch the value from a Map located at the corresponding key.
  136. // key: *
  137. // returns: value
  138. get(key)
  139. ```
  140. ```js
  141. // Fetch the value from a Map located at the corresponding key.
  142. // If the key is missing, the key is set to the result of function fn.
  143. // key: *
  144. // fn: Function () -> value
  145. // returns: value
  146. getOrCompute(key, fn)
  147. ```
  148. ```js
  149. // Set a value on the Map stored at the `key` location.
  150. // key: *
  151. // value: *
  152. set(key, value)
  153. ```
  154. ```js
  155. // Returns `true` or `false` based on whether a Map as has a value set at a
  156. // particular key.
  157. // key: *
  158. // returns: Boolean
  159. has(key)
  160. ```
  161. ```js
  162. // Returns an array of all the values stored in the Map.
  163. // returns: Array
  164. values()
  165. ```
  166. ```js
  167. // Returns an object of all the entries in the backing Map
  168. // where the key is the object property, and the value
  169. // corresponding to the key. Will return `undefined` if the backing
  170. // Map is empty.
  171. // This will order properties by their name if the value is
  172. // a ChainedMap that used .before() or .after().
  173. // returns: Object, undefined if empty
  174. entries()
  175. ```
  176. ```js
  177. // Provide an object which maps its properties and values
  178. // into the backing Map as keys and values.
  179. // You can also provide an array as the second argument
  180. // for property names to omit from being merged.
  181. // obj: Object
  182. // omit: Optional Array
  183. merge(obj, omit)
  184. ```
  185. ```js
  186. // Execute a function against the current configuration context
  187. // handler: Function -> ChainedMap
  188. // A function which is given a single argument of the ChainedMap instance
  189. batch(handler)
  190. ```
  191. ```js
  192. // Conditionally execute a function to continue configuration
  193. // condition: Boolean
  194. // whenTruthy: Function -> ChainedMap
  195. // invoked when condition is truthy, given a single argument of the ChainedMap instance
  196. // whenFalsy: Optional Function -> ChainedMap
  197. // invoked when condition is falsy, given a single argument of the ChainedMap instance
  198. when(condition, whenTruthy, whenFalsy)
  199. ```
  200. ## ChainedSet
  201. Another of the core API interfaces in webpack-chain is a `ChainedSet`. A
  202. `ChainedSet` operates similar to a JavaScript Set, with some conveniences for
  203. chaining and generating configuration. If a property is marked as being a
  204. `ChainedSet`, it will have an API and methods as described below:
  205. **Unless stated otherwise, these methods will return the `ChainedSet`, allowing
  206. you to chain these methods.**
  207. ```js
  208. // Add/append a value to the end of a Set.
  209. // value: *
  210. add(value)
  211. ```
  212. ```js
  213. // Add a value to the beginning of a Set.
  214. // value: *
  215. prepend(value)
  216. ```
  217. ```js
  218. // Remove all values from a Set.
  219. clear()
  220. ```
  221. ```js
  222. // Remove a specific value from a Set.
  223. // value: *
  224. delete(value)
  225. ```
  226. ```js
  227. // Returns `true` or `false` based on whether or not the
  228. // backing Set contains the specified value.
  229. // value: *
  230. // returns: Boolean
  231. has(value)
  232. ```
  233. ```js
  234. // Returns an array of values contained in the backing Set.
  235. // returns: Array
  236. values()
  237. ```
  238. ```js
  239. // Concatenates the given array to the end of the backing Set.
  240. // arr: Array
  241. merge(arr)
  242. ```
  243. ```js
  244. // Execute a function against the current configuration context
  245. // handler: Function -> ChainedSet
  246. // A function which is given a single argument of the ChainedSet instance
  247. batch(handler)
  248. ```
  249. ```js
  250. // Conditionally execute a function to continue configuration
  251. // condition: Boolean
  252. // whenTruthy: Function -> ChainedSet
  253. // invoked when condition is truthy, given a single argument of the ChainedSet instance
  254. // whenFalsy: Optional Function -> ChainedSet
  255. // invoked when condition is falsy, given a single argument of the ChainedSet instance
  256. when(condition, whenTruthy, whenFalsy)
  257. ```
  258. ## Shorthand methods
  259. A number of shorthand methods exist for setting a value on a `ChainedMap`
  260. with the same key as the shorthand method name.
  261. For example, `devServer.hot` is a shorthand method, so it can be used as:
  262. ```js
  263. // A shorthand method for setting a value on a ChainedMap
  264. devServer.hot(true);
  265. // This would be equivalent to:
  266. devServer.set('hot', true);
  267. ```
  268. A shorthand method is chainable, so calling it will return the original
  269. instance, allowing you to continue to chain.
  270. ### Config
  271. Create a new configuration object.
  272. ```js
  273. const Config = require('webpack-chain');
  274. const config = new Config();
  275. ```
  276. Moving to deeper points in the API will change the context of what you
  277. are modifying. You can move back to the higher context by either referencing
  278. the top-level `config` again, or by calling `.end()` to move up one level.
  279. If you are familiar with jQuery, `.end()` works similarly. All API calls
  280. will return the API instance at the current context unless otherwise
  281. specified. This is so you may chain API calls continuously if desired.
  282. For details on the specific values that are valid for all shorthand and
  283. low-level methods, please refer to their corresponding name in the
  284. [webpack docs hierarchy](https://webpack.js.org/configuration/).
  285. ```js
  286. Config : ChainedMap
  287. ```
  288. #### Config shorthand methods
  289. ```js
  290. config
  291. .amd(amd)
  292. .bail(bail)
  293. .cache(cache)
  294. .devtool(devtool)
  295. .context(context)
  296. .externals(externals)
  297. .loader(loader)
  298. .name(name)
  299. .mode(mode)
  300. .parallelism(parallelism)
  301. .profile(profile)
  302. .recordsPath(recordsPath)
  303. .recordsInputPath(recordsInputPath)
  304. .recordsOutputPath(recordsOutputPath)
  305. .stats(stats)
  306. .target(target)
  307. .watch(watch)
  308. .watchOptions(watchOptions)
  309. ```
  310. #### Config entryPoints
  311. ```js
  312. // Backed at config.entryPoints : ChainedMap
  313. config.entry(name) : ChainedSet
  314. config
  315. .entry(name)
  316. .add(value)
  317. .add(value)
  318. config
  319. .entry(name)
  320. .clear()
  321. // Using low-level config.entryPoints:
  322. config.entryPoints
  323. .get(name)
  324. .add(value)
  325. .add(value)
  326. config.entryPoints
  327. .get(name)
  328. .clear()
  329. ```
  330. #### Config output: shorthand methods
  331. ```js
  332. config.output : ChainedMap
  333. config.output
  334. .auxiliaryComment(auxiliaryComment)
  335. .chunkFilename(chunkFilename)
  336. .chunkLoadTimeout(chunkLoadTimeout)
  337. .crossOriginLoading(crossOriginLoading)
  338. .devtoolFallbackModuleFilenameTemplate(devtoolFallbackModuleFilenameTemplate)
  339. .devtoolLineToLine(devtoolLineToLine)
  340. .devtoolModuleFilenameTemplate(devtoolModuleFilenameTemplate)
  341. .devtoolNamespace(devtoolNamespace)
  342. .filename(filename)
  343. .hashFunction(hashFunction)
  344. .hashDigest(hashDigest)
  345. .hashDigestLength(hashDigestLength)
  346. .hashSalt(hashSalt)
  347. .hotUpdateChunkFilename(hotUpdateChunkFilename)
  348. .hotUpdateFunction(hotUpdateFunction)
  349. .hotUpdateMainFilename(hotUpdateMainFilename)
  350. .jsonpFunction(jsonpFunction)
  351. .library(library)
  352. .libraryExport(libraryExport)
  353. .libraryTarget(libraryTarget)
  354. .path(path)
  355. .pathinfo(pathinfo)
  356. .publicPath(publicPath)
  357. .sourceMapFilename(sourceMapFilename)
  358. .sourcePrefix(sourcePrefix)
  359. .strictModuleExceptionHandling(strictModuleExceptionHandling)
  360. .umdNamedDefine(umdNamedDefine)
  361. ```
  362. #### Config resolve: shorthand methods
  363. ```js
  364. config.resolve : ChainedMap
  365. config.resolve
  366. .cachePredicate(cachePredicate)
  367. .cacheWithContext(cacheWithContext)
  368. .enforceExtension(enforceExtension)
  369. .enforceModuleExtension(enforceModuleExtension)
  370. .unsafeCache(unsafeCache)
  371. .symlinks(symlinks)
  372. ```
  373. #### Config resolve alias
  374. ```js
  375. config.resolve.alias : ChainedMap
  376. config.resolve.alias
  377. .set(key, value)
  378. .set(key, value)
  379. .delete(key)
  380. .clear()
  381. ```
  382. #### Config resolve modules
  383. ```js
  384. config.resolve.modules : ChainedSet
  385. config.resolve.modules
  386. .add(value)
  387. .prepend(value)
  388. .clear()
  389. ```
  390. #### Config resolve aliasFields
  391. ```js
  392. config.resolve.aliasFields : ChainedSet
  393. config.resolve.aliasFields
  394. .add(value)
  395. .prepend(value)
  396. .clear()
  397. ```
  398. #### Config resolve descriptionFields
  399. ```js
  400. config.resolve.descriptionFields : ChainedSet
  401. config.resolve.descriptionFields
  402. .add(value)
  403. .prepend(value)
  404. .clear()
  405. ```
  406. #### Config resolve extensions
  407. ```js
  408. config.resolve.extensions : ChainedSet
  409. config.resolve.extensions
  410. .add(value)
  411. .prepend(value)
  412. .clear()
  413. ```
  414. #### Config resolve mainFields
  415. ```js
  416. config.resolve.mainFields : ChainedSet
  417. config.resolve.mainFields
  418. .add(value)
  419. .prepend(value)
  420. .clear()
  421. ```
  422. #### Config resolve mainFiles
  423. ```js
  424. config.resolve.mainFiles : ChainedSet
  425. config.resolve.mainFiles
  426. .add(value)
  427. .prepend(value)
  428. .clear()
  429. ```
  430. #### Config resolveLoader
  431. The API for `config.resolveLoader` is identical to `config.resolve` with
  432. the following additions:
  433. #### Config resolveLoader moduleExtensions
  434. ```js
  435. config.resolveLoader.moduleExtensions : ChainedSet
  436. config.resolveLoader.moduleExtensions
  437. .add(value)
  438. .prepend(value)
  439. .clear()
  440. ```
  441. #### Config resolveLoader packageMains
  442. ```js
  443. config.resolveLoader.packageMains : ChainedSet
  444. config.resolveLoader.packageMains
  445. .add(value)
  446. .prepend(value)
  447. .clear()
  448. ```
  449. #### Config performance: shorthand methods
  450. ```js
  451. config.performance : ChainedMap
  452. config.performance
  453. .hints(hints)
  454. .maxEntrypointSize(maxEntrypointSize)
  455. .maxAssetSize(maxAssetSize)
  456. .assetFilter(assetFilter)
  457. ```
  458. #### Configuring optimizations: shorthand methods
  459. ```js
  460. config.optimization : ChainedMap
  461. config.optimization
  462. .concatenateModules(concatenateModules)
  463. .flagIncludedChunks(flagIncludedChunks)
  464. .mergeDuplicateChunks(mergeDuplicateChunks)
  465. .minimize(minimize)
  466. .namedChunks(namedChunks)
  467. .namedModules(namedModules)
  468. .nodeEnv(nodeEnv)
  469. .noEmitOnErrors(noEmitOnErrors)
  470. .occurrenceOrder(occurrenceOrder)
  471. .portableRecords(portableRecords)
  472. .providedExports(providedExports)
  473. .removeAvailableModules(removeAvailableModules)
  474. .removeEmptyChunks(removeEmptyChunks)
  475. .runtimeChunk(runtimeChunk)
  476. .sideEffects(sideEffects)
  477. .splitChunks(splitChunks)
  478. .usedExports(usedExports)
  479. ```
  480. #### Config optimization minimizers
  481. ```js
  482. // Backed at config.optimization.minimizers
  483. config.optimization
  484. .minimizer(name) : ChainedMap
  485. ```
  486. #### Config optimization minimizers: adding
  487. _NOTE: Do not use `new` to create the minimizer plugin, as this will be done for you._
  488. ```js
  489. config.optimization
  490. .minimizer(name)
  491. .use(WebpackPlugin, args)
  492. // Examples
  493. config.optimization
  494. .minimizer('css')
  495. .use(OptimizeCSSAssetsPlugin, [{ cssProcessorOptions: { safe: true } }])
  496. // Minimizer plugins can also be specified by their path, allowing the expensive require()s to be
  497. // skipped in cases where the plugin or webpack configuration won't end up being used.
  498. config.optimization
  499. .minimizer('css')
  500. .use(require.resolve('optimize-css-assets-webpack-plugin'), [{ cssProcessorOptions: { safe: true } }])
  501. ```
  502. #### Config optimization minimizers: modify arguments
  503. ```js
  504. config.optimization
  505. .minimizer(name)
  506. .tap(args => newArgs)
  507. // Example
  508. config.optimization
  509. .minimizer('css')
  510. .tap(args => [...args, { cssProcessorOptions: { safe: false } }])
  511. ```
  512. #### Config optimization minimizers: modify instantiation
  513. ```js
  514. config.optimization
  515. .minimizer(name)
  516. .init((Plugin, args) => new Plugin(...args));
  517. ```
  518. #### Config optimization minimizers: removing
  519. ```js
  520. config.optimization.minimizers.delete(name)
  521. ```
  522. #### Config plugins
  523. ```js
  524. // Backed at config.plugins
  525. config.plugin(name) : ChainedMap
  526. ```
  527. #### Config plugins: adding
  528. _NOTE: Do not use `new` to create the plugin, as this will be done for you._
  529. ```js
  530. config
  531. .plugin(name)
  532. .use(WebpackPlugin, args)
  533. // Examples
  534. config
  535. .plugin('hot')
  536. .use(webpack.HotModuleReplacementPlugin);
  537. // Plugins can also be specified by their path, allowing the expensive require()s to be
  538. // skipped in cases where the plugin or webpack configuration won't end up being used.
  539. config
  540. .plugin('env')
  541. .use(require.resolve('webpack/lib/EnvironmentPlugin'), [{ 'VAR': false }]);
  542. ```
  543. #### Config plugins: modify arguments
  544. ```js
  545. config
  546. .plugin(name)
  547. .tap(args => newArgs)
  548. // Example
  549. config
  550. .plugin('env')
  551. .tap(args => [...args, 'SECRET_KEY']);
  552. ```
  553. #### Config plugins: modify instantiation
  554. ```js
  555. config
  556. .plugin(name)
  557. .init((Plugin, args) => new Plugin(...args));
  558. ```
  559. #### Config plugins: removing
  560. ```js
  561. config.plugins.delete(name)
  562. ```
  563. #### Config plugins: ordering before
  564. Specify that the current `plugin` context should operate before another named
  565. `plugin`. You cannot use both `.before()` and `.after()` on the same plugin.
  566. ```js
  567. config
  568. .plugin(name)
  569. .before(otherName)
  570. // Example
  571. config
  572. .plugin('html-template')
  573. .use(HtmlWebpackTemplate)
  574. .end()
  575. .plugin('script-ext')
  576. .use(ScriptExtWebpackPlugin)
  577. .before('html-template');
  578. ```
  579. #### Config plugins: ordering after
  580. Specify that the current `plugin` context should operate after another named
  581. `plugin`. You cannot use both `.before()` and `.after()` on the same plugin.
  582. ```js
  583. config
  584. .plugin(name)
  585. .after(otherName)
  586. // Example
  587. config
  588. .plugin('html-template')
  589. .after('script-ext')
  590. .use(HtmlWebpackTemplate)
  591. .end()
  592. .plugin('script-ext')
  593. .use(ScriptExtWebpackPlugin);
  594. ```
  595. #### Config resolve plugins
  596. ```js
  597. // Backed at config.resolve.plugins
  598. config.resolve.plugin(name) : ChainedMap
  599. ```
  600. #### Config resolve plugins: adding
  601. _NOTE: Do not use `new` to create the plugin, as this will be done for you._
  602. ```js
  603. config.resolve
  604. .plugin(name)
  605. .use(WebpackPlugin, args)
  606. ```
  607. #### Config resolve plugins: modify arguments
  608. ```js
  609. config.resolve
  610. .plugin(name)
  611. .tap(args => newArgs)
  612. ```
  613. #### Config resolve plugins: modify instantiation
  614. ```js
  615. config.resolve
  616. .plugin(name)
  617. .init((Plugin, args) => new Plugin(...args))
  618. ```
  619. #### Config resolve plugins: removing
  620. ```js
  621. config.resolve.plugins.delete(name)
  622. ```
  623. #### Config resolve plugins: ordering before
  624. Specify that the current `plugin` context should operate before another named
  625. `plugin`. You cannot use both `.before()` and `.after()` on the same resolve
  626. plugin.
  627. ```js
  628. config.resolve
  629. .plugin(name)
  630. .before(otherName)
  631. // Example
  632. config.resolve
  633. .plugin('beta')
  634. .use(BetaWebpackPlugin)
  635. .end()
  636. .plugin('alpha')
  637. .use(AlphaWebpackPlugin)
  638. .before('beta');
  639. ```
  640. #### Config resolve plugins: ordering after
  641. Specify that the current `plugin` context should operate after another named
  642. `plugin`. You cannot use both `.before()` and `.after()` on the same resolve
  643. plugin.
  644. ```js
  645. config.resolve
  646. .plugin(name)
  647. .after(otherName)
  648. // Example
  649. config.resolve
  650. .plugin('beta')
  651. .after('alpha')
  652. .use(BetaWebpackTemplate)
  653. .end()
  654. .plugin('alpha')
  655. .use(AlphaWebpackPlugin);
  656. ```
  657. #### Config node
  658. ```js
  659. config.node : ChainedMap
  660. config.node
  661. .set('__dirname', 'mock')
  662. .set('__filename', 'mock');
  663. ```
  664. #### Config devServer
  665. ```js
  666. config.devServer : ChainedMap
  667. ```
  668. #### Config devServer allowedHosts
  669. ```js
  670. config.devServer.allowedHosts : ChainedSet
  671. config.devServer.allowedHosts
  672. .add(value)
  673. .prepend(value)
  674. .clear()
  675. ```
  676. #### Config devServer: shorthand methods
  677. ```js
  678. config.devServer
  679. .after(after)
  680. .before(before)
  681. .bonjour(bonjour)
  682. .clientLogLevel(clientLogLevel)
  683. .color(color)
  684. .compress(compress)
  685. .contentBase(contentBase)
  686. .disableHostCheck(disableHostCheck)
  687. .filename(filename)
  688. .headers(headers)
  689. .historyApiFallback(historyApiFallback)
  690. .host(host)
  691. .hot(hot)
  692. .hotOnly(hotOnly)
  693. .http2(http2)
  694. .https(https)
  695. .index(index)
  696. .info(info)
  697. .inline(inline)
  698. .lazy(lazy)
  699. .mimeTypes(mimeTypes)
  700. .noInfo(noInfo)
  701. .open(open)
  702. .openPage(openPage)
  703. .overlay(overlay)
  704. .pfx(pfx)
  705. .pfxPassphrase(pfxPassphrase)
  706. .port(port)
  707. .progress(progress)
  708. .proxy(proxy)
  709. .public(public)
  710. .publicPath(publicPath)
  711. .quiet(quiet)
  712. .setup(setup)
  713. .socket(socket)
  714. .sockHost(sockHost)
  715. .sockPath(sockPath)
  716. .sockPort(sockPort)
  717. .staticOptions(staticOptions)
  718. .stats(stats)
  719. .stdin(stdin)
  720. .useLocalIp(useLocalIp)
  721. .watchContentBase(watchContentBase)
  722. .watchOptions(watchOptions)
  723. .writeToDisk(writeToDisk)
  724. ```
  725. #### Config module
  726. ```js
  727. config.module : ChainedMap
  728. ```
  729. #### Config module: shorthand methods
  730. ```js
  731. config.module : ChainedMap
  732. config.module
  733. .noParse(noParse)
  734. ```
  735. #### Config module rules: shorthand methods
  736. ```js
  737. config.module.rules : ChainedMap
  738. config.module
  739. .rule(name)
  740. .test(test)
  741. .pre()
  742. .post()
  743. .enforce(preOrPost)
  744. ```
  745. #### Config module rules uses (loaders): creating
  746. ```js
  747. config.module.rules{}.uses : ChainedMap
  748. config.module
  749. .rule(name)
  750. .use(name)
  751. .loader(loader)
  752. .options(options)
  753. // Example
  754. config.module
  755. .rule('compile')
  756. .use('babel')
  757. .loader('babel-loader')
  758. .options({ presets: ['@babel/preset-env'] });
  759. ```
  760. #### Config module rules uses (loaders): modifying options
  761. ```js
  762. config.module
  763. .rule(name)
  764. .use(name)
  765. .tap(options => newOptions)
  766. // Example
  767. config.module
  768. .rule('compile')
  769. .use('babel')
  770. .tap(options => merge(options, {
  771. plugins: ['@babel/plugin-proposal-class-properties']
  772. }));
  773. ```
  774. #### Config module rules nested rules:
  775. ```js
  776. config.module.rules{}.rules : ChainedMap<Rule>
  777. config.module
  778. .rule(name)
  779. .rule(name)
  780. // Example
  781. config.module
  782. .rule('css')
  783. .test(/\.css$/)
  784. .use('style')
  785. .loader('style-loader')
  786. .end()
  787. .rule('postcss')
  788. .resourceQuery(/postcss/)
  789. .use('postcss')
  790. .loader('postcss-loader')
  791. ```
  792. #### Config module rules nested rules: ordering before
  793. Specify that the current `rule` context should operate before another named
  794. `rule`. You cannot use both `.before()` and `.after()` on the same `rule`.
  795. ```js
  796. config.module.rules{}.rules : ChainedMap<Rule>
  797. config.module
  798. .rule(name)
  799. .rule(name)
  800. .before(otherName)
  801. // Example
  802. config.module
  803. .rule('css')
  804. .use('style')
  805. .loader('style-loader')
  806. .end()
  807. .rule('postcss')
  808. .resourceQuery(/postcss/)
  809. .use('postcss')
  810. .loader('postcss-loader')
  811. .end()
  812. .end()
  813. .rule('css-loader')
  814. .resourceQuery(/css-loader/)
  815. .before('postcss')
  816. .use('css-loader')
  817. .loader('css-loader')
  818. ```
  819. #### Config module rules nested rules: ordering after
  820. Specify that the current `rule` context should operate after another named
  821. `rule`. You cannot use both `.before()` and `.after()` on the same `rule`.
  822. ```js
  823. config.module.rules{}.rules : ChainedMap<Rule>
  824. config.module
  825. .rule(name)
  826. .rule(name)
  827. .after(otherName)
  828. // Example
  829. config.module
  830. .rule('css')
  831. .use('style')
  832. .loader('style-loader')
  833. .end()
  834. .rule('postcss')
  835. .resourceQuery(/postcss/)
  836. .after('css-loader')
  837. .use('postcss')
  838. .loader('postcss-loader')
  839. .end()
  840. .end()
  841. .rule('css-loader')
  842. .resourceQuery(/css-loader/)
  843. .use('css-loader')
  844. .loader('css-loader')
  845. ```
  846. #### Config module rules oneOfs (conditional rules):
  847. ```js
  848. config.module.rules{}.oneOfs : ChainedMap<Rule>
  849. config.module
  850. .rule(name)
  851. .oneOf(name)
  852. // Example
  853. config.module
  854. .rule('css')
  855. .oneOf('inline')
  856. .resourceQuery(/inline/)
  857. .use('url')
  858. .loader('url-loader')
  859. .end()
  860. .end()
  861. .oneOf('external')
  862. .resourceQuery(/external/)
  863. .use('file')
  864. .loader('file-loader')
  865. ```
  866. #### Config module rules oneOfs (conditional rules): ordering before
  867. Specify that the current `oneOf` context should operate before another named
  868. `oneOf`. You cannot use both `.before()` and `.after()` on the same `oneOf`.
  869. ```js
  870. config.module
  871. .rule(name)
  872. .oneOf(name)
  873. .before()
  874. // Example
  875. config.module
  876. .rule('scss')
  877. .test(/\.scss$/)
  878. .oneOf('normal')
  879. .use('sass')
  880. .loader('sass-loader')
  881. .end()
  882. .end()
  883. .oneOf('sass-vars')
  884. .before('normal')
  885. .resourceQuery(/\?sassvars/)
  886. .use('sass-vars')
  887. .loader('sass-vars-to-js-loader')
  888. ```
  889. #### Config module rules oneOfs (conditional rules): ordering after
  890. Specify that the current `oneOf` context should operate after another named
  891. `oneOf`. You cannot use both `.before()` and `.after()` on the same `oneOf`.
  892. ```js
  893. config.module
  894. .rule(name)
  895. .oneOf(name)
  896. .after()
  897. // Example
  898. config.module
  899. .rule('scss')
  900. .test(/\.scss$/)
  901. .oneOf('vue')
  902. .resourceQuery(/\?vue/)
  903. .use('vue-style')
  904. .loader('vue-style-loader')
  905. .end()
  906. .end()
  907. .oneOf('normal')
  908. .use('sass')
  909. .loader('sass-loader')
  910. .end()
  911. .end()
  912. .oneOf('sass-vars')
  913. .after('vue')
  914. .resourceQuery(/\?sassvars/)
  915. .use('sass-vars')
  916. .loader('sass-vars-to-js-loader')
  917. ```
  918. #### Config module rules resolve
  919. Specify a resolve configuration to be merged over the default `config.resolve`
  920. for modules that match the rule.
  921. See "Config resolve" sections above for full syntax.
  922. **Note:** This option is supported by webpack since 4.36.1.
  923. ```js
  924. config.module
  925. .rule(name)
  926. .resolve
  927. // Example
  928. config.module
  929. .rule('scss')
  930. .test(/\.scss$/)
  931. .resolve
  932. .symlinks(true)
  933. ```
  934. ---
  935. ### Merging Config
  936. webpack-chain supports merging in an object to the configuration instance which
  937. matches a layout similar to how the webpack-chain schema is laid out.
  938. **Note:** This object does not match the webpack configuration schema exactly
  939. (for example the `[name]` keys for entry/rules/plugins), so you may need to transform
  940. webpack configuration objects (such as those output by webpack-chain's `.toConfig()`)
  941. to match the layout below prior to passing to `.merge()`.
  942. ```js
  943. config.merge({ devtool: 'source-map' });
  944. config.get('devtool') // "source-map"
  945. ```
  946. ```js
  947. config.merge({
  948. [key]: value,
  949. amd,
  950. bail,
  951. cache,
  952. context,
  953. devtool,
  954. externals,
  955. loader,
  956. mode,
  957. parallelism,
  958. profile,
  959. recordsPath,
  960. recordsInputPath,
  961. recordsOutputPath,
  962. stats,
  963. target,
  964. watch,
  965. watchOptions,
  966. entry: {
  967. [name]: [...values]
  968. },
  969. plugin: {
  970. [name]: {
  971. plugin: WebpackPlugin,
  972. args: [...args],
  973. before,
  974. after
  975. }
  976. },
  977. devServer: {
  978. [key]: value,
  979. clientLogLevel,
  980. compress,
  981. contentBase,
  982. filename,
  983. headers,
  984. historyApiFallback,
  985. host,
  986. hot,
  987. hotOnly,
  988. https,
  989. inline,
  990. lazy,
  991. noInfo,
  992. overlay,
  993. port,
  994. proxy,
  995. quiet,
  996. setup,
  997. stats,
  998. watchContentBase
  999. },
  1000. node: {
  1001. [key]: value
  1002. },
  1003. optimization: {
  1004. concatenateModules,
  1005. flagIncludedChunks,
  1006. mergeDuplicateChunks,
  1007. minimize,
  1008. minimizer: {
  1009. [name]: {
  1010. plugin: WebpackPlugin,
  1011. args: [...args],
  1012. before,
  1013. after
  1014. }
  1015. },
  1016. namedChunks,
  1017. namedModules,
  1018. nodeEnv,
  1019. noEmitOnErrors,
  1020. occurrenceOrder,
  1021. portableRecords,
  1022. providedExports,
  1023. removeAvailableModules,
  1024. removeEmptyChunks,
  1025. runtimeChunk,
  1026. sideEffects,
  1027. splitChunks,
  1028. usedExports,
  1029. },
  1030. performance: {
  1031. [key]: value,
  1032. hints,
  1033. maxEntrypointSize,
  1034. maxAssetSize,
  1035. assetFilter
  1036. },
  1037. resolve: {
  1038. [key]: value,
  1039. alias: {
  1040. [key]: value
  1041. },
  1042. aliasFields: [...values],
  1043. descriptionFields: [...values],
  1044. extensions: [...values],
  1045. mainFields: [...values],
  1046. mainFiles: [...values],
  1047. modules: [...values],
  1048. plugin: {
  1049. [name]: {
  1050. plugin: WebpackPlugin,
  1051. args: [...args],
  1052. before,
  1053. after
  1054. }
  1055. }
  1056. },
  1057. resolveLoader: {
  1058. [key]: value,
  1059. alias: {
  1060. [key]: value
  1061. },
  1062. aliasFields: [...values],
  1063. descriptionFields: [...values],
  1064. extensions: [...values],
  1065. mainFields: [...values],
  1066. mainFiles: [...values],
  1067. modules: [...values],
  1068. moduleExtensions: [...values],
  1069. packageMains: [...values],
  1070. plugin: {
  1071. [name]: {
  1072. plugin: WebpackPlugin,
  1073. args: [...args],
  1074. before,
  1075. after
  1076. }
  1077. }
  1078. },
  1079. module: {
  1080. [key]: value,
  1081. rule: {
  1082. [name]: {
  1083. [key]: value,
  1084. enforce,
  1085. issuer,
  1086. parser,
  1087. resource,
  1088. resourceQuery,
  1089. test,
  1090. include: [...paths],
  1091. exclude: [...paths],
  1092. rules: {
  1093. [name]: Rule
  1094. },
  1095. oneOf: {
  1096. [name]: Rule
  1097. },
  1098. use: {
  1099. [name]: {
  1100. loader: LoaderString,
  1101. options: LoaderOptions,
  1102. before,
  1103. after
  1104. }
  1105. }
  1106. }
  1107. }
  1108. }
  1109. })
  1110. ```
  1111. ### Conditional configuration
  1112. When working with instances of `ChainedMap` and `ChainedSet`, you can perform
  1113. conditional configuration using `when`. You must specify an expression to
  1114. `when()` which will be evaluated for truthiness or falsiness. If the expression
  1115. is truthy, the first function argument will be invoked with an instance of the
  1116. current chained instance. You can optionally provide a second function to be
  1117. invoked when the condition is falsy, which is also given the current chained
  1118. instance.
  1119. ```js
  1120. // Example: Only add minify plugin during production
  1121. config
  1122. .when(process.env.NODE_ENV === 'production', config => {
  1123. config
  1124. .plugin('minify')
  1125. .use(BabiliWebpackPlugin);
  1126. });
  1127. ```
  1128. ```js
  1129. // Example: Only add minify plugin during production,
  1130. // otherwise set devtool to source-map
  1131. config
  1132. .when(process.env.NODE_ENV === 'production',
  1133. config => config.plugin('minify').use(BabiliWebpackPlugin),
  1134. config => config.devtool('source-map')
  1135. );
  1136. ```
  1137. ### Inspecting generated configuration
  1138. You can inspect the generated webpack config using `config.toString()`. This
  1139. will generate a stringified version of the config with comment hints for named
  1140. rules, uses and plugins:
  1141. ```js
  1142. config
  1143. .module
  1144. .rule('compile')
  1145. .test(/\.js$/)
  1146. .use('babel')
  1147. .loader('babel-loader');
  1148. config.toString();
  1149. /*
  1150. {
  1151. module: {
  1152. rules: [
  1153. /* config.module.rule('compile') */
  1154. {
  1155. test: /\.js$/,
  1156. use: [
  1157. /* config.module.rule('compile').use('babel') */
  1158. {
  1159. loader: 'babel-loader'
  1160. }
  1161. ]
  1162. }
  1163. ]
  1164. }
  1165. }
  1166. */
  1167. ```
  1168. By default the generated string cannot be used directly as real webpack config
  1169. if it contains objects and plugins that need to be required. In order to
  1170. generate usable config, you can customize how objects and plugins are
  1171. stringified by setting a special `__expression` property on them:
  1172. ```js
  1173. const sass = require('sass');
  1174. sass.__expression = `require('sass')`;
  1175. class MyPlugin {}
  1176. MyPlugin.__expression = `require('my-plugin')`;
  1177. function myFunction () {}
  1178. myFunction.__expression = `require('my-function')`;
  1179. config
  1180. .plugin('example')
  1181. .use(MyPlugin, [{ fn: myFunction, implementation: sass, }]);
  1182. config.toString();
  1183. /*
  1184. {
  1185. plugins: [
  1186. new (require('my-plugin'))({
  1187. fn: require('my-function'),
  1188. implementation: require('sass')
  1189. })
  1190. ]
  1191. }
  1192. */
  1193. ```
  1194. Plugins specified via their path will have their `require()` statement generated
  1195. automatically:
  1196. ```js
  1197. config
  1198. .plugin('env')
  1199. .use(require.resolve('webpack/lib/ProvidePlugin'), [{ jQuery: 'jquery' }])
  1200. config.toString();
  1201. /*
  1202. {
  1203. plugins: [
  1204. new (require('/foo/bar/src/node_modules/webpack/lib/EnvironmentPlugin.js'))(
  1205. {
  1206. jQuery: 'jquery'
  1207. }
  1208. )
  1209. ]
  1210. }
  1211. */
  1212. ```
  1213. You can also call `toString` as a static method on `Config` in order to
  1214. modify the configuration object prior to stringifying.
  1215. ```js
  1216. Config.toString({
  1217. ...config.toConfig(),
  1218. module: {
  1219. defaultRules: [
  1220. {
  1221. use: [
  1222. {
  1223. loader: 'banner-loader',
  1224. options: { prefix: 'banner-prefix.txt' },
  1225. },
  1226. ],
  1227. },
  1228. ],
  1229. },
  1230. })
  1231. ```
  1232. ```
  1233. {
  1234. plugins: [
  1235. /* config.plugin('foo') */
  1236. new TestPlugin()
  1237. ],
  1238. module: {
  1239. defaultRules: [
  1240. {
  1241. use: [
  1242. {
  1243. loader: 'banner-loader',
  1244. options: {
  1245. prefix: 'banner-prefix.txt'
  1246. }
  1247. }
  1248. ]
  1249. }
  1250. ]
  1251. }
  1252. }
  1253. ```
  1254. [npm-image]: https://img.shields.io/npm/v/webpack-chain.svg
  1255. [npm-downloads]: https://img.shields.io/npm/dt/webpack-chain.svg
  1256. [npm-url]: https://www.npmjs.com/package/webpack-chain
  1257. [travis-image]: https://api.travis-ci.com/neutrinojs/webpack-chain.svg?branch=master
  1258. [travis-url]: https://travis-ci.com/neutrinojs/webpack-chain