作用
- 将模块打包生成后的 id 变成 hash 值,用于生成稳定的模块 id
new webpack.ids.HashedModuleIdsPlugin(),
![在这里插入图片描述](https://img-blog.csdnimg.cn/7c322c1090b748c2a3a791c83d529788.png#pic_left)
涉及 webpack API
const chunkGraph = compilation.chunkGraph;
-
获取当前编译过程中被使用过的 module id:compilation.usedModuleIds
compilation.usedModuleIds;
-
获取当前编译过程中所有的模块对象:compilation.modules
for (const module of compilation.modules) {
}
-
判断 module 是否需要生成 id:module.needId
- 表示该模块是否需要一个模块 id, 在 webpack 的编译过程中,有些模块可能不需要一个独立的模块 id,例如一些内置模块或者一些被动态加载的模块
for (const module of compilation.modules) {
if (!module.needId) continue;
const moduleId = chunkGraph.getModuleId(module);
}
-
获取指定module 的 module id:chunkGraph.getModuleId
for (const module of compilation.modules) {
if (!module.needId) continue;
const moduleId = chunkGraph.getModuleId(module);
}
-
获取 module 属于多少个chunk:chunkGraph.getNumberOfModuleChunks
if (chunkGraph.getNumberOfModuleChunks(module) !== 0){
}
-
获取 module 标识符:module.identifier
- 根据 module 的 type、request、layer创建
for (const module of compilation.modules) {
module.identifier()
}
identifier() {
if (this.layer === null) {
if (this.type === "javascript/auto") {
return this.request;
} else {
return `${this.type}|${this.request}`;
}
} else {
return `${this.type}|${this.request}|${this.layer}`;
}
}
-
设置 module id:chunkGraph.setModuleId
for (const module of compilation.modules) {
const moduleId= 'xxx'
chunkGraph.setModuleId(module, moduleId);
}
实现
constructor
class HashedModuleIdsPlugin {
constructor(options = {}) {
validate(options);
this.options = {
context: null,
hashFunction: "md4",
hashDigest: "base64",
hashDigestLength: 4,
...options
};
}
}
apply
apply(compiler) {
const options = this.options;
compiler.hooks.compilation.tap("HashedModuleIdsPlugin", compilation => {
compilation.hooks.moduleIds.tap("HashedModuleIdsPlugin", () => {
const chunkGraph = compilation.chunkGraph;
const context = this.options.context
? this.options.context
: compiler.context;
const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
const modulesInNaturalOrder = modules.sort(
compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
);
for (const module of modulesInNaturalOrder) {
const ident = getFullModuleName(module, context, compiler.root);
const hash = createHash(options.hashFunction);
hash.update(ident || "");
const hashId = (
hash.digest(options.hashDigest)
);
let len = options.hashDigestLength;
while (usedIds.has(hashId.slice(0, len))) len++;
const moduleId = hashId.slice(0, len);
chunkGraph.setModuleId(module, moduleId);
usedIds.add(moduleId);
}
});
});
}
getUsedModuleIdsAndModules
- 获取所有效的 modules 和已经编译使用过的 module id
- 只有需要生成 module id 的 module 且之前没有创建过且 module 在某个 chunk 中才有效
const getUsedModuleIdsAndModules = (compilation, filter) => {
const chunkGraph = compilation.chunkGraph;
const modules = [];
const usedIds = new Set();
if (compilation.usedModuleIds) {
for (const id of compilation.usedModuleIds) {
usedIds.add(id + "");
}
}
for (const module of compilation.modules) {
if (!module.needId) continue;
const moduleId = chunkGraph.getModuleId(module);
if (moduleId !== null) {
usedIds.add(moduleId + "");
} else {
if (
(!filter || filter(module)) &&
chunkGraph.getNumberOfModuleChunks(module) !== 0
) {
modules.push(module);
}
}
}
return [usedIds, modules];
};