作用
- 将模块打包生成后的 id 变成 hash 值,用于生成稳定的模块 id
new webpack.ids.HashedModuleIdsPlugin(),
文章来源地址https://www.toymoban.com/news/detail-416889.html
涉及 webpack API
-
获取chunkGraph
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
// chunkGraph.getNumberOfModuleChunks 表示 module 属于多少个chunk ,为 0 表示模块对象不属于任何一个 chunk
if (chunkGraph.getNumberOfModuleChunks(module) !== 0){
// ...
}
-
获取 module 标识符:module.identifier
- 根据 module 的 type、request、layer创建
for (const module of compilation.modules) {
module.identifier()
}
// module.identifier
identifier() {
if (this.layer === null) {
if (this.type === "javascript/auto") {
return this.request; // "/xxx/Desktop/webpack/wb/node_modules/babel-loader/lib/index.js??ruleSet[1].rules[1].use[0]!/xxx/Desktop/webpack/wb/src/o1.js"
} 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 {
/**
* @param {HashedModuleIdsPluginOptions=} options options object
*/
constructor(options = {}) {
validate(options);
/** @type {HashedModuleIdsPluginOptions} */
this.options = {
context: null,
hashFunction: "md4",
hashDigest: "base64",
hashDigestLength: 4,
...options
};
}
}
apply
apply(compiler) {
const options = this.options;
compiler.hooks.compilation.tap("HashedModuleIdsPlugin", compilation => {
// hooks.moduleIds 为每个模块分配 id 时触发
compilation.hooks.moduleIds.tap("HashedModuleIdsPlugin", () => {
const chunkGraph = compilation.chunkGraph;
const context = this.options.context // "/xxx/Desktop/webpack/wb"
? this.options.context
: compiler.context;
// 获取所有效的 modules 和已经编译使用过的 module id
const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
// 对 modules 排序
const modulesInNaturalOrder = modules.sort(
compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
);
for (const module of modulesInNaturalOrder) {
// 获取 module 标识,用来创建 hash
const ident = getFullModuleName(module, context, compiler.root); // "./node_modules/babel-loader/lib/index.js??ruleSet[1].rules[1].use[0]!./src/o1.js"
const hash = createHash(options.hashFunction);
hash.update(ident || "");
const hashId = /** @type {string} */ (
hash.digest(options.hashDigest)
);
let len = options.hashDigestLength;
// 默认取 hash 前四位,如果有重复往后取
while (usedIds.has(hashId.slice(0, len))) len++;
const moduleId = hashId.slice(0, len);
// 更改 module id
chunkGraph.setModuleId(module, moduleId);
// 添加新 module id
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();
// 用于存储在当前编译过程中被使用过的 module id。
if (compilation.usedModuleIds) {
for (const id of compilation.usedModuleIds) {
usedIds.add(id + "");
}
}
// compilation.modules: 存储在当前编译过程中所有的模块对象,包括那些被使用过的模块和那些没有被使用过的模块。
for (const module of compilation.modules) {
// module.needId 表示该模块是否需要一个模块 id, 在 webpack 的编译过程中,有些模块可能不需要一个独立的模块 id,例如一些内置模块或者一些被动态加载的模块
if (!module.needId) continue;
// 获取 module id
const moduleId = chunkGraph.getModuleId(module);
if (moduleId !== null) {
// 如果已有则跳过
usedIds.add(moduleId + "");
} else {
// chunkGraph.getNumberOfModuleChunks 表示 module 属于多少个chunk ,为 0 表示模块对象不属于任何一个 chunk
if (
(!filter || filter(module)) &&
chunkGraph.getNumberOfModuleChunks(module) !== 0
) {
// 将该 module 放入 modules 用于后续计算 module id hash 值
modules.push(module);
}
}
}
return [usedIds, modules];
};
文章来源:https://www.toymoban.com/news/detail-416889.html
到了这里,关于webpack plugin源码解析(四) HashedModuleIdsPlugin的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!