细说细说webpack源码之源码之compile流程流程-rules参数处理技巧参数处理技巧(2)
主要介绍了webpack源码之compile流程-rules参数处理技巧的相关知识,需要的朋友参考下吧
上篇文章给大家介绍了细说webpack源码之compile流程-rules参数处理技巧(1), 细说webpack源码之compile流程-入口函数run
大家可以点击查看。
第一步处理rule为字符串,直接返回一个包装类,很简单看注释就好了。
test
然后处理test、include、exclude,如下:
if (rule.test || rule.include || rule.exclude) {
// 标记使用参数
checkResourceSource("test + include + exclude");
// 没有就是undefined
condition = {
test: rule.test,
include: rule.include,
exclude: rule.exclude
};
// 处理常规参数
try {
newRule.resource = RuleSet.normalizeCondition(condition);
} catch (error) {
throw new Error(RuleSet.buildErrorMessage(condition, error));
}
}
checkResourceSource直接看源码:
let resourceSource;
// ...
function checkResourceSource(newSource) {
// 第一次直接跳到后面赋值
if (resourceSource && resourceSource !== newSource)
throw new Error(RuleSet.buildErrorMessage(rule, new Error("Rule can only have one resource source (provided " + newSource + " and " + resourceSource + ")")));
resourceSource = newSource;
}
这个用于检测配置来源的唯一性,后面会能看到作用,同样作用的还有checkUseSource方法。
随后将三个参数包装成一个对象传入normalizeCondition方法,该方法对常规参数进行函数包装:
class RuleSet {
constructor(rules) { /**/ };
static normalizeCondition(condition) {
// 假值报错
if (!condition) throw new Error("Expected condition but got falsy value");
// 检测给定字符串是否以这个开头
if (typeof condition === "string") { return str => str.indexOf(condition) === 0; }
// 函数直接返回
if (typeof condition === "function") { return condition; }
// 正则表达式返回一个正则的test函数
if (condition instanceof RegExp) { return condition.test.bind(condition); }
// 数组map递归处理 有一个满足返回true
if (Array.isArray(condition)) {
const items = condition.map(c => RuleSet.normalizeCondition(c));
return orMatcher(items);
}
if (typeof condition !== "object") throw Error("Unexcepted " + typeof condition + " when condition was expected (" + condition + ")");
const matchers = [];
// 对象会对每个值进行函数包装弹入matchers中
Object.keys(condition).forEach(key => {
const value = condition[key];
switch (key) {
case "or":
case "include":
case "test":
if (value)
matchers.push(RuleSet.normalizeCondition(value));
break;
case "and":
if (value) {
const items = value.map(c => RuleSet.normalizeCondition(c));
matchers.push(andMatcher(items));
}
break;
case "not":
case "exclude":