nodejs交互工具库系列
库 | 作用 |
---|---|
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版本配置的批改 |
nodejs交互工具库 -- chalk-pipe和chalk
nodejs交互工具库 -- commander和Inquirer
nodejs交互工具库 -- slash, minimist和dotenv, dotenv-expand
nodejs交互工具库 -- hash-sum, deepmerge和yaml-front-matter
nodejs交互工具库 -- resolve和semver
nodejs交互工具库 -- leven, lru cache和portfinder
nodejs交互工具库 -- ora和envinfo
nodejs交互工具库 -- memfs和execa
nodejs交互工具库 -- webpack-merge和webpack-chain
webpack-merge - Merge designed for Webpack
webpack-merge 提供 merge
函数用于连贯数组和合并对象,从而创立一个新对象. 如果遇到函数,它将执行它们,通过算法运行后果,而后再次将返回值包装到函数中.
这个行为在配置webpack时特地有用,只管它的用处不止于此. 无论何时你须要合并配置对象,webpack-merge都能够派上用场.
merge(...configuration | [...configuration])
merge
是API的外围,也是最重要的思维。通常这就是您所须要的,除非您想要进一步定制
const { merge } = require('webpack-merge');// Default APIconst 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"}
Limitations
留神 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
)匹配您的配置构造,而后应用特定的策略来定义如何转换特定的字段。
Using with TypeScript
webpack-merge 反对开箱即用的TypeScript。你应该依照以下形式将配置类型从webpack传递给它:
import { Configuration } from "webpack";import { merge } from "webpack-merge";const config = merge<Configuration>({...}, {...});...
Development
nvm use
npm i
npm run build -- --watch
in one terminalnpm t -- --watch
in another one
Before contributing, please open an issue where to discuss.
Further Information and Support
查看 SurviveJS - Webpack 来更深刻地开掘webpack。这本收费的书宽泛地应用了webpack-merge,并向您展现了如何组合您的配置来放弃它的可维护性。
如果您须要具体的帮忙,我也能够作为参谋。我能够在进步设置的可维护性方面做出特地的奉献,同时减速它并指出更好的实际。除了进步开发人员的生产力之外,这项工作还会在缩小应用程序大小和加载工夫方面对产品的最终用户产生影响。
参考
根本罕用的办法场景就这些了,更残缺的用法能够间接查阅文档
webpack-merge
webpack-chain
应用链式API去生成简化webpack 版本2-4配置的批改.
这个文档对应于webpack-chain的v5版本。无关以前的版本,请参阅:
- v4 docs
- v3 docs
- v2 docs
- v1 docs
留神:尽管webpack-chain在Neutrino中被宽泛应用,然而这个包是齐全独立的,能够被任何我的项目应用
Introduction
webpack's外围配置基于创立和批改一个可能很蠢笨的JavaScript对象. 尽管这对于单个我的项目的配置来说是能够的,然而尝试在我的项目之间共享这些对象会使后续的批改变得凌乱,因为您须要对底层对象构造有深刻的了解能力进行这些更改.
webpack-chain
尝试通过提供一个可链接的或连贯的API来创立和批改webpack配置来改良这个过程. API的要害局部能够通过用户指定的名称援用,这有助于标准化如何跨我的项目批改配置.
通过上面的示例能够更容易地解释这一点。
Installation
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
Getting Started
一旦你应用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.jsconst Config = require('webpack-chain');const config = new Config();// 使配置在指标之间共享// ...module.exports = config;// webpack.dev.jsconst config = require('./webpack.core');// Dev-specific configuration// ...module.exports = config.toConfig();// webpack.prod.jsconst config = require('./webpack.core');// Production-specific configuration// ...module.exports = config.toConfig();
ChainedMap
在 webpack-chain外围API接口之一是 ChainedMap
. 一个ChainedMap
操作相似于JavaScript Map, 能够不便地链接和生成配置. 如果一个属性被标记为 ChainedMap
, 它将具备如下所述的API和办法:
除非另有阐明,这些办法将返回 ChainedMap
, 容许您链接这些办法.
// 从映射中删除所有条目.clear()
// 从给定其键的映射中删除单个条目// key: *delete(key)
// 从位于对应键的映射中获取值.// key: *// returns: valueget(key)
// 从位于对应键的映射中获取值.// 如果短少键,则将键设置为函数fn的后果.// key: *// fn: Function () -> value// returns: valuegetOrCompute(key, fn)
// 在`key`地位缓存的Map设置值.// key: *// value: *set(key, value)
// 返回 `true` 或 `false` 取决于Map是否设定了一个特定的key.// key: *// returns: Booleanhas(key)
// 返回映射中存储的所有值的数组.// returns: Arrayvalues()
// 返回备份映射中所有条目标对象,其中键是对象属性,以及与键对应的值。如果反对映射为空,将返回“undefined”。// 这将依据属性的名称排序,如果值是应用.before() 或者 .after()的ChainedMap.// returns: Object, undefined if emptyentries()
// 提供一个映射其属性和值的对象// 作为键和值导入备份映射.// 您还能够提供一个数组作为第二个参数// 用于防止合并的属性名称// obj: Object// omit: Optional Arraymerge(obj, omit)
// 依据以后配置上下文执行函数// handler: Function -> ChainedMap // 给ChainedMap实例一个参数的函数batch(handler)
// 有条件地执行函数以持续配置// condition: Boolean// whenTruthy: Function -> ChainedMap // 在条件为真时调用,给定ChainedMap实例的单个参数// whenFalsy: Optional Function -> ChainedMap // 条件不牢靠时调用,给定ChainedMap实例的单个参数when(condition, whenTruthy, whenFalsy)
ChainedSet
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: Booleanhas(value)
// 返回backing Set蕴含值的数组// returns: Arrayvalues()
// 将给定数组连贯到backing Set.// arr: Arraymerge(arr)
// 依据以后配置上下文执行函数// handler: Function -> ChainedSet // 给ChainedSet实例一个参数的函数batch(handler)
// 有条件地执行函数以持续配置// condition: Boolean// whenTruthy: Function -> ChainedSet // 在条件为真时调用,给定ChainedSet实例的单个参数// whenFalsy: Optional Function -> ChainedSet // 在条件不牢靠时调用,给定ChainedSet实例的单个参数when(condition, whenTruthy, whenFalsy)
Shorthand methods
有许多快捷办法能够应用与快捷办法名雷同的键设置ChainedMap
上的值。例如,devServer.hot
是一种速记法,所以它能够被用作:
// 在ChainedMap上设置值的一种速记办法devServer.hot(true);// 这就等于:devServer.set('hot', true);
快捷的办法是可链的,因而调用它将返回原始实例,从而容许您持续进行链操作
Config
创立一个新的配置对象。
const Config = require('webpack-chain');const config = new Config();
在API中挪动到更深的点将扭转所批改内容的上下文。您能够通过再次援用顶级配置或调用.end()向上挪动一级回到更高的上下文.如果您相熟jQuery,那么.end()的工作原理与此相似。除非另有指定,否则所有API调用都将在以后上下文返回API实例。这样,如果须要,就能够间断地将API调用链起来。
无关对所有速记和低级办法无效的特定值的详细信息,请参考在 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 : ChainedMapconfig.entry(name) : ChainedSetconfig .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 : ChainedMapconfig.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
config.resolve : ChainedMapconfig.resolve .cachePredicate(cachePredicate) .cacheWithContext(cacheWithContext) .enforceExtension(enforceExtension) .enforceModuleExtension(enforceModuleExtension) .unsafeCache(unsafeCache) .symlinks(symlinks)
Config resolve alias
config.resolve.alias : ChainedMapconfig.resolve.alias .set(key, value) .set(key, value) .delete(key) .clear()
Config resolve modules
config.resolve.modules : ChainedSetconfig.resolve.modules .add(value) .prepend(value) .clear()
Config resolve aliasFields
config.resolve.aliasFields : ChainedSetconfig.resolve.aliasFields .add(value) .prepend(value) .clear()
Config resolve descriptionFields
config.resolve.descriptionFields : ChainedSetconfig.resolve.descriptionFields .add(value) .prepend(value) .clear()
Config resolve extensions
config.resolve.extensions : ChainedSetconfig.resolve.extensions .add(value) .prepend(value) .clear()
Config resolve mainFields
config.resolve.mainFields : ChainedSetconfig.resolve.mainFields .add(value) .prepend(value) .clear()
Config resolve mainFiles
config.resolve.mainFiles : ChainedSetconfig.resolve.mainFiles .add(value) .prepend(value) .clear()
Config resolveLoader
config.resolveLoader
API 和config.resolve
雷同,增加了以下内容:
Config resolveLoader moduleExtensions
config.resolveLoader.moduleExtensions : ChainedSetconfig.resolveLoader.moduleExtensions .add(value) .prepend(value) .clear()
Config resolveLoader packageMains
config.resolveLoader.packageMains : ChainedSetconfig.resolveLoader.packageMains .add(value) .prepend(value) .clear()
Config performance: shorthand methods
config.performance : ChainedMapconfig.performance .hints(hints) .maxEntrypointSize(maxEntrypointSize) .maxAssetSize(maxAssetSize) .assetFilter(assetFilter)
Configuring optimizations: shorthand methods
config.optimization : ChainedMapconfig.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.minimizersconfig.optimization .minimizer(name) : ChainedMap
Config optimization minimizers: adding
留神:不要应用new创立最小化插件,因为这将为你实现。
config.optimization .minimizer(name) .use(WebpackPlugin, args)// Examplesconfig.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 minimizers: modify arguments
config.optimization .minimizer(name) .tap(args => newArgs)// Exampleconfig.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.pluginsconfig.plugin(name) : ChainedMap
Config plugins: adding
留神:不要应用new来创立插件,因为这将为您实现。
config .plugin(name) .use(WebpackPlugin, args)// Examplesconfig .plugin('hot') .use(webpack.HotModuleReplacementPlugin);// 最小化插件也能够依据它们的门路指定,这样在插件或webpack配置最终不会被应用的状况下,就能够跳过低廉的require()。config .plugin('env') .use(require.resolve('webpack/lib/EnvironmentPlugin'), [{ 'VAR': false }]);
Config plugins: modify arguments
config .plugin(name) .tap(args => newArgs)// Exampleconfig .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
指定以后插件上下文应该在另一个已命名插件之前操作。不能在同一个插件上同时应用.before()和.after()。
config .plugin(name) .before(otherName)// Exampleconfig .plugin('html-template') .use(HtmlWebpackTemplate) .end() .plugin('script-ext') .use(ScriptExtWebpackPlugin) .before('html-template');
Config plugins: ordering after
指定以后的插件上下文应该在另一个命名的插件之后操作。不能在同一个插件上同时应用.before()和.after()。
config .plugin(name) .after(otherName)// Exampleconfig .plugin('html-template') .after('script-ext') .use(HtmlWebpackTemplate) .end() .plugin('script-ext') .use(ScriptExtWebpackPlugin);
Config resolve plugins
// Backed at config.resolve.pluginsconfig.resolve.plugin(name) : ChainedMap
Config resolve plugins: adding
留神:不要应用new来创立插件,因为这将为您实现。
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
指定以后插件上下文应该在另一个已命名插件之前操作。不能在同一个解析插件上同时应用.before()和.after()。
config.resolve .plugin(name) .before(otherName)// Exampleconfig.resolve .plugin('beta') .use(BetaWebpackPlugin) .end() .plugin('alpha') .use(AlphaWebpackPlugin) .before('beta');
Config resolve plugins: ordering after
指定以后的插件上下文应该在另一个命名的插件之后操作。不能在同一个解析插件上同时应用.before()和.after()。
config.resolve .plugin(name) .after(otherName)// Exampleconfig.resolve .plugin('beta') .after('alpha') .use(BetaWebpackTemplate) .end() .plugin('alpha') .use(AlphaWebpackPlugin);
Config node
config.node : ChainedMapconfig.node .set('__dirname', 'mock') .set('__filename', 'mock');
Config devServer
config.devServer : ChainedMap
Config devServer allowedHosts
config.devServer.allowedHosts : ChainedSetconfig.devServer.allowedHosts .add(value) .prepend(value) .clear()
Config devServer: shorthand methods
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
config.module : ChainedMap
Config module: shorthand methods
config.module : ChainedMapconfig.module .noParse(noParse)
Config module rules: shorthand methods
config.module.rules : ChainedMapconfig.module .rule(name) .test(test) .pre() .post() .enforce(preOrPost)
Config module rules uses (loaders): creating
config.module.rules{}.uses : ChainedMapconfig.module .rule(name) .use(name) .loader(loader) .options(options)// Exampleconfig.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)// Exampleconfig.module .rule('compile') .use('babel') .tap(options => merge(options, { plugins: ['@babel/plugin-proposal-class-properties'] }));
Config module rules oneOfs (conditional rules):
config.module.rules{}.oneOfs : ChainedMap<Rule>config.module .rule(name) .oneOf(name)// Exampleconfig.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
指定上下文的以后上下文应该在另一个已命名的上下文之前操作。.before()和.after()不能同时应用。
config.module .rule(name) .oneOf(name) .before()// Exampleconfig.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
指定上下文的以后上下文应该在另一个已命名的上下文之后操作。.before()和.after()不能同时应用。
config.module .rule(name) .oneOf(name) .after()// Exampleconfig.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')
Merging Config
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 } } } } }})
Conditional configuration
在应用ChainedMap和ChainedSet实例时,能够应用When执行条件配置。您必须为when()指定一个表达式,该表达式将被评估为实在或谬误. 如果表达式为真,则第一个函数参数将与以后链接实例的实例一起调用。您能够抉择提供第二个函数,以便在条件为falsy时调用,该函数也提供以后链接实例.
// 示例:只在生产过程中增加minify插件config .when(process.env.NODE_ENV === 'production', config => { config .plugin('minify') .use(BabiliWebpackPlugin); });
// 示例:只在生产过程中增加minify插件// 否则设置devtool为source-mapconfig .when(process.env.NODE_ENV === 'production', config => config.plugin('minify').use(BabiliWebpackPlugin), config => config.devtool('source-map') );
Inspecting generated configuration
您能够应用以下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' } } ] } ] }}
参考
根本罕用的办法场景就这些了,更残缺的用法能够间接查阅文档
webpack-chain