webpack 配置是基于 JavaScript 对象,跨项目修改对象会变得很混乱。 webpack-chain 通过为创建和修改 webpack 配置提供一个可链式调用 API 来改进这个过程。
webpack-chain简单的例子
const Config = require('webpack-chain');
const config = new Config();
config
.entry('index')
.add('src/index.js')
.end()
.output
.path('dist')
.filename('[name].bundle.js')
.end()
console.log(config.toConfig())
最终生成的配置如下
{
entry: {
index: [ 'src/index.js' ]
},
output: {
path: 'dist',
filename: '[name].bundle.js'
}
}
核心原理解析
webpack 配置的本质是一个对象,分别向 entry, output, plugin等key中添加属性,最终合并成一个对象
webpack对象值分为三种
- 基本类型 string, boolean
- 对象
- 数组
在webpack-chain中分别对应 function, Map,Set
以output为例解析Map对象
核心
// ChainedMap.js
module.exports = class ChainedMap {
constructor(parent) {
this.parent = parent
this.store = new Map();
}
// 添加属性
set(key, value) {
this.store.set(key, value);
return this;
}
// 最终生成配置
toConfig() {
return [...this.store].reduce((acc, [key, value]) => {
acc[key] = value;
return acc;
}, {});
}
// 链式调用使用
end() {
return this.parent
}
}
output配置
// config.js
const ChainedMap = require('./ChainedMap');
class Output extends ChainedMap {
constructor(parent) {
super(parent)
this.path = (value) => this.set('path', value);
this.filename = (value) => this.set('filename', value);
}
}
module.exports = class Config {
constructor() {
this.output = new Output(this)
}
toConfig() {
return {
output: this.output.toConfig()
}
}
}
此时即可通过如下代码生成output配置
const Config = require('./Config');
const config = new Config();
config
.output
.path('dist')
.filename('[name].bundle.js')
.end()
// 最终生成 { output: { path: 'dist', filename: '[name].bundle.js' } }
console.log(config.toConfig())
其他
其他配置原理基本相同,不同数据结构有相应的调整,如entry是一个对象,但对象每个属性值都可以是一个数组,需要做相应的处理。pligin和moudule配置会更复杂。这里只介绍基本原理,有兴趣的可以直接查看源码