细说webpack源码之compile流程-rules参数处理技巧(2(2)

  这里用js的rules做案例,看这个方法的返回:

class RuleSet {
 constructor(rules) { /**/ };
 /*
 Example:
 {
  test: /\.js$/,
  loader: 'babel-loader',
  include: [resolve('src'), resolve('test')]
 }
 */
 /*
 condition:
 {
  test: /\.js$/,
  include: ['d:\\workspace\\src', 'd:\\workspace\\test'],
  exclude: undefined
 }
 */
 static normalizeCondition(condition) {
 // include返回类似于 [(str) => str.indexOf('d:\\workspace\\src') === 0,...] 的函数
 if (typeof condition === "string") { return str => str.indexOf(condition) === 0; }
 // test参数返回了 /\.js$/.test 函数
 if (condition instanceof RegExp) { return condition.test.bind(condition); }
 // include为数组
 if (Array.isArray(condition)) {
  const items = condition.map(c => RuleSet.normalizeCondition(c));
  return orMatcher(items);
 }
 const matchers = [];
 // 解析出['test','include','exclude']
 Object.keys(condition).forEach(key => {
  const value = condition[key];
  switch (key) {
  // 此value为一个数组
  case "include":
  case "test":
   if (value)
   matchers.push(RuleSet.normalizeCondition(value));
   break;
  // undefined跳过
  case "exclude":
   if (value) { /**/ }
   break;
  default:
   throw new Error("Unexcepted property " + key + " in condition");
  }
 });
 return andMatcher(matchers);
 }
}

  这里继续看orMatcher、andMatcher函数的处理:

function orMatcher(items) {
 // 当一个函数被满足条件时返回true
 return function(str) {
 for (let i = 0; i < items.length; i++) {
  if (items[i](str))
  return true;
 }
 return false;
 };
}

function andMatcher(items) {
 // 当一个条件不满足时返回false
 return function(str) {
 for (let i = 0; i < items.length; i++) {
  if (!items[i](str))
  return false;
 }
 return true;
 };
}

  从字面意思也可以理解函数作用,比如说这里的include被包装成一个orMatcher函数,传入的字符串无论是以数组中任何一个元素开头都会返回true,andMatcher以及未出现的notMatcher同理。

resource

  下面是对resource参数的处理,源码如下:

if (rule.resource) {
 // 如果前面检测到了test || include || exclude参数 这里会报错
 checkResourceSource("resource");
 try {
 newRule.resource = RuleSet.normalizeCondition(rule.resource);
 } catch (error) {
 throw new Error(RuleSet.buildErrorMessage(rule.resource, error));
 }
}

  可以看出这个参数与前面那个是互斥的,应该是老版API,下面两种方式实现是一样的:

/*
方式1:
 rules:[
 {
  test: /\.js$/,
  loader: 'babel-loader',
  include: [resolve('src'), resolve('test')]
 }
 ]
*/
/*
方式2:
 rules:[
 {
  resource:{
  test: /\.js$/,
  include: [resolve('src'), resolve('test')]
  exclude: undefined
  }
 }
 ]
*/
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/456.html