1
1
// @ts -check
2
- // Import types
3
- /** @typedef {import("./typings").HtmlTagObject } HtmlTagObject */
4
- /** @typedef {import("./typings").Options } HtmlWebpackOptions */
5
- /** @typedef {import("./typings").ProcessedOptions } ProcessedHtmlWebpackOptions */
6
- /** @typedef {import("./typings").TemplateParameter } TemplateParameter */
7
- /** @typedef {import("webpack/lib/Compiler.js") } WebpackCompiler */
8
- /** @typedef {import("webpack/lib/Compilation.js") } WebpackCompilation */
9
2
'use strict' ;
10
3
11
4
const promisify = require ( 'util' ) . promisify ;
@@ -23,7 +16,13 @@ const chunkSorter = require('./lib/chunksorter.js');
23
16
const getHtmlWebpackPluginHooks = require ( './lib/hooks.js' ) . getHtmlWebpackPluginHooks ;
24
17
const { assert } = require ( 'console' ) ;
25
18
26
- const fsReadFileAsync = promisify ( fs . readFile ) ;
19
+ /** @typedef {import("./typings").HtmlTagObject } HtmlTagObject */
20
+ /** @typedef {import("./typings").Options } HtmlWebpackOptions */
21
+ /** @typedef {import("./typings").ProcessedOptions } ProcessedHtmlWebpackOptions */
22
+ /** @typedef {import("./typings").TemplateParameter } TemplateParameter */
23
+ /** @typedef {import("webpack/lib/Compiler.js") } WebpackCompiler */
24
+ /** @typedef {import("webpack/lib/Compilation.js") } WebpackCompilation */
25
+ /** @typedef {Array<{ source: import('webpack').sources.Source, name: string }> } PreviousEmittedAssets */
27
26
28
27
class HtmlWebpackPlugin {
29
28
/**
@@ -216,7 +215,7 @@ function hookIntoCompiler (compiler, options, plugin) {
216
215
/**
217
216
* store the previous generated asset to emit them even if the content did not change
218
217
* to support watch mode for third party plugins like the clean-webpack-plugin or the compression plugin
219
- * @type {Array<{html: string, name: string}> }
218
+ * @type {PreviousEmittedAssets }
220
219
*/
221
220
let previousEmittedAssets = [ ] ;
222
221
@@ -302,8 +301,8 @@ function hookIntoCompiler (compiler, options, plugin) {
302
301
// If the template and the assets did not change we don't have to emit the html
303
302
const newAssetJson = JSON . stringify ( getAssetFiles ( assets ) ) ;
304
303
if ( isCompilationCached && options . cache && assetJson === newAssetJson ) {
305
- previousEmittedAssets . forEach ( ( { name, html } ) => {
306
- compilation . emitAsset ( name , new webpack . sources . RawSource ( html , false ) ) ;
304
+ previousEmittedAssets . forEach ( ( { name, source } ) => {
305
+ compilation . emitAsset ( name , source ) ;
307
306
} ) ;
308
307
return callback ( ) ;
309
308
} else {
@@ -314,7 +313,7 @@ function hookIntoCompiler (compiler, options, plugin) {
314
313
// The html-webpack plugin uses a object representation for the html-tags which will be injected
315
314
// to allow altering them more easily
316
315
// Just before they are converted a third-party-plugin author might change the order and content
317
- const assetsPromise = getFaviconPublicPath ( options . favicon , compilation , assets . publicPath )
316
+ const assetsPromise = generateFavicon ( options . favicon , compilation , assets . publicPath , previousEmittedAssets )
318
317
. then ( ( faviconPath ) => {
319
318
assets . favicon = faviconPath ;
320
319
return getHtmlWebpackPluginHooks ( compilation ) . beforeAssetTagGeneration . promise ( {
@@ -408,9 +407,12 @@ function hookIntoCompiler (compiler, options, plugin) {
408
407
'[templatehash] is now [contenthash]' )
409
408
) ;
410
409
const replacedFilename = replacePlaceholdersInFilename ( filename , html , compilation ) ;
410
+ const source = new webpack . sources . RawSource ( html , false ) ;
411
+
411
412
// Add the evaluated html code to the webpack assets
412
- compilation . emitAsset ( replacedFilename . path , new webpack . sources . RawSource ( html , false ) , replacedFilename . info ) ;
413
- previousEmittedAssets . push ( { name : replacedFilename . path , html } ) ;
413
+ compilation . emitAsset ( replacedFilename . path , source , replacedFilename . info ) ;
414
+ previousEmittedAssets . push ( { name : replacedFilename . path , source } ) ;
415
+
414
416
return replacedFilename . path ;
415
417
} )
416
418
. then ( ( finalOutputName ) => getHtmlWebpackPluginHooks ( compilation ) . afterEmit . promise ( {
@@ -529,26 +531,6 @@ function hookIntoCompiler (compiler, options, plugin) {
529
531
return Promise . resolve ( htmlAfterMinification ) ;
530
532
}
531
533
532
- /*
533
- * Pushes the content of the given filename to the compilation assets
534
- * @param {string } filename
535
- * @param {WebpackCompilation } compilation
536
- *
537
- * @returns {string } file basename
538
- */
539
- function addFileToAssets ( filename , compilation ) {
540
- filename = path . resolve ( compilation . compiler . context , filename ) ;
541
- return fsReadFileAsync ( filename )
542
- . then ( source => new webpack . sources . RawSource ( source , false ) )
543
- . catch ( ( ) => Promise . reject ( new Error ( 'HtmlWebpackPlugin: could not load file ' + filename ) ) )
544
- . then ( rawSource => {
545
- const basename = path . basename ( filename ) ;
546
- compilation . fileDependencies . add ( filename ) ;
547
- compilation . emitAsset ( basename , rawSource ) ;
548
- return basename ;
549
- } ) ;
550
- }
551
-
552
534
/**
553
535
* Replace [contenthash] in filename
554
536
*
@@ -757,23 +739,37 @@ function hookIntoCompiler (compiler, options, plugin) {
757
739
* Converts a favicon file from disk to a webpack resource
758
740
* and returns the url to the resource
759
741
*
760
- * @param {string|false } faviconFilePath
742
+ * @param {string|false } favicon
761
743
* @param {WebpackCompilation } compilation
762
744
* @param {string } publicPath
745
+ * @param {PreviousEmittedAssets } previousEmittedAssets
763
746
* @returns {Promise<string|undefined> }
764
747
*/
765
- function getFaviconPublicPath ( faviconFilePath , compilation , publicPath ) {
766
- if ( ! faviconFilePath ) {
748
+ function generateFavicon ( favicon , compilation , publicPath , previousEmittedAssets ) {
749
+ if ( ! favicon ) {
767
750
return Promise . resolve ( undefined ) ;
768
751
}
769
- return addFileToAssets ( faviconFilePath , compilation )
770
- . then ( ( faviconName ) => {
771
- const faviconPath = publicPath + faviconName ;
752
+
753
+ const filename = path . resolve ( compilation . compiler . context , favicon ) ;
754
+
755
+ return promisify ( compilation . inputFileSystem . readFile ) ( filename )
756
+ . then ( ( buf ) => {
757
+ const source = new webpack . sources . RawSource ( buf , false ) ;
758
+ const name = path . basename ( filename ) ;
759
+
760
+ compilation . fileDependencies . add ( filename ) ;
761
+ compilation . emitAsset ( name , source ) ;
762
+ previousEmittedAssets . push ( { name, source } ) ;
763
+
764
+ const faviconPath = publicPath + name ;
765
+
772
766
if ( options . hash ) {
773
767
return appendHash ( faviconPath , compilation . hash ) ;
774
768
}
769
+
775
770
return faviconPath ;
776
- } ) ;
771
+ } )
772
+ . catch ( ( ) => Promise . reject ( new Error ( 'HtmlWebpackPlugin: could not load file ' + filename ) ) ) ;
777
773
}
778
774
779
775
/**
0 commit comments