关于javascript:nodejs交互工具库-webpackmerge和webpackchain

22次阅读

共计 22668 个字符,预计需要花费 57 分钟才能阅读完成。

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 主动寻找 800065535 内可用端口号
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 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"}

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

customizeArraycustomizeObject 提供小策略 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

  1. nvm use
  2. npm i
  3. npm run build -- --watch in one terminal
  4. npm 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.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();

ChainedMap

在 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)

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: 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)

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 : ChainedMap
config.entry(name) : ChainedSet

config
  .entry(name)
  .add(value)
  .add(value)

config
  .entry(name)
  .clear()

// Using low-level config.entryPoints:

config.entryPoints
  .get(name)
  .add(value)
  .add(value)

config.entryPoints
  .get(name)
  .clear()
Config output: shorthand methods
config.output : ChainedMap

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

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

config.resolve.alias
  .set(key, value)
  .set(key, value)
  .delete(key)
  .clear()
Config resolve modules
config.resolve.modules : ChainedSet

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

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

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

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

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

config.resolve.mainFiles
  .add(value)
  .prepend(value)
  .clear()
Config resolveLoader

config.resolveLoaderAPI 和config.resolve 雷同, 增加了以下内容:

Config resolveLoader moduleExtensions
config.resolveLoader.moduleExtensions : ChainedSet

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

config.resolveLoader.packageMains
  .add(value)
  .prepend(value)
  .clear()
Config performance: shorthand methods
config.performance : ChainedMap

config.performance
  .hints(hints)
  .maxEntrypointSize(maxEntrypointSize)
  .maxAssetSize(maxAssetSize)
  .assetFilter(assetFilter)
Configuring optimizations: shorthand methods
config.optimization : ChainedMap

config.optimization
  .concatenateModules(concatenateModules)
  .flagIncludedChunks(flagIncludedChunks)
  .mergeDuplicateChunks(mergeDuplicateChunks)
  .minimize(minimize)
  .namedChunks(namedChunks)
  .namedModules(namedModules)
  .nodeEnv(nodeEnv)
  .noEmitOnErrors(noEmitOnErrors)
  .occurrenceOrder(occurrenceOrder)
  .portableRecords(portableRecords)
  .providedExports(providedExports)
  .removeAvailableModules(removeAvailableModules)
  .removeEmptyChunks(removeEmptyChunks)
  .runtimeChunk(runtimeChunk)
  .sideEffects(sideEffects)
  .splitChunks(splitChunks)
  .usedExports(usedExports)
Config optimization minimizers
// Backed at config.optimization.minimizers
config.optimization
  .minimizer(name) : ChainedMap
Config optimization minimizers: adding

留神: 不要应用 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 minimizers: modify arguments
config.optimization
  .minimizer(name)
  .tap(args => newArgs)

// Example
config.optimization
  .minimizer('css')
  .tap(args => [...args, { cssProcessorOptions: { safe: false} }])
Config optimization minimizers: modify instantiation
config.optimization
  .minimizer(name)
  .init((Plugin, args) => new Plugin(...args));
Config optimization minimizers: removing
config.optimization.minimizers.delete(name)
Config plugins
// Backed at config.plugins
config.plugin(name) : ChainedMap
Config plugins: adding

留神: 不要应用 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 plugins: modify arguments
config
  .plugin(name)
  .tap(args => newArgs)

// Example
config
  .plugin('env')
  .tap(args => [...args, 'SECRET_KEY']);
Config plugins: modify instantiation
config
  .plugin(name)
  .init((Plugin, args) => new Plugin(...args));
Config plugins: removing
config.plugins.delete(name)
Config plugins: ordering before

指定以后插件上下文应该在另一个已命名插件之前操作。不能在同一个插件上同时应用.before()和.after()。

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

指定以后的插件上下文应该在另一个命名的插件之后操作。不能在同一个插件上同时应用.before()和.after()。

config
  .plugin(name)
    .after(otherName)

// Example

config
  .plugin('html-template')
    .after('script-ext')
    .use(HtmlWebpackTemplate)
    .end()
  .plugin('script-ext')
    .use(ScriptExtWebpackPlugin);
Config resolve plugins
// Backed at config.resolve.plugins
config.resolve.plugin(name) : ChainedMap
Config resolve plugins: adding

留神: 不要应用 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)

// Example

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

// Example

config.resolve
  .plugin('beta')
    .after('alpha')
    .use(BetaWebpackTemplate)
    .end()
  .plugin('alpha')
    .use(AlphaWebpackPlugin);
Config node
config.node : ChainedMap

config.node
  .set('__dirname', 'mock')
  .set('__filename', 'mock');
Config devServer
config.devServer : ChainedMap
Config devServer allowedHosts
config.devServer.allowedHosts : ChainedSet

config.devServer.allowedHosts
  .add(value)
  .prepend(value)
  .clear()
Config devServer: shorthand methods
config.devServer
  .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 : ChainedMap

config.module
  .noParse(noParse)
Config module rules: shorthand methods
config.module.rules : ChainedMap

config.module
  .rule(name)
    .test(test)
    .pre()
    .post()
    .enforce(preOrPost)
Config module rules uses (loaders): creating
config.module.rules{}.uses : ChainedMap

config.module
  .rule(name)
    .use(name)
      .loader(loader)
      .options(options)

// Example

config.module
  .rule('compile')
    .use('babel')
      .loader('babel-loader')
      .options({presets: ['@babel/preset-env'] });
Config module rules uses (loaders): modifying options
config.module
  .rule(name)
    .use(name)
      .tap(options => newOptions)

// Example

config.module
  .rule('compile')
    .use('babel')
      .tap(options => merge(options, {plugins: ['@babel/plugin-proposal-class-properties']
      }));
Config module rules oneOfs (conditional rules):
config.module.rules{}.oneOfs : ChainedMap<Rule>

config.module
  .rule(name)
    .oneOf(name)

// Example

config.module
  .rule('css')
    .oneOf('inline')
      .resourceQuery(/inline/)
      .use('url')
        .loader('url-loader')
        .end()
      .end()
    .oneOf('external')
      .resourceQuery(/external/)
      .use('file')
        .loader('file-loader')
Config module rules oneOfs (conditional rules): ordering before

指定上下文的以后上下文应该在另一个已命名的上下文之前操作。.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')
Config module rules oneOfs (conditional rules): ordering after

指定上下文的以后上下文应该在另一个已命名的上下文之后操作。.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')

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-map
config
  .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

正文完
 0