庫 | 做用 |
---|---|
chalk-pipe | 使用更簡單的樣式字符串建立粉筆樣式方案 |
chalk | 正確處理終端字符串樣式 |
Commander.js | 完整的 node.js 命令行解決方案 |
Inquirer.js | 一組通用的交互式命令行用戶界面。 |
slash | 系統路徑符處理 |
minimist | 解析參數選項 |
dotenv | 將環境變量從 .env文件加載到process.env中 |
dotenv-expand | 擴展計算機上已經存在的環境變量 |
hash-sum | 很是快的惟一哈希生成器 |
deepmerge | 深度合併兩個或多個對象的可枚舉屬性。 |
yaml-front-matter | 解析yaml或json |
resolve | 實現node的 require.resolve() 算法,這樣就能夠異步和同步地使用require.resolve()表明文件 |
semver | npm的語義版本器 |
leven | 測量兩字符串之間的差別<br/>最快的JS實現之一 |
lru cache | 刪除最近最少使用的項的緩存對象 |
portfinder | 自動尋找 8000 至65535 內可用端口號 |
ora | 優雅的終端轉輪 |
envinfo | 生成故障排除軟件問題(如操做系統、二進制版本、瀏覽器、已安裝語言等)時所需的通用詳細信息的報告 |
memfs | 內存文件系統與Node's fs API相同實現 |
execa | 針對人類的流程執行 |
webpack-merge | 用於鏈接數組和合並對象,從而建立一個新對象 |
webpack-chain | 使用鏈式API去生成簡化webpack版本配置的修改 |
strip-ansi | 從字符串中去掉ANSI轉義碼 |
address | 獲取當前機器的IP, MAC和DNS服務器。 |
default-gateway | 經過對OS路由接口的exec調用得到機器的默認網關 |
joi | JavaScript最強大的模式描述語言和數據驗證器。 |
fs-extra | 添加了未包含在原生fs 模塊中的文件系統方法,並向fs 方法添加了promise支持 |
Acorn | 一個小而快速的JavaScript解析器,徹底用JavaScript編寫。 |
zlib.js | ZLIB.js是ZLIB(RFC1950), DEFLATE(RFC1951), GZIP(RFC1952)和PKZIP在JavaScript實現。 |
nodejs交互工具庫 -- chalk-pipe和chalkcss
nodejs交互工具庫 -- commander和Inquirerhtml
nodejs交互工具庫 -- slash, minimist和dotenv, dotenv-expandvue
nodejs交互工具庫 -- hash-sum, deepmerge和yaml-front-matternode
nodejs交互工具庫 -- resolve和semverjquery
nodejs交互工具庫 -- leven, lru cache和portfinderwebpack
nodejs交互工具庫 -- memfs和execagithub
nodejs交互工具庫 -- webpack-merge和webpack-chainweb
nodejs交互工具庫 -- strip-ansi, address, default-gateway和joi算法
nodejs交互工具庫 -- fs-extra, Acorn和zlib
webpack-merge 提供 merge
函數用於鏈接數組和合並對象,從而建立一個新對象. 若是遇到函數,它將執行它們,經過算法運行結果,而後再次將返回值包裝到函數中.
這個行爲在配置webpack時特別有用,儘管它的用途不止於此. 不管什麼時候你須要合併配置對象,webpack-merge均可以派上用場.
merge(...configuration | [...configuration])
merge
是API的核心,也是最重要的思想。一般這就是您所須要的,除非您想要進一步定製
const { merge } = require('webpack-merge'); // Default API const output = merge(object1, object2, object3, ...); // 您能夠直接傳遞一個對象數組. // 這適用於全部可用的功能. const output = merge([object1, object2, object3]); // 與右邊匹配的鍵優先: const output = merge( { fruit: "apple", color: "red" }, { fruit: "strawberries" } ); console.log(output); // { color: "red", fruit: "strawberries"}
注意 Promise
s不被支持! 若是你想返回一個包裹配置的 Promise
, merge
在其中一個裏面. 例如: Promise.resolve(merge({ ... }, { ... }))
.
下面示例中的配置級函數也是如此:
webpack.config.js
const commonConfig = { ... }; const productionConfig = { ... }; const developmentConfig = { ... }; module.exports = env => { switch(env) { case 'development': return merge(commonConfig, developmentConfig); case 'production': return merge(commonConfig, productionConfig); default: throw new Error('No matching configuration was found!'); } }
你能夠經過 webpack --env development
選擇你想要的配置假如你使用了 webpack-cli.
mergeWithCustomize({ customizeArray, customizeObject })(...configuration | [...configuration])
若是你須要更多的靈活性,merge
行爲能夠定製每一個字段以下:
const { mergeWithCustomize } = require('webpack-merge'); const output = mergeWithCustomize( { customizeArray(a, b, key) { if (key === 'extensions') { return _.uniq([...a, ...b]); } // 回到默認的合併 return undefined; }, customizeObject(a, b, key) { if (key === 'module') { // 自定義合併 return _.merge({}, a, b); } // 回到默認的合併 return undefined; } } )(object1, object2, object3, ...);
例如,若是前面的代碼僅使用object1和object2調用,而object1爲:
{ foo1: ['object1'], foo2: ['object1'], bar1: { object1: {} }, bar2: { object1: {} }, }
而object2
爲
{ foo1: ['object2'], foo2: ['object2'], bar1: { object2: {} }, bar2: { object2: {} }, }
而後對數組類型的每一個屬性調用 customizeArray
,即:
customizeArray(["object1"], ["object2"], "foo1"); customizeArray(["object1"], ["object2"], "foo2");
對對象類型的每一個屬性調用 customizeObject
,即:
customizeObject({ object1: {} }, { object2: {} }, bar1); customizeObject({ object1: {} }, { object2: {} }, bar2);
customizeArray
and customizeObject
customizeArray
和customizeObject
提供小策略 mergeWithCustomize
. 他們支持字段名append
, prepend
, replace
, 和通配符.
const { mergeWithCustomize, customizeArray, customizeObject } = require('webpack-merge'); const output = mergeWithCustomize({ customizeArray: customizeArray({ 'entry.*': 'prepend' }), customizeObject: customizeObject({ entry: 'prepend' }) })(object1, object2, object3, ...);
unique(<field>, <fields>, field => field)
unique
使用了一種策略來強制配置中的惟一性. 當你想要肯定只有一個插件的時候,它是最有用的.
第一個<field>
是用於查找重複項的配置屬性。
<fields>
表示在對每一個副本運行field =>field函數時應該唯一的值
const { mergeWithCustomize, unique } = require("webpack-merge"); const output = mergeWithCustomize({ customizeArray: unique( "plugins", ["HotModuleReplacementPlugin"], plugin => plugin.constructor && plugin.constructor.name ) })( { plugins: [new webpack.HotModuleReplacementPlugin()] }, { plugins: [new webpack.HotModuleReplacementPlugin()] } ); // 輸出只包含一個HotModuleReplacementPlugin如今和它的 // 將是最後一個插件實例.
mergeWithRules
爲支持高級合併需求(即在加載器內合併), mergeWithRules
包含容許匹配字段和應用匹配策略的附加語法。考慮下面的完整示例:
const a = { module: { rules: [ { test: /\.css$/, use: [{ loader: "style-loader" }, { loader: "sass-loader" }] } ] } }; const b = { module: { rules: [ { test: /\.css$/, use: [ { loader: "style-loader", options: { modules: true } } ] } ] } }; const result = { module: { rules: [ { test: /\.css$/, use: [ { loader: "style-loader", options: { modules: true } }, { loader: "sass-loader" } ] } ] } }; assert.deepStrictEqual( mergeWithRules({ module: { rules: { test: "match", use: { loader: "match", options: "replace" } } } })(a, b), result );
它的工做方式是,您應該使用 match
(或CustomizeRule
)註釋字段以進行匹配。匹配(若是您正在使用TypeScript
)匹配您的配置結構,而後使用特定的策略來定義如何轉換特定的字段。
webpack-merge 支持開箱即用的TypeScript。你應該按照如下方式將配置類型從webpack傳遞給它:
import { Configuration } from "webpack"; import { merge } from "webpack-merge"; const config = merge<Configuration>({...}, {...}); ...
nvm use
npm i
npm run build -- --watch
in one terminalnpm t -- --watch
in another oneBefore contributing, please open an issue where to discuss.
查看 SurviveJS - Webpack 來更深刻地挖掘webpack。這本免費的書普遍地使用了webpack-merge,並向您展現瞭如何組合您的配置來保持它的可維護性。
若是您須要具體的幫助,我也能夠做爲顧問。我能夠在提升設置的可維護性方面作出特別的貢獻,同時加速它並指出更好的實踐。除了提升開發人員的生產力以外,這項工做還會在減小應用程序大小和加載時間方面對產品的最終用戶產生影響。
基本經常使用的方法場景就這些了,更完整的用法能夠直接查閱文檔
使用鏈式API去生成簡化webpack 版本2-4配置的修改.
這個文檔對應於webpack-chain的v5版本。有關之前的版本,請參閱:
注意:雖然webpack-chain在Neutrino中被普遍使用,可是這個包是徹底獨立的,能夠被任何項目使用
webpack's核心配置基於建立和修改一個可能很笨拙的JavaScript對象. 雖然這對於單個項目的配置來講是能夠的,可是嘗試在項目之間共享這些對象會使後續的修改變得混亂,由於您須要對底層對象結構有深刻的理解才能進行這些更改.
webpack-chain
嘗試經過提供一個可連接的或連貫的API來建立和修改webpack配置來改進這個過程. API的關鍵部分能夠經過用戶指定的名稱引用,這有助於標準化如何跨項目修改配置.
經過下面的示例能夠更容易地解釋這一點。
webpack-chain
須要Node.js v6.9或更高. webpack-chain
也只建立用於webpack版本 2, 3, 和4的配置對象.
您可使用Yarn或npm(任選一種)安裝此軟件包:
Yarn
yarn add --dev webpack-chain
npm
npm install --save-dev webpack-chain
一旦你使用webpack-chain
替代, 你能夠建立一個webpack配置. 對於本指南, 咱們的例子基礎配置 webpack.config.js
在項目的頂層目錄
// 須要webpack-chain模塊。此模塊導出單個 // 用於建立配置API的構造函數 const Config = require('webpack-chain'); // 使用新的API實例化配置 const config = new Config(); // 使用chain API進行配置更改. // 每一個API調用跟蹤對存儲配置的更改. config // 與入口點交互 .entry('index') .add('src/index.js') .end() // 修改輸出設置 .output .path('dist') .filename('[name].bundle.js'); // 建立可在之後修改的命名規則 config.module .rule('lint') .test(/\.js$/) .pre() .include .add('src') .end() // 甚至建立命名的使用(加載器) .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 }] ] }); // 也建立命名插件! config .plugin('clean') .use(CleanPlugin, [['dist'], { root: '/dir' }]); // 導出完成的配置對象以供webpack使用 module.exports = config.toConfig();
共享配置也很簡單。只需導出配置並調用.toConfig()
便可在傳遞到webpack以前
// webpack.core.js const Config = require('webpack-chain'); const config = new Config(); // 使配置在目標之間共享 // ... 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();
在 webpack-chain核心API接口之一是 ChainedMap
. 一個ChainedMap
操做相似於JavaScript Map, 能夠方便地連接和生成配置. 若是一個屬性被標記爲 ChainedMap
, 它將具備以下所述的API和方法:
除非另有說明,這些方法將返回 ChainedMap
, 容許您連接這些方法.
// 從映射中刪除全部條目. clear()
// 從給定其鍵的映射中刪除單個條目 // key: * delete(key)
// 從位於對應鍵的映射中獲取值. // key: * // returns: value get(key)
// 從位於對應鍵的映射中獲取值. // 若是缺乏鍵,則將鍵設置爲函數fn的結果. // key: * // fn: Function () -> value // returns: value getOrCompute(key, fn)
// 在`key`位置緩存的Map設置值. // key: * // value: * set(key, value)
// 返回 `true` 或 `false` 取決於Map是否設定了一個特定的key. // key: * // returns: Boolean has(key)
// 返回映射中存儲的全部值的數組. // returns: Array values()
// 返回備份映射中全部條目的對象,其中鍵是對象屬性,以及與鍵對應的值。若是支持映射爲空,將返回「undefined」。 // 這將根據屬性的名稱排序,若是值是使用.before() 或者 .after()的ChainedMap. // returns: Object, undefined if empty entries()
// 提供一個映射其屬性和值的對象 // 做爲鍵和值導入備份映射. // 您還能夠提供一個數組做爲第二個參數 // 用於避免合併的屬性名稱 // obj: Object // omit: Optional Array merge(obj, omit)
// 根據當前配置上下文執行函數 // handler: Function -> ChainedMap // 給ChainedMap實例一個參數的函數 batch(handler)
// 有條件地執行函數以繼續配置 // condition: Boolean // whenTruthy: Function -> ChainedMap // 在條件爲真時調用,給定ChainedMap實例的單個參數 // whenFalsy: Optional Function -> ChainedMap // 條件不可靠時調用,給定ChainedMap實例的單個參數 when(condition, whenTruthy, whenFalsy)
webpack-chain中的另外一個核心API接口是 ChainedSet
. ChainedSet
操做相似於JavaScript Set,便於連接和生成配置.若是一個屬性被標記爲 ChainedSet
, 它將有一個API和方法描述以下:
除非另有說明,這些方法將返回 ChainedMap
, 容許您連接這些方法.
// Set末尾添加/追加一個值. // value: * add(value)
// Set開頭添加/追加一個值. // value: * prepend(value)
// Set刪除全部值. clear()
// Set移除特定的值. // value: * delete(value)
// 返回 `true` 或 `false` 取決於Map是否設定了一個特定的key // value: * // returns: Boolean has(value)
// 返回backing Set包含值的數組 // returns: Array values()
// 將給定數組鏈接到backing Set. // arr: Array merge(arr)
// 根據當前配置上下文執行函數 // handler: Function -> ChainedSet // 給ChainedSet實例一個參數的函數 batch(handler)
// 有條件地執行函數以繼續配置 // condition: Boolean // whenTruthy: Function -> ChainedSet // 在條件爲真時調用,給定ChainedSet實例的單個參數 // whenFalsy: Optional Function -> ChainedSet // 在條件不可靠時調用,給定ChainedSet實例的單個參數 when(condition, whenTruthy, whenFalsy)
有許多快捷方法可使用與快捷方法名相同的鍵設置ChainedMap
上的值。例如,devServer.hot
是一種速記法,因此它能夠被用做:
// 在ChainedMap上設置值的一種速記方法 devServer.hot(true); // 這就等於: devServer.set('hot', true);
快捷的方法是可鏈的,所以調用它將返回原始實例,從而容許您繼續進行鏈操做
建立一個新的配置對象。
const Config = require('webpack-chain'); const config = new Config();
在API中移動到更深的點將改變所修改內容的上下文。您能夠經過再次引用頂級配置或調用.end()向上移動一級回到更高的上下文.若是您熟悉jQuery,那麼.end()的工做原理與此相似。除非另有指定,不然全部API調用都將在當前上下文返回API實例。這樣,若是須要,就能夠連續地將API調用鏈起來。
有關對全部速記和低級方法有效的特定值的詳細信息,請參考在 webpack docs hierarchy.
Config : ChainedMap
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)
// 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 : 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 : ChainedMap config.resolve .cachePredicate(cachePredicate) .cacheWithContext(cacheWithContext) .enforceExtension(enforceExtension) .enforceModuleExtension(enforceModuleExtension) .unsafeCache(unsafeCache) .symlinks(symlinks)
config.resolve.alias : ChainedMap config.resolve.alias .set(key, value) .set(key, value) .delete(key) .clear()
config.resolve.modules : ChainedSet config.resolve.modules .add(value) .prepend(value) .clear()
config.resolve.aliasFields : ChainedSet config.resolve.aliasFields .add(value) .prepend(value) .clear()
config.resolve.descriptionFields : ChainedSet config.resolve.descriptionFields .add(value) .prepend(value) .clear()
config.resolve.extensions : ChainedSet config.resolve.extensions .add(value) .prepend(value) .clear()
config.resolve.mainFields : ChainedSet config.resolve.mainFields .add(value) .prepend(value) .clear()
config.resolve.mainFiles : ChainedSet config.resolve.mainFiles .add(value) .prepend(value) .clear()
config.resolveLoader
API 和config.resolve
相同,添加了如下內容:
config.resolveLoader.moduleExtensions : ChainedSet config.resolveLoader.moduleExtensions .add(value) .prepend(value) .clear()
config.resolveLoader.packageMains : ChainedSet config.resolveLoader.packageMains .add(value) .prepend(value) .clear()
config.performance : ChainedMap config.performance .hints(hints) .maxEntrypointSize(maxEntrypointSize) .maxAssetSize(maxAssetSize) .assetFilter(assetFilter)
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)
// Backed at config.optimization.minimizers config.optimization .minimizer(name) : ChainedMap
注意:不要使用new建立最小化插件,由於這將爲你完成。
config.optimization .minimizer(name) .use(WebpackPlugin, args) // Examples config.optimization .minimizer('css') .use(OptimizeCSSAssetsPlugin, [{ cssProcessorOptions: { safe: true } }]) // 最小化插件也能夠根據它們的路徑指定,這樣在插件或webpack配置最終不會被使用的狀況下,就能夠跳過昂貴的require()。 config.optimization .minimizer('css') .use(require.resolve('optimize-css-assets-webpack-plugin'), [{ cssProcessorOptions: { safe: true } }])
config.optimization .minimizer(name) .tap(args => newArgs) // Example config.optimization .minimizer('css') .tap(args => [...args, { cssProcessorOptions: { safe: false } }])
config.optimization .minimizer(name) .init((Plugin, args) => new Plugin(...args));
config.optimization.minimizers.delete(name)
// Backed at config.plugins config.plugin(name) : ChainedMap
注意:不要使用new來建立插件,由於這將爲您完成。
config .plugin(name) .use(WebpackPlugin, args) // Examples config .plugin('hot') .use(webpack.HotModuleReplacementPlugin); // 最小化插件也能夠根據它們的路徑指定,這樣在插件或webpack配置最終不會被使用的狀況下,就能夠跳過昂貴的require()。 config .plugin('env') .use(require.resolve('webpack/lib/EnvironmentPlugin'), [{ 'VAR': false }]);
config .plugin(name) .tap(args => newArgs) // Example config .plugin('env') .tap(args => [...args, 'SECRET_KEY']);
config .plugin(name) .init((Plugin, args) => new Plugin(...args));
config.plugins.delete(name)
指定當前插件上下文應該在另外一個已命名插件以前操做。不能在同一個插件上同時使用.before()和.after()。
config .plugin(name) .before(otherName) // Example config .plugin('html-template') .use(HtmlWebpackTemplate) .end() .plugin('script-ext') .use(ScriptExtWebpackPlugin) .before('html-template');
指定當前的插件上下文應該在另外一個命名的插件以後操做。不能在同一個插件上同時使用.before()和.after()。
config .plugin(name) .after(otherName) // Example config .plugin('html-template') .after('script-ext') .use(HtmlWebpackTemplate) .end() .plugin('script-ext') .use(ScriptExtWebpackPlugin);
// Backed at config.resolve.plugins config.resolve.plugin(name) : ChainedMap
注意:不要使用new來建立插件,由於這將爲您完成。
config.resolve .plugin(name) .use(WebpackPlugin, args)
config.resolve .plugin(name) .tap(args => newArgs)
config.resolve .plugin(name) .init((Plugin, args) => new Plugin(...args))
config.resolve.plugins.delete(name)
指定當前插件上下文應該在另外一個已命名插件以前操做。不能在同一個解析插件上同時使用.before()和.after()。
config.resolve .plugin(name) .before(otherName) // Example config.resolve .plugin('beta') .use(BetaWebpackPlugin) .end() .plugin('alpha') .use(AlphaWebpackPlugin) .before('beta');
指定當前的插件上下文應該在另外一個命名的插件以後操做。不能在同一個解析插件上同時使用.before()和.after()。
config.resolve .plugin(name) .after(otherName) // Example config.resolve .plugin('beta') .after('alpha') .use(BetaWebpackTemplate) .end() .plugin('alpha') .use(AlphaWebpackPlugin);
config.node : ChainedMap config.node .set('__dirname', 'mock') .set('__filename', 'mock');
config.devServer : ChainedMap
config.devServer.allowedHosts : ChainedSet config.devServer.allowedHosts .add(value) .prepend(value) .clear()
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(pfxPassphrase) .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 : ChainedMap
config.module : ChainedMap config.module .noParse(noParse)
config.module.rules : ChainedMap config.module .rule(name) .test(test) .pre() .post() .enforce(preOrPost)
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 .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 : 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')
指定上下文的當前上下文應該在另外一個已命名的上下文以前操做。.before()和.after()不能同時使用。
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')
指定上下文的當前上下文應該在另外一個已命名的上下文以後操做。.before()和.after()不能同時使用。
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')
webpack-chain支持將對象合併到與佈局相似的配置實例中。請注意,這不是一個webpack配置對象,可是您能夠在將一個webpack配置對象提供給webpack-chain以前轉換它以匹配它的佈局。
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, 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 } } } } } })
在使用ChainedMap和ChainedSet實例時,可使用When執行條件配置。您必須爲when()指定一個表達式,該表達式將被評估爲真實或錯誤. 若是表達式爲真,則第一個函數參數將與當前連接實例的實例一塊兒調用。您能夠選擇提供第二個函數,以便在條件爲falsy時調用,該函數也提供當前連接實例.
// 示例:只在生產過程當中添加minify插件 config .when(process.env.NODE_ENV === 'production', config => { config .plugin('minify') .use(BabiliWebpackPlugin); });
// 示例:只在生產過程當中添加minify插件 // 不然設置devtool爲source-map config .when(process.env.NODE_ENV === 'production', config => config.plugin('minify').use(BabiliWebpackPlugin), config => config.devtool('source-map') );
您可使用如下config.toString()
命令檢查生成的webpack配置 . 這將生成一個stringified版本的配置,帶有關於命名規則、使用方法和插件的註釋提示:
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' } ] } ] } } */
默認狀況下,生成的字符串不能直接用做真正的webpack配置,若是它包含了須要的對象和插件.爲了生成可用的配置,您能夠經過設置一個特殊的__expression
屬性來定製對象和插件是怎麼分層的
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') }) ] } */
經過路徑指定的插件將自動生成它們的require()語句:
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' } ) ] } */
您還能夠將toString做爲配置的靜態方法調用,以便在字符串化以前修改配置對象。
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' } } ] } ] } }
基本經常使用的方法場景就這些了,更完整的用法能夠直接查閱文檔