move Module.hash and .renderedHash into ChunkGraph

This commit is contained in:
Tobias Koppers 2018-08-22 19:23:48 +02:00
parent 190a8af6d4
commit 3aa2280498
15 changed files with 183 additions and 54 deletions

View File

@ -5,13 +5,15 @@
"use strict";
const validateOptions = require("schema-utils");
const { ConcatSource } = require("webpack-sources");
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
const Template = require("./Template");
const validateOptions = require("schema-utils");
const schema = require("../schemas/plugins/BannerPlugin.json");
/** @typedef {import("./Compiler")} Compiler */
const wrapComment = str => {
if (!str.includes("\n")) {
return Template.toComment(str);
@ -47,6 +49,10 @@ class BannerPlugin {
}
}
/**
* @param {Compiler} compiler webpack compiler
* @returns {void}
*/
apply(compiler) {
const options = this.options;
const banner = this.banner;

View File

@ -78,7 +78,7 @@ class Chunk {
this.rendered = false;
/** @type {string=} */
this.hash = undefined;
/** @type {Object} */
/** @type {Record<string, string>} */
this.contentHash = Object.create(null);
/** @type {string=} */
this.renderedHash = undefined;
@ -359,14 +359,14 @@ class Chunk {
this,
compareModulesById(compilation.moduleGraph)
)) {
hash.update(m.hash);
hash.update(compilation.chunkGraph.getModuleHash(m));
}
const entryModules = compilation.chunkGraph.getChunkEntryModulesWithChunkGroupIterable(
this
);
for (const [m, chunkGroup] of entryModules) {
hash.update("entry");
hash.update(m.hash);
hash.update(compilation.chunkGraph.getModuleHash(m));
hash.update(chunkGroup.id);
}
}

View File

@ -74,6 +74,10 @@ class ChunkGraphModule {
this.chunks = new SortableSet();
/** @type {Set<Chunk>} */
this.entryInChunks = new Set();
/** @type {string} */
this.hash = undefined;
/** @type {string} */
this.renderedHash = undefined;
}
}
@ -384,7 +388,7 @@ class ChunkGraph {
chunkModuleIdMap[asyncChunk.id] = array;
}
array.push(module.id);
chunkModuleHashMap[module.id] = module.renderedHash;
chunkModuleHashMap[module.id] = this.getRenderedModuleHash(module);
}
}
if (array !== undefined) {
@ -674,6 +678,36 @@ class ChunkGraph {
return cgc.entryModules;
}
/**
* @param {Module} module the module
* @returns {string} hash
*/
getModuleHash(module) {
const cgm = this._getChunkGraphModule(module);
return cgm.hash;
}
/**
* @param {Module} module the module
* @returns {string} hash
*/
getRenderedModuleHash(module) {
const cgm = this._getChunkGraphModule(module);
return cgm.renderedHash;
}
/**
* @param {Module} module the module
* @param {string} hash the full hash
* @param {string} renderedHash the shortened hash for rendering
* @returns {void}
*/
setModuleHashes(module, hash, renderedHash) {
const cgm = this._getChunkGraphModule(module);
cgm.hash = hash;
cgm.renderedHash = renderedHash;
}
// TODO remove in webpack 6
/**
* @param {Module} module the module

View File

@ -105,6 +105,41 @@ const createHash = require("./util/createHash");
* @property {AsyncDependenciesBlock[]} blocks
*/
/**
* @typedef {Object} ChunkPathData
* @property {string|number} id
* @property {string=} name
* @property {string} hash
* @property {string} renderedHash
* @property {function(number): string=} hashWithLength
* @property {(Record<string, string>)=} contentHash
* @property {(Record<string, (length: number) => string>)=} contentHashWithLength
*/
/**
* @typedef {Object} ModulePathData
* @property {string|number} id
* @property {string} hash
* @property {string} renderedHash
* @property {function(number): string=} hashWithLength
*/
/**
* @typedef {Object} PathData
* @property {ChunkGraph=} chunkGraph
* @property {string=} hash
* @property {function(number): string=} hashWithLength
* @property {(Chunk|ChunkPathData)=} chunk
* @property {(Module|ModulePathData)=} module
* @property {string=} filename
* @property {string=} basename
* @property {string=} query
* @property {string=} contentHashType
* @property {string=} contentHash
* @property {function(number): string=} contentHashWithLength
* @property {boolean=} noChunkHash
*/
/**
* @param {Chunk} a first chunk to sort by id
* @param {Chunk} b second chunk to sort by id
@ -2065,6 +2100,7 @@ class Compilation {
}
createHash() {
const chunkGraph = this.chunkGraph;
const outputOptions = this.outputOptions;
const hashFunction = outputOptions.hashFunction;
const hashDigest = outputOptions.hashDigest;
@ -2092,8 +2128,12 @@ class Compilation {
const module = modules[i];
const moduleHash = createHash(hashFunction);
module.updateHash(moduleHash, this);
module.hash = moduleHash.digest(hashDigest);
module.renderedHash = module.hash.substr(0, hashDigestLength);
const moduleHashDigest = moduleHash.digest(hashDigest);
chunkGraph.setModuleHashes(
module,
moduleHashDigest,
moduleHashDigest.substr(0, hashDigestLength)
);
}
// clone needed as sort below is inplace mutation
const chunks = this.chunks.slice();
@ -2151,7 +2191,10 @@ class Compilation {
const module = this.modules[i];
if (module.buildInfo.assets) {
for (const assetName of Object.keys(module.buildInfo.assets)) {
const fileName = this.getPath(assetName);
const fileName = this.getPath(assetName, {
chunkGraph: this.chunkGraph,
module
});
this.assets[fileName] = module.buildInfo.assets[assetName];
this.hooks.moduleAsset.call(module, fileName);
}
@ -2261,11 +2304,10 @@ class Compilation {
/**
* @param {string} filename used to get asset path with hash
* @param {TODO=} data // TODO: figure out this param type
* @param {PathData} data context data
* @returns {string} interpolated path
*/
getPath(filename, data) {
data = data || {};
data.hash = data.hash || this.hash;
return this.mainTemplate.getAssetPath(filename, data);
}

View File

@ -305,7 +305,7 @@ class Compiler {
this.hooks.emit.callAsync(compilation, err => {
if (err) return callback(err);
outputPath = compilation.getPath(this.outputPath);
outputPath = compilation.getPath(this.outputPath, {});
this.outputFileSystem.mkdirp(outputPath, emitFiles);
});
}

View File

@ -212,7 +212,9 @@ module.exports = class HotModuleReplacementPlugin {
records.moduleHashs = {};
for (const module of compilation.modules) {
const identifier = module.identifier();
records.moduleHashs[identifier] = module.hash;
records.moduleHashs[identifier] = chunkGraph.getModuleHash(
module
);
}
records.chunkHashs = {};
for (const chunk of compilation.chunks) {
@ -278,7 +280,7 @@ module.exports = class HotModuleReplacementPlugin {
const updatedModules = new Set();
for (const module of compilation.modules) {
const identifier = module.identifier();
const hash = module.hash;
const hash = chunkGraph.getModuleHash(module);
if (records.moduleHashs[identifier] !== hash) {
updatedModules.add(module);
}

View File

@ -198,7 +198,7 @@ class JavascriptModulesPlugin {
compareModulesById(moduleGraph)
)) {
if (typeof m.source === "function") {
hash.update(m.hash);
hash.update(chunkGraph.getModuleHash(m));
}
}
chunk.contentHash.javascript = hash

View File

@ -10,11 +10,17 @@ const path = require("path");
const EntryDependency = require("./dependencies/EntryDependency");
const { compareModulesById } = require("./util/comparators");
/** @typedef {import("./Compiler")} Compiler */
class LibManifestPlugin {
constructor(options) {
this.options = options;
}
/**
* @param {Compiler} compiler webpack compiler
* @returns {void}
*/
apply(compiler) {
compiler.hooks.emit.tapAsync(
"LibManifestPlugin",

View File

@ -78,12 +78,6 @@ class Module extends DependenciesBlock {
/** @type {number} */
this.debugId = debugId++;
// Hash
/** @type {string} */
this.hash = undefined;
/** @type {string} */
this.renderedHash = undefined;
// Info from Factory
/** @type {TODO} */
this.resolveOptions = EMPTY_RESOLVE_OPTIONS;
@ -110,6 +104,25 @@ class Module extends DependenciesBlock {
// TODO remove in webpack 6
// BACKWARD-COMPAT START
/**
* @returns {string} the hash of the module
*/
get hash() {
return ChunkGraph.getChunkGraphForModule(this, "Module.hash").getModuleHash(
this
);
}
/**
* @returns {string} the shortened hash of the module
*/
get renderedHash() {
return ChunkGraph.getChunkGraphForModule(
this,
"Module.renderedHash"
).getRenderedModuleHash(this);
}
get profile() {
return ModuleGraph.getModuleGraphForModule(
this,
@ -276,9 +289,6 @@ class Module extends DependenciesBlock {
* @returns {void}
*/
disconnect() {
this.hash = undefined;
this.renderedHash = undefined;
this.id = null;
super.disconnect();

View File

@ -24,6 +24,7 @@ const createHash = require("./util/createHash");
const contextify = require("./util/identifier").contextify;
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
/** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */
@ -494,13 +495,14 @@ class NormalModule extends Module {
}
/**
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {DependencyTemplates} dependencyTemplates dependency templates
* @returns {string} hash
*/
getHashDigest(dependencyTemplates) {
// TODO webpack 5 refactor
let dtHash = dependencyTemplates.getHash();
return `${this.hash}-${dtHash}`;
getHashDigest(chunkGraph, dependencyTemplates) {
const hash = chunkGraph.getModuleHash(this);
const dtHash = dependencyTemplates.getHash();
return `${hash}-${dtHash}`;
}
/**
@ -511,9 +513,10 @@ class NormalModule extends Module {
dependencyTemplates,
runtimeTemplate,
moduleGraph,
chunkGraph,
type = "javascript"
}) {
const hashDigest = this.getHashDigest(dependencyTemplates);
const hashDigest = this.getHashDigest(chunkGraph, dependencyTemplates);
const cacheEntry = this._cachedSources.get(type);
if (cacheEntry !== undefined && cacheEntry.hash === hashDigest) {
// We can reuse the cached source

View File

@ -6,14 +6,17 @@
"use strict";
const path = require("path");
const validateOptions = require("schema-utils");
const { ConcatSource, RawSource } = require("webpack-sources");
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin");
const createHash = require("./util/createHash");
const validateOptions = require("schema-utils");
const schema = require("../schemas/plugins/SourceMapDevToolPlugin.json");
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./Compiler")} Compiler */
const assetsCache = new WeakMap();
const getTaskForFile = (file, chunk, options, compilation) => {
@ -65,6 +68,10 @@ class SourceMapDevToolPlugin {
this.options = options;
}
/**
* @param {Compiler} compiler webpack compiler
* @returns {void}
*/
apply(compiler) {
const sourceMapFilename = this.sourceMapFilename;
const sourceMappingURLComment = this.sourceMappingURLComment;
@ -84,11 +91,13 @@ class SourceMapDevToolPlugin {
new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation);
compilation.hooks.afterOptimizeChunkAssets.tap(
{
/** @type {TODO} */ ({
name: "SourceMapDevToolPlugin",
context: true
},
(context, chunks) => {
}),
/** @type {TODO} */
/** @param {any} context @param {Chunk[]} chunks @returns {void} */
((context, chunks) => {
const moduleToSourceNameMapping = new Map();
const reportProgress =
context && context.reportProgress
@ -281,7 +290,7 @@ class SourceMapDevToolPlugin {
}
});
reportProgress(1.0);
}
})
);
});
}

View File

@ -12,6 +12,7 @@ const HotUpdateChunk = require("./HotUpdateChunk");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation").PathData} PathData */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./ModuleGraph")} ModuleGraph */
@ -48,7 +49,7 @@ const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g;
* @typedef {Object} RenderManifestEntry
* @property {function(): Source} render
* @property {string=} filenameTemplate
* @property {TODO=} pathOptions
* @property {PathData=} pathOptions
* @property {TODO} identifier
* @property {TODO=} hash
*/

View File

@ -5,6 +5,10 @@
"use strict";
const Module = require("./Module");
/** @typedef {import("./Compilation").PathData} PathData */
const REGEXP_HASH = /\[hash(?::(\d+))?\]/gi,
REGEXP_CHUNKHASH = /\[chunkhash(?::(\d+))?\]/gi,
REGEXP_MODULEHASH = /\[modulehash(?::(\d+))?\]/gi,
@ -53,25 +57,40 @@ const getReplacer = (value, allowEmpty) => {
return fn;
};
/**
* @param {string | function(PathData): string} path the raw path
* @param {PathData} data context data
* @returns {string} the interpolated path
*/
const replacePathVariables = (path, data) => {
const chunkGraph = data.chunkGraph;
const chunk = data.chunk;
const chunkId = chunk && chunk.id;
const chunkName = chunk && (chunk.name || chunk.id);
const chunkHash = chunk && (chunk.renderedHash || chunk.hash);
const chunkHashWithLength = chunk && chunk.hashWithLength;
const chunkHashWithLength =
chunk && "hashWithLength" in chunk && chunk.hashWithLength;
const contentHashType = data.contentHashType;
const contentHash =
(chunk && chunk.contentHash && chunk.contentHash[contentHashType]) ||
data.contentHash;
const contentHashWithLength =
data.contentHash ||
(chunk &&
chunk.contentHashWithLength &&
chunk.contentHashWithLength[contentHashType]) ||
data.contentHashWithLength;
contentHashType &&
chunk.contentHash &&
chunk.contentHash[contentHashType]);
const contentHashWithLength =
data.contentHashWithLength ||
(chunk && "contentHashWithLength" in chunk
? chunk.contentHashWithLength[contentHashType]
: undefined);
const module = data.module;
const moduleId = module && module.id;
const moduleHash = module && (module.renderedHash || module.hash);
const moduleHashWithLength = module && module.hashWithLength;
const moduleHash =
module &&
(module instanceof Module
? chunkGraph.getRenderedModuleHash(module)
: module.renderedHash || module.hash);
const moduleHashWithLength =
module && "hashWithLength" in module && module.hashWithLength;
if (typeof path === "function") {
path = path(data);

View File

@ -375,18 +375,14 @@ class WasmMainTemplatePlugin {
mainTemplate.hooks.hashForChunk.tap(
"WasmMainTemplatePlugin",
(hash, chunk) => {
const chunkModuleMaps = this.compilation.chunkGraph.getChunkModuleMaps(
chunk,
m => m.type.startsWith("webassembly")
const chunkGraph = this.compilation.chunkGraph;
const chunkModuleMaps = chunkGraph.getChunkModuleMaps(chunk, m =>
m.type.startsWith("webassembly")
);
hash.update(JSON.stringify(chunkModuleMaps.id));
const wasmModules = getAllWasmModules(
moduleGraph,
this.compilation.chunkGraph,
chunk
);
const wasmModules = getAllWasmModules(moduleGraph, chunkGraph, chunk);
for (const module of wasmModules) {
hash.update(module.hash);
hash.update(chunkGraph.getModuleHash(module));
}
}
);

View File

@ -92,15 +92,16 @@ class WebAssemblyModulesPlugin {
dependencyTemplates,
runtimeTemplate: compilation.runtimeTemplate,
moduleGraph,
chunkGraph: compilation.chunkGraph
chunkGraph
}
),
filenameTemplate,
pathOptions: {
chunkGraph,
module
},
identifier: `webassemblyModule${module.id}`,
hash: module.hash
hash: chunkGraph.getModuleHash(module)
});
}
}