diff --git a/README.md b/README.md
index 9f5b7d7a..02d46c71 100644
--- a/README.md
+++ b/README.md
@@ -464,7 +464,7 @@ which will inject the element `:contenthash::]`
-
-* `hashType` - one of `sha1`, `md5`, `sha256`, `sha512` or any other node.js supported hash type
-* `digestType` - one of `hex`, `base26`, `base32`, `base36`, `base49`, `base52`, `base58`, `base62`, `base64`
-* `maxlength` - maximum length of the generated hash in chars
-
-**Defaults:** `[md5:contenthash:hex:9999]`
+Refer webpack's [Template Strings](https://webpack.js.org/configuration/output/#template-strings) for more details
### Events
diff --git a/index.js b/index.js
index eb74aeb1..45f286ad 100644
--- a/index.js
+++ b/index.js
@@ -14,7 +14,6 @@ const vm = require('vm');
const fs = require('fs');
const _ = require('lodash');
const path = require('path');
-const loaderUtils = require('loader-utils');
const { CachedChildCompilation } = require('./lib/cached-child-compiler');
const { createHtmlTagObject, htmlTagObjectToString, HtmlTagArray } = require('./lib/html-tags');
@@ -132,8 +131,7 @@ class HtmlWebpackPlugin {
...global,
HTML_WEBPACK_PLUGIN: true,
require: require,
- htmlWebpackPluginPublicPath:
- publicPath,
+ htmlWebpackPluginPublicPath: publicPath,
URL: require('url').URL,
__filename: templateWithoutLoaders
});
@@ -189,13 +187,6 @@ function hookIntoCompiler (compiler, options, plugin) {
options.filename = path.relative(outputPath, filename);
}
- // `contenthash` is introduced in webpack v4.3
- // which conflicts with the plugin's existing `contenthash` method,
- // hence it is renamed to `templatehash` to avoid conflicts
- options.filename = options.filename.replace(/\[(?:(\w+):)?contenthash(?::([a-z]+\d*))?(?::(\d+))?\]/ig, (match) => {
- return match.replace('contenthash', 'templatehash');
- });
-
// Check if webpack is running in production mode
// @see https://github.com/webpack/webpack/blob/3366421f1784c449f415cda5930a8e445086f688/lib/WebpackOptionsDefaulter.js#L12-L14
const isProductionLikeMode = compiler.options.mode === 'production' || !compiler.options.mode;
@@ -249,21 +240,12 @@ function hookIntoCompiler (compiler, options, plugin) {
compilation.errors.push(prettyError(templateResult.error, compiler.context).toString());
}
- const compiledEntries = 'compiledEntry' in templateResult ? {
- hash: templateResult.compiledEntry.hash,
- chunk: templateResult.compiledEntry.entry
- } : {
- hash: templateResult.mainCompilationHash
- };
-
- const childCompilationOutputName = compilation.getAssetPath(options.filename, compiledEntries);
-
// If the child compilation was not executed during a previous main compile run
// it is a cached result
const isCompilationCached = templateResult.mainCompilationHash !== compilation.hash;
/** The public path used inside the html file */
- const htmlPublicPath = getPublicPath(compilation, childCompilationOutputName, options.publicPath);
+ const htmlPublicPath = getPublicPath(compilation, options.filename, options.publicPath);
/** Generated file paths from the entry point names */
const assets = htmlWebpackPluginAssets(compilation, sortedEntryNames, htmlPublicPath);
@@ -288,7 +270,7 @@ function hookIntoCompiler (compiler, options, plugin) {
assets.favicon = faviconPath;
return getHtmlWebpackPluginHooks(compilation).beforeAssetTagGeneration.promise({
assets: assets,
- outputName: childCompilationOutputName,
+ outputName: options.filename,
plugin: plugin
});
});
@@ -306,7 +288,7 @@ function hookIntoCompiler (compiler, options, plugin) {
...generateFaviconTags(assets.favicon)
]
},
- outputName: childCompilationOutputName,
+ outputName: options.filename,
publicPath: htmlPublicPath,
plugin: plugin
}))
@@ -320,7 +302,7 @@ function hookIntoCompiler (compiler, options, plugin) {
return getHtmlWebpackPluginHooks(compilation).alterAssetTagGroups.promise({
headTags: assetGroups.headTags,
bodyTags: assetGroups.bodyTags,
- outputName: childCompilationOutputName,
+ outputName: options.filename,
publicPath: htmlPublicPath,
plugin: plugin
});
@@ -351,7 +333,7 @@ function hookIntoCompiler (compiler, options, plugin) {
const injectedHtmlPromise = Promise.all([assetTagGroupsPromise, templateExectutionPromise])
// Allow plugins to change the html before assets are injected
.then(([assetTags, html]) => {
- const pluginArgs = { html, headTags: assetTags.headTags, bodyTags: assetTags.bodyTags, plugin: plugin, outputName: childCompilationOutputName };
+ const pluginArgs = { html, headTags: assetTags.headTags, bodyTags: assetTags.bodyTags, plugin: plugin, outputName: options.filename };
return getHtmlWebpackPluginHooks(compilation).afterTemplateExecution.promise(pluginArgs);
})
.then(({ html, headTags, bodyTags }) => {
@@ -361,7 +343,7 @@ function hookIntoCompiler (compiler, options, plugin) {
const emitHtmlPromise = injectedHtmlPromise
// Allow plugins to change the html after assets are injected
.then((html) => {
- const pluginArgs = { html, plugin: plugin, outputName: childCompilationOutputName };
+ const pluginArgs = { html, plugin: plugin, outputName: options.filename };
return getHtmlWebpackPluginHooks(compilation).beforeEmit.promise(pluginArgs)
.then(result => result.html);
})
@@ -372,16 +354,15 @@ function hookIntoCompiler (compiler, options, plugin) {
return options.showErrors ? prettyError(err, compiler.context).toHtml() : 'ERROR';
})
.then(html => {
- // Allow to use [templatehash] as placeholder for the html-webpack-plugin name
- // See also https://survivejs.com/webpack/optimizing/adding-hashes-to-filenames/
- // From https://github.com/webpack-contrib/extract-text-webpack-plugin/blob/8de6558e33487e7606e7cd7cb2adc2cccafef272/src/index.js#L212-L214
- const finalOutputName = childCompilationOutputName.replace(/\[(?:(\w+):)?templatehash(?::([a-z]+\d*))?(?::(\d+))?\]/ig, (_, hashType, digestType, maxLength) => {
- return loaderUtils.getHashDigest(Buffer.from(html, 'utf8'), hashType, digestType, parseInt(maxLength, 10));
- });
+ const filename = options.filename.replace(/\[templatehash([^\]]*)\]/g, require('util').deprecate(
+ (match, options) => `[contenthash${options}]`,
+ '[templatehash] is now [contenthash]')
+ );
+ const replacedFilename = replacePlaceholdersInFilename(filename, html, compilation);
// Add the evaluated html code to the webpack assets
- compilation.emitAsset(finalOutputName, new webpack.sources.RawSource(html, false));
- previousEmittedAssets.push({ name: finalOutputName, html });
- return finalOutputName;
+ compilation.emitAsset(replacedFilename.path, new webpack.sources.RawSource(html, false), replacedFilename.info);
+ previousEmittedAssets.push({ name: replacedFilename.path, html });
+ return replacedFilename.path;
})
.then((finalOutputName) => getHtmlWebpackPluginHooks(compilation).afterEmit.promise({
outputName: finalOutputName,
@@ -519,6 +500,38 @@ function hookIntoCompiler (compiler, options, plugin) {
});
}
+ /**
+ * Replace [contenthash] in filename
+ *
+ * @see https://survivejs.com/webpack/optimizing/adding-hashes-to-filenames/
+ *
+ * @param {string} filename
+ * @param {string|Buffer} fileContent
+ * @param {WebpackCompilation} compilation
+ * @returns {{ path: string, info: {} }}
+ */
+ function replacePlaceholdersInFilename (filename, fileContent, compilation) {
+ if (/\[\\*([\w:]+)\\*\]/i.test(filename) === false) {
+ return { path: filename, info: {} };
+ }
+ const hash = compiler.webpack.util.createHash(compilation.outputOptions.hashFunction);
+ hash.update(fileContent);
+ if (compilation.outputOptions.hashSalt) {
+ hash.update(compilation.outputOptions.hashSalt);
+ }
+ const contentHash = hash.digest(compilation.outputOptions.hashDigest).slice(0, compilation.outputOptions.hashDigestLength);
+ return compilation.getPathWithInfo(
+ filename,
+ {
+ contentHash,
+ chunk: {
+ hash: contentHash,
+ contentHash
+ }
+ }
+ );
+ }
+
/**
* Helper to sort chunks
* @param {string[]} entryNames
diff --git a/package.json b/package.json
index c814d399..d8855a78 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,6 @@
]
},
"devDependencies": {
- "@types/loader-utils": "2.0.1",
"@types/node": "11.13.9",
"commitizen": "4.2.1",
"css-loader": "5.0.1",
@@ -45,9 +44,9 @@
"standard-version": "9.1.0",
"style-loader": "2.0.0",
"typescript": "4.1.3",
- "webpack": "5.23.0",
+ "webpack": "5.24.3",
"webpack-recompilation-simulator": "3.2.0",
- "webpack-cli": "4.2.0"
+ "webpack-cli": "4.5.0"
},
"dependencies": {
"@types/html-minifier-terser": "^5.0.0",
diff --git a/spec/basic.spec.js b/spec/basic.spec.js
index 572d7740..794e14c6 100644
--- a/spec/basic.spec.js
+++ b/spec/basic.spec.js
@@ -951,7 +951,24 @@ describe('HtmlWebpackPlugin', () => {
}, ['