Skip to content

Commit 82b34a1

Browse files
authoredJul 8, 2018
feat(hooks): Provide static getHook method for access to all html-webpack-plugin hooks (#995)
BREAKING CHANGE: The html-webpack-plugin doesn't add its hooks to the compilation object anymore
1 parent bbc07a3 commit 82b34a1

File tree

6 files changed

+43
-56
lines changed

6 files changed

+43
-56
lines changed
 

‎README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,7 @@ function MyPlugin(options) {
308308
MyPlugin.prototype.apply = function (compiler) {
309309
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
310310
console.log('The compiler is starting a new compilation...');
311-
312-
compilation.hooks.htmlWebpackPluginAfterHtmlProcessing.tapAsync(
311+
HtmlWebpackPlugin.getHooks(compilation).htmlWebpackPluginAfterHtmlProcessing.tapAsync(
313312
'MyPlugin',
314313
(data, cb) => {
315314
data.html += 'The Magic Footer'

‎index.js

+21-11
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,13 @@ const childCompiler = require('./lib/compiler.js');
2121
const prettyError = require('./lib/errors.js');
2222
const chunkSorter = require('./lib/chunksorter.js');
2323
const getHtmlWebpackPluginHooks = require('./lib/hooks.js').getHtmlWebpackPluginHooks;
24-
const getHtmlWebpackPluginHook = require('./lib/hooks.js').getHtmlWebpackPluginHook;
2524

2625
const fsStatAsync = promisify(fs.stat);
2726
const fsReadFileAsync = promisify(fs.readFile);
2827

2928
class HtmlWebpackPlugin {
3029
/**
31-
* @param {Partial<HtmlWebpackPluginOptions>} options
30+
* @param {Partial<HtmlWebpackPluginOptions>} [options]
3231
*/
3332
constructor (options) {
3433
// Default options
@@ -60,10 +59,7 @@ class HtmlWebpackPlugin {
6059
this.childCompilationOutputName = undefined;
6160
this.assetJson = undefined;
6261
this.hash = undefined;
63-
/**
64-
* The major version number of this plugin
65-
*/
66-
this.version = 4;
62+
this.version = HtmlWebpackPlugin.version;
6763
}
6864

6965
/**
@@ -173,7 +169,7 @@ class HtmlWebpackPlugin {
173169
})
174170
// Allow plugins to make changes to the assets before invoking the template
175171
// This only makes sense to use if `inject` is `false`
176-
.then(compilationResult => getHtmlWebpackPluginHook(compilation, 'htmlWebpackPluginBeforeHtmlGeneration').promise({
172+
.then(compilationResult => getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginBeforeHtmlGeneration.promise({
177173
assets: assets,
178174
outputName: self.childCompilationOutputName,
179175
plugin: self
@@ -186,7 +182,7 @@ class HtmlWebpackPlugin {
186182
// Allow plugins to change the html before assets are injected
187183
.then(html => {
188184
const pluginArgs = {html: html, assets: assets, plugin: self, outputName: self.childCompilationOutputName};
189-
return getHtmlWebpackPluginHook(compilation, 'htmlWebpackPluginBeforeHtmlProcessing').promise(pluginArgs);
185+
return getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginBeforeHtmlProcessing.promise(pluginArgs);
190186
})
191187
.then(result => {
192188
const html = result.html;
@@ -195,7 +191,7 @@ class HtmlWebpackPlugin {
195191
const assetTags = self.generateHtmlTagObjects(assets);
196192
const pluginArgs = {head: assetTags.head, body: assetTags.body, plugin: self, outputName: self.childCompilationOutputName};
197193
// Allow plugins to change the assetTag definitions
198-
return getHtmlWebpackPluginHook(compilation, 'htmlWebpackPluginAlterAssetTags').promise(pluginArgs)
194+
return getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginAlterAssetTags.promise(pluginArgs)
199195
.then(result => self.postProcessHtml(html, assets, { body: result.body, head: result.head })
200196
.then(html => _.extend(result, {html: html, assets: assets})));
201197
})
@@ -204,7 +200,7 @@ class HtmlWebpackPlugin {
204200
const html = result.html;
205201
const assets = result.assets;
206202
const pluginArgs = {html: html, assets: assets, plugin: self, outputName: self.childCompilationOutputName};
207-
return getHtmlWebpackPluginHook(compilation, 'htmlWebpackPluginAfterHtmlProcessing').promise(pluginArgs)
203+
return getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginAfterHtmlProcessing.promise(pluginArgs)
208204
.then(result => result.html);
209205
})
210206
.catch(err => {
@@ -222,7 +218,7 @@ class HtmlWebpackPlugin {
222218
size: () => html.length
223219
};
224220
})
225-
.then(() => getHtmlWebpackPluginHook(compilation, 'htmlWebpackPluginAfterEmit').promise({
221+
.then(() => getHtmlWebpackPluginHooks(compilation).htmlWebpackPluginAfterEmit.promise({
226222
html: compilation.assets[self.childCompilationOutputName],
227223
outputName: self.childCompilationOutputName,
228224
plugin: self
@@ -697,4 +693,18 @@ function templateParametersGenerator (compilation, assets, options) {
697693
}
698694
};
699695
}
696+
697+
// Statics:
698+
/**
699+
* The major version number of this plugin
700+
*/
701+
HtmlWebpackPlugin.version = 4;
702+
703+
/**
704+
* A static helper to get the hooks for this plugin
705+
*
706+
* Usage: HtmlWebpackPlugin.getHook(compilation, 'HookName').tap('YourPluginName', () => { ... });
707+
*/
708+
HtmlWebpackPlugin.getHooks = getHtmlWebpackPluginHooks;
709+
700710
module.exports = HtmlWebpackPlugin;

‎lib/compiler.js

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
2222
* for multile HtmlWebpackPlugin instances to improve the compilation performance.
2323
*/
2424
class HtmlWebpackChildCompiler {
25-
2625
constructor () {
2726
/**
2827
* @type {string[]} templateIds

‎lib/hooks.js

+19-40
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,6 @@
55
'use strict';
66
/**
77
* This file provides access to all public htmlWebpackPlugin hooks
8-
*
9-
* Usage:
10-
* ```js
11-
* const getHtmlWebpackPluginHooks = require('html-webpack-plugin/lib/hooks').getHtmlWebpackPluginHooks;
12-
*
13-
* compiler.hooks.compilation.tap('YOUR_PLUGIN_NAME', (compilation) => {
14-
* const htmlWebpackPluginHooks = getHtmlWebpackPluginHooks(compilation);
15-
* htmlWebpackPluginHooks.htmlWebpackPluginAfterEmit.tap('YOUR_PLUGIN_NAME', (pluginArgs) => {
16-
* // your code
17-
* });
18-
* });
19-
* ```
208
*/
219

2210
/** @typedef {import("webpack/lib/Compilation.js")} WebpackCompilation */
@@ -75,18 +63,23 @@ const AsyncSeriesWaterfallHook = require('tapable').AsyncSeriesWaterfallHook;
7563
}} HtmlWebpackPluginHooks
7664
*/
7765

66+
/**
67+
* @type {WeakMap<WebpackCompilation, HtmlWebpackPluginHooks>}}
68+
*/
69+
const htmlWebpackPluginHooksMap = new WeakMap();
70+
7871
/**
7972
* Returns all public hooks of the html webpack plugin for the given compilation
8073
*
8174
* @param {WebpackCompilation} compilation
8275
* @returns {HtmlWebpackPluginHooks}
8376
*/
8477
function getHtmlWebpackPluginHooks (compilation) {
85-
/** @type {HtmlWebpackPluginHooks} */
86-
const hooks = compilation.hooks;
78+
let hooks = htmlWebpackPluginHooksMap.get(compilation);
8779
// Setup the hooks only once
88-
if (!hooks.htmlWebpackPluginAfterEmit) {
89-
attachHooksToCompilation(compilation);
80+
if (hooks === undefined) {
81+
hooks = createHtmlWebpackPluginHooks();
82+
htmlWebpackPluginHooksMap.set(compilation, hooks);
9083
}
9184
return {
9285
htmlWebpackPluginBeforeHtmlGeneration: hooks.htmlWebpackPluginBeforeHtmlGeneration,
@@ -101,32 +94,18 @@ function getHtmlWebpackPluginHooks (compilation) {
10194
* Add hooks to the webpack compilation object to allow foreign plugins to
10295
* extend the HtmlWebpackPlugin
10396
*
104-
* @param {WebpackCompilation} compilation
97+
* @returns {HtmlWebpackPluginHooks}
10598
*/
106-
function attachHooksToCompilation (compilation) {
107-
/** @type {HtmlWebpackPluginHooks} */
108-
const hooks = compilation.hooks;
109-
hooks.htmlWebpackPluginBeforeHtmlGeneration = new AsyncSeriesWaterfallHook(['pluginArgs']);
110-
hooks.htmlWebpackPluginBeforeHtmlProcessing = new AsyncSeriesWaterfallHook(['pluginArgs']);
111-
hooks.htmlWebpackPluginAlterAssetTags = new AsyncSeriesWaterfallHook(['pluginArgs']);
112-
hooks.htmlWebpackPluginAfterHtmlProcessing = new AsyncSeriesWaterfallHook(['pluginArgs']);
113-
hooks.htmlWebpackPluginAfterEmit = new AsyncSeriesWaterfallHook(['pluginArgs']);
99+
function createHtmlWebpackPluginHooks () {
100+
return {
101+
htmlWebpackPluginBeforeHtmlGeneration: new AsyncSeriesWaterfallHook(['pluginArgs']),
102+
htmlWebpackPluginBeforeHtmlProcessing: new AsyncSeriesWaterfallHook(['pluginArgs']),
103+
htmlWebpackPluginAlterAssetTags: new AsyncSeriesWaterfallHook(['pluginArgs']),
104+
htmlWebpackPluginAfterHtmlProcessing: new AsyncSeriesWaterfallHook(['pluginArgs']),
105+
htmlWebpackPluginAfterEmit: new AsyncSeriesWaterfallHook(['pluginArgs'])
106+
};
114107
}
115108

116-
/**
117-
* Small workaround helper to work around https://github.com/Microsoft/TypeScript/issues/1178
118-
* Returns the hook of the given name
119-
*
120-
* @type {
121-
<T extends keyof HtmlWebpackPluginHooks>(compilation: WebpackCompilation, hookName: T) => HtmlWebpackPluginHooks[T]
122-
}
123-
*/
124-
const getHtmlWebpackPluginHook = (compilation, hookName) => {
125-
const hooks = getHtmlWebpackPluginHooks(compilation);
126-
return /** @type {any} */hooks[hookName];
127-
};
128-
129109
module.exports = {
130-
getHtmlWebpackPluginHooks,
131-
getHtmlWebpackPluginHook
110+
getHtmlWebpackPluginHooks
132111
};

‎spec/BasicSpec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ function getChunksInfoFromStats (stats) {
136136
function tapCompilationEvent (compilation, eventName, handler) {
137137
// Webpack 4 has a new interface
138138
if (compilation.hooks) {
139-
return compilation.hooks[trainCaseToCamelCase(eventName)].tapAsync(
139+
return HtmlWebpackPlugin.getHooks(compilation)[trainCaseToCamelCase(eventName)].tapAsync(
140140
'AsyncPlugin' + tapCompilationEvent.counter++,
141141
handler
142142
);

‎spec/ExampleSpec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* and matches them against their dist folder
44
*/
55

6-
/* eslint-env jasmine */
6+
/* eslint-env jasmine */
77
'use strict';
88

99
var path = require('path');

0 commit comments

Comments
 (0)
Please sign in to comment.