@@ -14,7 +14,6 @@ const vm = require('vm');
14
14
const fs = require ( 'fs' ) ;
15
15
const _ = require ( 'lodash' ) ;
16
16
const path = require ( 'path' ) ;
17
- const loaderUtils = require ( 'loader-utils' ) ;
18
17
const { CachedChildCompilation } = require ( './lib/cached-child-compiler' ) ;
19
18
20
19
const { createHtmlTagObject, htmlTagObjectToString, HtmlTagArray } = require ( './lib/html-tags' ) ;
@@ -132,8 +131,7 @@ class HtmlWebpackPlugin {
132
131
...global ,
133
132
HTML_WEBPACK_PLUGIN : true ,
134
133
require : require ,
135
- htmlWebpackPluginPublicPath :
136
- publicPath ,
134
+ htmlWebpackPluginPublicPath : publicPath ,
137
135
URL : require ( 'url' ) . URL ,
138
136
__filename : templateWithoutLoaders
139
137
} ) ;
@@ -189,13 +187,6 @@ function hookIntoCompiler (compiler, options, plugin) {
189
187
options . filename = path . relative ( outputPath , filename ) ;
190
188
}
191
189
192
- // `contenthash` is introduced in webpack v4.3
193
- // which conflicts with the plugin's existing `contenthash` method,
194
- // hence it is renamed to `templatehash` to avoid conflicts
195
- options . filename = options . filename . replace ( / \[ (?: ( \w + ) : ) ? c o n t e n t h a s h (?: : ( [ a - z ] + \d * ) ) ? (?: : ( \d + ) ) ? \] / ig, ( match ) => {
196
- return match . replace ( 'contenthash' , 'templatehash' ) ;
197
- } ) ;
198
-
199
190
// Check if webpack is running in production mode
200
191
// @see https://github.com/webpack/webpack/blob/3366421f1784c449f415cda5930a8e445086f688/lib/WebpackOptionsDefaulter.js#L12-L14
201
192
const isProductionLikeMode = compiler . options . mode === 'production' || ! compiler . options . mode ;
@@ -249,21 +240,12 @@ function hookIntoCompiler (compiler, options, plugin) {
249
240
compilation . errors . push ( prettyError ( templateResult . error , compiler . context ) . toString ( ) ) ;
250
241
}
251
242
252
- const compiledEntries = 'compiledEntry' in templateResult ? {
253
- hash : templateResult . compiledEntry . hash ,
254
- chunk : templateResult . compiledEntry . entry
255
- } : {
256
- hash : templateResult . mainCompilationHash
257
- } ;
258
-
259
- const childCompilationOutputName = compilation . getAssetPath ( options . filename , compiledEntries ) ;
260
-
261
243
// If the child compilation was not executed during a previous main compile run
262
244
// it is a cached result
263
245
const isCompilationCached = templateResult . mainCompilationHash !== compilation . hash ;
264
246
265
247
/** The public path used inside the html file */
266
- const htmlPublicPath = getPublicPath ( compilation , childCompilationOutputName , options . publicPath ) ;
248
+ const htmlPublicPath = getPublicPath ( compilation , options . filename , options . publicPath ) ;
267
249
268
250
/** Generated file paths from the entry point names */
269
251
const assets = htmlWebpackPluginAssets ( compilation , sortedEntryNames , htmlPublicPath ) ;
@@ -288,7 +270,7 @@ function hookIntoCompiler (compiler, options, plugin) {
288
270
assets . favicon = faviconPath ;
289
271
return getHtmlWebpackPluginHooks ( compilation ) . beforeAssetTagGeneration . promise ( {
290
272
assets : assets ,
291
- outputName : childCompilationOutputName ,
273
+ outputName : options . filename ,
292
274
plugin : plugin
293
275
} ) ;
294
276
} ) ;
@@ -306,7 +288,7 @@ function hookIntoCompiler (compiler, options, plugin) {
306
288
...generateFaviconTags ( assets . favicon )
307
289
]
308
290
} ,
309
- outputName : childCompilationOutputName ,
291
+ outputName : options . filename ,
310
292
publicPath : htmlPublicPath ,
311
293
plugin : plugin
312
294
} ) )
@@ -320,7 +302,7 @@ function hookIntoCompiler (compiler, options, plugin) {
320
302
return getHtmlWebpackPluginHooks ( compilation ) . alterAssetTagGroups . promise ( {
321
303
headTags : assetGroups . headTags ,
322
304
bodyTags : assetGroups . bodyTags ,
323
- outputName : childCompilationOutputName ,
305
+ outputName : options . filename ,
324
306
publicPath : htmlPublicPath ,
325
307
plugin : plugin
326
308
} ) ;
@@ -351,7 +333,7 @@ function hookIntoCompiler (compiler, options, plugin) {
351
333
const injectedHtmlPromise = Promise . all ( [ assetTagGroupsPromise , templateExectutionPromise ] )
352
334
// Allow plugins to change the html before assets are injected
353
335
. then ( ( [ assetTags , html ] ) => {
354
- const pluginArgs = { html, headTags : assetTags . headTags , bodyTags : assetTags . bodyTags , plugin : plugin , outputName : childCompilationOutputName } ;
336
+ const pluginArgs = { html, headTags : assetTags . headTags , bodyTags : assetTags . bodyTags , plugin : plugin , outputName : options . filename } ;
355
337
return getHtmlWebpackPluginHooks ( compilation ) . afterTemplateExecution . promise ( pluginArgs ) ;
356
338
} )
357
339
. then ( ( { html, headTags, bodyTags } ) => {
@@ -361,7 +343,7 @@ function hookIntoCompiler (compiler, options, plugin) {
361
343
const emitHtmlPromise = injectedHtmlPromise
362
344
// Allow plugins to change the html after assets are injected
363
345
. then ( ( html ) => {
364
- const pluginArgs = { html, plugin : plugin , outputName : childCompilationOutputName } ;
346
+ const pluginArgs = { html, plugin : plugin , outputName : options . filename } ;
365
347
return getHtmlWebpackPluginHooks ( compilation ) . beforeEmit . promise ( pluginArgs )
366
348
. then ( result => result . html ) ;
367
349
} )
@@ -372,16 +354,15 @@ function hookIntoCompiler (compiler, options, plugin) {
372
354
return options . showErrors ? prettyError ( err , compiler . context ) . toHtml ( ) : 'ERROR' ;
373
355
} )
374
356
. then ( html => {
375
- // Allow to use [templatehash] as placeholder for the html-webpack-plugin name
376
- // See also https://survivejs.com/webpack/optimizing/adding-hashes-to-filenames/
377
- // From https://github.com/webpack-contrib/extract-text-webpack-plugin/blob/8de6558e33487e7606e7cd7cb2adc2cccafef272/src/index.js#L212-L214
378
- const finalOutputName = childCompilationOutputName . replace ( / \[ (?: ( \w + ) : ) ? t e m p l a t e h a s h (?: : ( [ a - z ] + \d * ) ) ? (?: : ( \d + ) ) ? \] / ig, ( _ , hashType , digestType , maxLength ) => {
379
- return loaderUtils . getHashDigest ( Buffer . from ( html , 'utf8' ) , hashType , digestType , parseInt ( maxLength , 10 ) ) ;
380
- } ) ;
357
+ const filename = options . filename . replace ( / \[ t e m p l a t e h a s h ( [ ^ \] ] * ) \] / g, require ( 'util' ) . deprecate (
358
+ ( match , options ) => `[contenthash${ options } ]` ,
359
+ '[templatehash] is now [contenthash]' )
360
+ ) ;
361
+ const replacedFilename = replacePlaceholdersInFilename ( filename , html , compilation ) ;
381
362
// Add the evaluated html code to the webpack assets
382
- compilation . emitAsset ( finalOutputName , new webpack . sources . RawSource ( html , false ) ) ;
383
- previousEmittedAssets . push ( { name : finalOutputName , html } ) ;
384
- return finalOutputName ;
363
+ compilation . emitAsset ( replacedFilename . path , new webpack . sources . RawSource ( html , false ) , replacedFilename . info ) ;
364
+ previousEmittedAssets . push ( { name : replacedFilename . path , html } ) ;
365
+ return replacedFilename . path ;
385
366
} )
386
367
. then ( ( finalOutputName ) => getHtmlWebpackPluginHooks ( compilation ) . afterEmit . promise ( {
387
368
outputName : finalOutputName ,
@@ -519,6 +500,38 @@ function hookIntoCompiler (compiler, options, plugin) {
519
500
} ) ;
520
501
}
521
502
503
+ /**
504
+ * Replace [contenthash] in filename
505
+ *
506
+ * @see https://survivejs.com/webpack/optimizing/adding-hashes-to-filenames/
507
+ *
508
+ * @param {string } filename
509
+ * @param {string|Buffer } fileContent
510
+ * @param {WebpackCompilation } compilation
511
+ * @returns {{ path: string, info: {} } }
512
+ */
513
+ function replacePlaceholdersInFilename ( filename , fileContent , compilation ) {
514
+ if ( / \[ \\ * ( [ \w : ] + ) \\ * \] / i. test ( filename ) === false ) {
515
+ return { path : filename , info : { } } ;
516
+ }
517
+ const hash = compiler . webpack . util . createHash ( compilation . outputOptions . hashFunction ) ;
518
+ hash . update ( fileContent ) ;
519
+ if ( compilation . outputOptions . hashSalt ) {
520
+ hash . update ( compilation . outputOptions . hashSalt ) ;
521
+ }
522
+ const contentHash = hash . digest ( compilation . outputOptions . hashDigest ) . slice ( 0 , compilation . outputOptions . hashDigestLength ) ;
523
+ return compilation . getPathWithInfo (
524
+ filename ,
525
+ {
526
+ contentHash,
527
+ chunk : {
528
+ hash : contentHash ,
529
+ contentHash
530
+ }
531
+ }
532
+ ) ;
533
+ }
534
+
522
535
/**
523
536
* Helper to sort chunks
524
537
* @param {string[] } entryNames
0 commit comments