在 webpack 构建系统中,能够通过插件进行定制,这赋予了无限的可能性。这使你可以创建自定义资源类型,执行唯一的构建修改,甚至可以使用中间件来增强 webpack 运行时。下面是在编写插件时非常有用一些 webpack 的功能。
在执行完成编译的封存阶段后,编译的所有结构都可以遍历。
class MyPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
// 检索每个(构建输出的)chunk:
compilation.chunks.forEach((chunk) => {
// 检索 chunk 中(内置输入的)的每个模块:
chunk.getModules().forEach((module) => {
// 检索模块中包含的每个源文件路径:
module.buildInfo &&
module.buildInfo.fileDependencies &&
module.buildInfo.fileDependencies.forEach((filepath) => {
// 我们现在已经对源结构有不少了解……
});
});
// 检索由 chunk 生成的每个资源文件名:
chunk.files.forEach((filename) => {
// 获取 chunk 生成的每个文件的资源源代码:
var source = compilation.assets[filename].source();
});
});
callback();
});
}
}
module.exports = MyPlugin;
compilation.modules
:编译后的(内置输入的)模块数组。每个模块管理控制来源代码库中的原始文件的构建。module.fileDependencies
:模块中引入的源文件路径构成的数组。这包括源 JavaScript 文件本身(例如:index.js)以及它所需的所有依赖资源文件(样式表、图像等)。审查依赖,可以用于查看一个模块有哪些从属的源文件。compilation.chunks
:编译后的(构建输出的)chunk 集合。每个 chunk 所管理控制的最终渲染资源的组合。chunk.getModules()
:chunk 中引入的模块构成的数组。通过扩展可以审查每个模块的依赖,来查看哪些原始源文件被注入到 chunk 中。chunk.files
:chunk 生成的输出文件名构成的集合。你可以从 compilation.assets
表中访问这些资源来源。运行 webpack 中间件时,每个编译包括一个 fileDependencies
Set
(正在观察哪些文件)和一个 fileTimestamps
Map
,它将被观察的文件路径映射到时间戳。这可以用于检测编译中哪些文件已经修改:
class MyPlugin {
constructor() {
this.startTime = Date.now();
this.prevTimestamps = new Map();
}
apply(compiler) {
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
const changedFiles = Array.from(compilation.fileTimestamps.keys()).filter(
(watchfile) => {
return (
(this.prevTimestamps.get(watchfile) || this.startTime) <
(compilation.fileTimestamps.get(watchfile) || Infinity)
);
}
);
this.prevTimestamps = compilation.fileTimestamps;
callback();
});
}
}
module.exports = MyPlugin;
还可以将新文件路径添加到观察图中,以在这些文件修改时,接收消息和重新触发编译。只要将有效的文件路径推送到 compilation.fileDependencies
Set
中,就可以将其添加到观察图中。
类似于观察图,监听 chunk(或者模块,就当前情况而言)的修改也很简单,通过在编译时跟踪它们的哈希来实现。
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;