webpack/lib/RecordIdsPlugin.js

122 lines
4.5 KiB
JavaScript
Raw Normal View History

2013-05-31 18:22:40 +08:00
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
2017-02-21 22:13:09 +08:00
"use strict";
const identifierUtils = require("./util/identifier");
class RecordIdsPlugin {
constructor(options) {
this.options = options || {};
}
2017-02-21 22:13:09 +08:00
apply(compiler) {
const portableIds = this.options.portableIds;
2017-12-06 22:01:25 +08:00
compiler.hooks.compilation.tap("RecordIdsPlugin", (compilation) => {
compilation.hooks.recordModules.tap("RecordIdsPlugin", (modules, records) => {
2017-02-21 22:13:09 +08:00
if(!records.modules) records.modules = {};
if(!records.modules.byIdentifier) records.modules.byIdentifier = {};
if(!records.modules.usedIds) records.modules.usedIds = {};
2017-11-08 18:32:05 +08:00
modules.forEach(module => {
const identifier = portableIds ? identifierUtils.makePathsRelative(compiler.context, module.identifier(), compilation.cache) : module.identifier();
2017-02-21 22:13:09 +08:00
records.modules.byIdentifier[identifier] = module.id;
records.modules.usedIds[module.id] = module.id;
});
2017-02-21 22:13:09 +08:00
});
2017-12-06 22:01:25 +08:00
compilation.hooks.reviveModules.tap("RecordIdsPlugin", (modules, records) => {
2017-02-21 22:13:09 +08:00
if(!records.modules) return;
if(records.modules.byIdentifier) {
2018-01-05 14:41:09 +08:00
const usedIds = new Set();
2017-11-08 18:32:05 +08:00
modules.forEach(module => {
2017-02-21 22:13:09 +08:00
if(module.id !== null) return;
const identifier = portableIds ? identifierUtils.makePathsRelative(compiler.context, module.identifier(), compilation.cache) : module.identifier();
2017-02-21 22:13:09 +08:00
const id = records.modules.byIdentifier[identifier];
if(id === undefined) return;
2018-01-05 14:41:09 +08:00
if(usedIds.has(id)) return;
usedIds.add(id);
2017-02-21 22:13:09 +08:00
module.id = id;
});
}
compilation.usedModuleIds = records.modules.usedIds;
});
2015-04-24 05:55:50 +08:00
2017-11-08 18:32:05 +08:00
const getDepBlockIdent = (chunk, block) => {
2017-02-21 22:13:09 +08:00
const ident = [];
if(block.chunks.length > 1)
ident.push(block.chunks.indexOf(chunk));
while(block.parent) {
const p = block.parent;
const idx = p.blocks.indexOf(block);
const l = p.blocks.length - 1;
ident.push(`${idx}/${l}`);
2017-02-21 22:13:09 +08:00
block = block.parent;
}
if(!block.identifier) return null;
const identifier = portableIds ? identifierUtils.makePathsRelative(compiler.context, block.identifier(), compilation.cache) : block.identifier();
ident.push(identifier);
return ident.reverse().join(":");
2017-11-08 18:32:05 +08:00
};
2017-12-06 22:01:25 +08:00
compilation.hooks.recordChunks.tap("RecordIdsPlugin", (chunks, records) => {
2017-02-21 22:13:09 +08:00
records.nextFreeChunkId = compilation.nextFreeChunkId;
if(!records.chunks) records.chunks = {};
if(!records.chunks.byName) records.chunks.byName = {};
if(!records.chunks.byBlocks) records.chunks.byBlocks = {};
records.chunks.usedIds = {};
chunks.forEach(chunk => {
const name = chunk.name;
const blockIdents = chunk.mapBlocks(getDepBlockIdent.bind(null, chunk)).filter(Boolean);
2017-02-21 22:13:09 +08:00
if(name) records.chunks.byName[name] = chunk.id;
blockIdents.forEach((blockIdent) => {
records.chunks.byBlocks[blockIdent] = chunk.id;
});
records.chunks.usedIds[chunk.id] = chunk.id;
2013-05-31 18:22:40 +08:00
});
});
2017-12-06 22:01:25 +08:00
compilation.hooks.reviveChunks.tap("RecordIdsPlugin", (chunks, records) => {
2017-02-21 22:13:09 +08:00
if(!records.chunks) return;
2018-01-05 14:41:09 +08:00
const usedIds = new Set();
2017-02-21 22:13:09 +08:00
if(records.chunks.byName) {
2017-11-08 18:32:05 +08:00
chunks.forEach(chunk => {
2017-02-21 22:13:09 +08:00
if(chunk.id !== null) return;
if(!chunk.name) return;
const id = records.chunks.byName[chunk.name];
if(id === undefined) return;
2018-01-05 14:41:09 +08:00
if(usedIds.has(id)) return;
usedIds.add(id);
2017-02-21 22:13:09 +08:00
chunk.id = id;
});
}
if(records.chunks.byBlocks) {
const argumentedChunks = chunks.filter(chunk => chunk.id === null).map(chunk => ({
chunk,
blockIdents: chunk.mapBlocks(getDepBlockIdent.bind(null, chunk)).filter(Boolean)
2017-02-21 22:13:09 +08:00
})).filter(arg => arg.blockIdents.length > 0);
let blockIdentsCount = {};
argumentedChunks.forEach((arg, idx) => {
arg.blockIdents.forEach(blockIdent => {
const id = records.chunks.byBlocks[blockIdent];
if(typeof id !== "number") return;
const accessor = `${id}:${idx}`;
blockIdentsCount[accessor] = (blockIdentsCount[accessor] || 0) + 1;
});
2013-05-31 18:22:40 +08:00
});
2017-02-21 22:13:09 +08:00
blockIdentsCount = Object.keys(blockIdentsCount).map(accessor => [blockIdentsCount[accessor]].concat(accessor.split(":").map(Number))).sort((a, b) => b[0] - a[0]);
2017-11-08 18:32:05 +08:00
blockIdentsCount.forEach(arg => {
2017-02-21 22:13:09 +08:00
const id = arg[1];
2018-01-05 14:41:09 +08:00
if(usedIds.has(id)) return;
2017-02-21 22:13:09 +08:00
const idx = arg[2];
const chunk = argumentedChunks[idx].chunk;
if(chunk.id !== null) return;
2018-01-05 14:41:09 +08:00
usedIds.add(id);
2017-02-21 22:13:09 +08:00
chunk.id = id;
});
}
compilation.usedChunkIds = records.chunks.usedIds;
});
2013-05-31 18:22:40 +08:00
});
2017-02-21 22:13:09 +08:00
}
}
module.exports = RecordIdsPlugin;