webpack 输出打包信息源码分析

1,813 阅读4分钟

前言

最近打算写一款webpack压缩图片的插件,但是需要数据对比,原始数据和压缩后的数据以及压缩的比例相关信息,于是想到了webpack打包的时候不就有相关的输出嘛,于是查看了一下webpack是怎么输出信息的。

输出文件

  • 首先在webpack官网看到所有输出的相关信息全部有stats来管理的,自然而安的我们找到webpack源码里面的Stats.js来查找我们想要的信息。 找到toString方法,这个就是我们呢输出文件的调用方法,代码如下
toString(options) {
  if (typeof options === "boolean" || typeof options === "string") {
   options = Stats.presetToOptions(options);
  } else if (!options) {
   options = {};
  }

  const useColors = optionsOrFallback(options.colors, false);

  const obj = this.toJson(options, true);

  return Stats.jsonToString(obj, useColors);
 }
  • 接下来我们查看jsonToString这个方法
const defaultColors = {
  bold: "\u001b[1m",
  yellow: "\u001b[1m\u001b[33m",
  red: "\u001b[1m\u001b[31m",
  green: "\u001b[1m\u001b[32m",
  cyan: "\u001b[1m\u001b[36m",
  magenta: "\u001b[1m\u001b[35m"
};

可以看到webpack内置了一下输出颜色样式,具体颜色规则可移步这里
然后对defaultColors进行一步处理,代码如下

const colors = Object.keys(defaultColors).reduce(
  (obj, color) => {
    obj[color] = str => {
      if (useColors) {
        buf.push(
          useColors === true || useColors[color] === undefined
            ? defaultColors[color]
            : useColors[color]
        );
      }
      buf.push(str);
      if (useColors) {
        buf.push("\u001b[39m\u001b[22m");
      }
    };
    return obj;
  },
  {
    normal: str => buf.push(str)
  }
);

得到最终的colors如下

normal: [Function: normal],
  bold: [Function],
  yellow: [Function],
  red: [Function],
  green: [Function],
  cyan: [Function],
  magenta: [Function] }
  • 然后我们往下继续查找,
[  {    value: "Asset",    color: colors.bold  },  {    value: "Size",    color: colors.bold  },  {    value: "Chunks",    color: colors.bold  },  {    value: "",    color: colors.bold  },  {    value: "",    color: colors.bold  },  {    value: "Chunk Names",    color: colors.bold  }]

这些信息不正是我们webpack默认打包输出的信息嘛,然后继续找,直到我们找到table(t, "rrrlll")这段代码,我们来看看table这个函数是干嘛的。具体代码我这边注释如下

/**
 * 
 * @param {Array} array 输出文件的集合
 * @param {String} align 排列方式 l左对齐 r右对齐
 * @param {String} splitter 在输出的文件左右添加
 */
const table = (array, align, splitter) => {
  const rows = array.length; // 输出的行数
  const cols = array[0].length; // 输出的列数
  const colSizes = new Array(cols);
  // 初始化每列最长的字符串长度
  for (let col = 0; col < cols; col++) {
    colSizes[col] = 0;
  }
  // 找到每列最长的字符串的长度
  for (let row = 0; row < rows; row++) {
    for (let col = 0; col < cols; col++) {
      const value = `${getText(array, row, col)}`;
      if (value.length > colSizes[col]) {
        colSizes[col] = value.length;
      }
    }
  }
  for (let row = 0; row < rows; row++) {
    for (let col = 0; col < cols; col++) {
      const format = array[row][col].color;
      const value = `${getText(array, row, col)}`;
      let l = value.length;
      if (align[col] === "l") {
        format(value);
      }
      // 该字符串的长度小于本列最长的字符串的话,添加' '
      for (; l < colSizes[col] && col !== cols - 1; l++) {
        colors.normal(" ");
      }
      if (align[col] === "r") {
        format(value);
      }
      if (col + 1 < cols && colSizes[col] !== 0) {
        colors.normal(splitter || "  ");
      }
    }
    // 换行
    newline();
  }
};
  • 最后我们把buf.join('')输出出来就是我们所需要的输出样式了

压缩

最后我们测试一下写的压缩图片,测试结果如下:

参考资料

webpack