webpack-chain 核心原理解析

416 阅读1分钟

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配置会更复杂。这里只介绍基本原理,有兴趣的可以直接查看源码