
文章目录
- 作用
- 涉及 webpack API
-
- 获取chunkGraph
- 获取当前编译过程中被使用过的 module id:compilation.usedModuleIds
- 获取当前编译过程中所有的模块对象:compilation.modules
- 判断 module 是否需要生成 id:module.needId
- 获取指定module 的 module id:chunkGraph.getModuleId
- 获取 module 属于多少个chunk:chunkGraph.getNumberOfModuleChunks
- 获取 module 标识符:module.identifier
- 设置 module id:chunkGraph.setModuleId
- 实现
-
- constructor
- apply
- getUsedModuleIdsAndModules
作用
- 将模块打包生成后的 id 变成 hash 值,用于生成稳定的模块 id
new webpack.ids.HashedModuleIdsPlugin(),

涉及 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];
};