赞助 webpack,同时从官方商店购买衣服 所有收益将转到我们的 open collective

插件模式

在 webpack 构建系统中,能够通过插件进行定制,这赋予了无限的可能性。这使你可以创建自定义资源类型(asset type),执行唯一的构建修改(build modification),甚至可以使用中间件来增强 webpack 运行时。下面是在编写插件时非常有用一些 webpack 的功能。

检索遍历资源(asset)、chunk、模块和依赖

在执行完成编译的封存阶段(seal)之后,编译(compilation)的所有结构都可以遍历。

class MyPlugin {
  apply(compiler) {
    compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
      // 检索每个(构建输出的)chunk:
      compilation.chunks.forEach(chunk => {
        // 检索 chunk 中(内置输入的)的每个模块:
        chunk.modules.forEach(module => {
          // 检索模块中包含的每个源文件路径:
          module.fileDependencies.forEach(filepath => {
            // 我们现在已经对源结构有不少了解……
          });
        });

        // 检索由 chunk 生成的每个资源(asset)文件名:
        chunk.files.forEach(filename => {
          // Get the asset source for each file generated by the chunk:
          var source = compilation.assets[filename].source();
        });
      });

      callback();
    });
  }
}
module.exports = MyPlugin;
  • compilation.modules:编译后的(内置输入的)模块数组。每个模块管理控制来源代码库(source library)中的原始文件(raw file)的构建。
  • module.fileDependencies:模块中引入的源文件路径构成的数组。这包括源 JavaScript 文件本身(例如:index.js)以及它所需的所有依赖资源文件(样式表、图像等)。审查依赖,可以用于查看一个模块有哪些从属的源文件。
  • compilation.chunks:编译后的(构建输出的)chunk 数组。每个 chunk 所管理控制的最终渲染资源的组合。
  • chunk.modules:chunk 中引入的模块构成的数组。通过扩展(extension)可以审查每个模块的依赖,来查看哪些原始源文件被注入到 chunk 中。
  • chunk.files:chunk 生成的输出文件名构成的数组。你可以从 compilation.assets 表中访问这些资源来源。

监听观察图(watch graph)的修改

运行 webpack 中间件时,每个编译包括一个 fileDependencies 数组(正在观察哪些文件)和一个 fileTimestamps 哈希,它将被观察的文件路径映射到时间戳。这可以用于检测编译中哪些文件已经修改:

class MyPlugin {
  constructor() {
    this.startTime = Date.now();
    this.prevTimestamps = {};
  }
  apply(compiler) {
    compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
      var changedFiles = Object.keys(compilation.fileTimestamps).filter(
        watchfile => {
          return (
            (this.prevTimestamps[watchfile] || this.startTime) <
            (compilation.fileTimestamps[watchfile] || Infinity)
          );
        }
      );

      this.prevTimestamps = compilation.fileTimestamps;
      callback();
    });
  }
}

module.exports = MyPlugin;

还可以将新文件路径添加到观察图(watch graph)中,以在这些文件修改时,接收消息和重新触发编译。只要将有效的文件路径推送到 compilation.fileDependencies 数组中,就可以将其添加到观察图中。注意:fileDependencies 数组在每次编译时都会重新构建,因此你的插件必须将自己要观察的依赖都推送到每次编译中,以使它们都处于观察中。

监听 chunk 的修改

类似于观察图(watch graph),监听 chunk(或者模块,就当前情况而言)的修改也很简单,通过在编译时跟踪它们的 hash 来实现。

class MyPlugin {
  constructor() {
    this.chunkVersions = {};
  }
  apply(compiler) {
    compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
      var changedChunks = compilation.chunks.filter(chunk => {
        var oldVersion = this.chunkVersions[chunk.name];
        this.chunkVersions[chunk.name] = chunk.hash;
        return chunk.hash !== oldVersion;
      });
      callback();
    });
  }
}

module.exports = MyPlugin;

贡献人员