applyModuleIds() {
const unusedIds = [];//找到当前未使用的 id
let nextFreeModuleId = 0;//已经使用的最大的 id
const usedIds = new Set();
if (this.usedModuleIds) {
for (const id of this.usedModuleIds) {
usedIds.add(id);
}
}
const modules1 = this.modules;
for (let indexModule1 = 0; indexModule1 < modules1.length; indexModule1++) {
const module1 = modules1[indexModule1];
if (module1.id !== null) {
usedIds.add(module1.id);
}
}
if (usedIds.size > 0) {
let usedIdMax = -1;
for (const usedIdKey of usedIds) {
if (typeof usedIdKey !== "number") {
continue;
}
usedIdMax = Math.max(usedIdMax, usedIdKey);
}
let lengthFreeModules = (nextFreeModuleId = usedIdMax + 1);
while (lengthFreeModules--) {
if (!usedIds.has(lengthFreeModules)) {
unusedIds.push(lengthFreeModules);
}
}
}
const modules2 = this.modules;
for (let indexModule2 = 0; indexModule2 < modules2.length; indexModule2++) {
const module2 = modules2[indexModule2];
if (module2.id === null) {
if (unusedIds.length > 0) {
module2.id = unusedIds.pop();
} else {
module2.id = nextFreeModuleId++;
}
}
}
}
applyChunkIds() {
/** @type {Set<number>} */
const usedIds = new Set();
// Get used ids from usedChunkIds property (i. e. from records)
if (this.usedChunkIds) {
for (const id of this.usedChunkIds) {
if (typeof id !== "number") {
continue;
}
usedIds.add(id);
}
}
// Get used ids from existing chunks
const chunks = this.chunks;
for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
const chunk = chunks[indexChunk];
const usedIdValue = chunk.id;
if (typeof usedIdValue !== "number") {
continue;
}
usedIds.add(usedIdValue);
}
// Calculate maximum assigned chunk id
let nextFreeChunkId = -1;
for (const id of usedIds) {
nextFreeChunkId = Math.max(nextFreeChunkId, id);
}
nextFreeChunkId++;
// Determine free chunk ids from 0 to maximum
/** @type {number[]} */
const unusedIds = [];
if (nextFreeChunkId > 0) {
let index = nextFreeChunkId;
while (index--) {
if (!usedIds.has(index)) {
unusedIds.push(index);
}
}
}
// Assign ids to chunk which has no id
for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
const chunk = chunks[indexChunk];
if (chunk.id === null) {
if (unusedIds.length > 0) {
chunk.id = unusedIds.pop();
} else {
chunk.id = nextFreeChunkId++;
}
}
if (!chunk.ids) {
chunk.ids = [chunk.id];
}
}
}
Module.js
updateHash(hash) {
hash.update(`${this.id}`);
hash.update(JSON.stringify(this.usedExports));
super.updateHash(hash);
}
Chunk.js
updateHash(hash) {
hash.update(`${this.id} `);
hash.update(this.ids ? this.ids.join(",") : "");
hash.update(`${this.name || ""} `);
for (const m of this._modules) {
hash.update(m.hash);
}
}
hash 值生成之后,会调用 createChunkAssets
方法来决定最终输出到每个 chunk 当中对应的文本内容
获取对应的渲染模板
render()
得到最终的代码assets
中