html-webpack-plugin 5.0.0 → 5.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,35 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [5.3.1](https://github.com/jantimon/html-webpack-plugin/compare/v5.3.0...v5.3.1) (2021-03-09)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * remove loader-utils from plugin core ([82d0ee8](https://github.com/jantimon/html-webpack-plugin/commit/82d0ee8ddf146f17d71e98c1b44b2f2ec7420051))
11
+
12
+ ## [5.3.0](https://github.com/jantimon/html-webpack-plugin/compare/v5.2.0...v5.3.0) (2021-03-07)
13
+
14
+
15
+ ### Features
16
+
17
+ * allow to modify the interpolation options in webpack config ([d654f5b](https://github.com/jantimon/html-webpack-plugin/commit/d654f5b90022304335b372d424ff4c08d3a9d341))
18
+ * drop loader-utils dependency ([41d7a50](https://github.com/jantimon/html-webpack-plugin/commit/41d7a50516aefd1af2704e3837d5d41351c6199b))
19
+
20
+ ## [5.2.0](https://github.com/jantimon/html-webpack-plugin/compare/v5.1.0...v5.2.0) (2021-02-19)
21
+
22
+
23
+ ### Features
24
+
25
+ * improve ssr ([73d2a66](https://github.com/jantimon/html-webpack-plugin/commit/73d2a660b10b9ebf8a341f0ddb173bcaaf1e513c))
26
+
27
+ ## [5.1.0](https://github.com/jantimon/html-webpack-plugin/compare/v5.0.0...v5.1.0) (2021-02-12)
28
+
29
+
30
+ ### Features
31
+
32
+ * omit html tag attribute with null/undefined/false value ([aa6e78d](https://github.com/jantimon/html-webpack-plugin/commit/aa6e78d1430c17d9cf05550b2c9f73a9a0c0166c)), closes [#1598](https://github.com/jantimon/html-webpack-plugin/issues/1598)
33
+
5
34
  ## [5.0.0](https://github.com/jantimon/html-webpack-plugin/compare/v4.5.1...v5.0.0) (2021-02-03)
6
35
 
7
36
 
package/README.md CHANGED
@@ -150,7 +150,7 @@ Allowed values are as follows:
150
150
  |**`templateParameters`**|`{Boolean\|Object\|Function}`| `false`| Allows to overwrite the parameters used in the template - see [example](https://github.com/jantimon/html-webpack-plugin/tree/master/examples/template-parameters) |
151
151
  |**`inject`**|`{Boolean\|String}`|`true`|`true \|\| 'head' \|\| 'body' \|\| false` Inject all assets into the given `template` or `templateContent`. When passing `'body'` all javascript resources will be placed at the bottom of the body element. `'head'` will place the scripts in the head element. Passing `true` will add it to the head/body depending on the `scriptLoading` option. Passing `false` will disable automatic injections. - see the [inject:false example](https://github.com/jantimon/html-webpack-plugin/tree/master/examples/custom-insertion-position)|
152
152
  |**`publicPath`**|`{String\|'auto'}`|`'auto'`|The publicPath used for script and link tags|
153
- |**`scriptLoading`**|`{'blocking'\|'defer'}`|`'blocking'`| Modern browsers support non blocking javascript loading (`'defer'`) to improve the page startup performance. |
153
+ |**`scriptLoading`**|`{'blocking'\|'defer'}`|`'defer'`| Modern browsers support non blocking javascript loading (`'defer'`) to improve the page startup performance. |
154
154
  |**`favicon`**|`{String}`|``|Adds the given favicon path to the output HTML|
155
155
  |**`meta`**|`{Object}`|`{}`|Allows to inject `meta`-tags. E.g. `meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}`|
156
156
  |**`base`**|`{Object\|String\|false}`|`false`|Inject a [`base`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) tag. E.g. `base: "https://example.com/path/page.html`|
@@ -464,7 +464,7 @@ which will inject the element `<base href="http://example.com/some/page.html" ta
464
464
 
465
465
  ### Long Term Caching
466
466
 
467
- For long term caching add `contenthash/templatehash` to the filename.
467
+ For long term caching add `contenthash` to the filename.
468
468
 
469
469
  **Example:**
470
470
 
@@ -476,15 +476,9 @@ plugins: [
476
476
  ]
477
477
  ```
478
478
 
479
- `contenthash/templatehash` is the hash of the content of the output file.
479
+ `contenthash` is the hash of the content of the output file.
480
480
 
481
- Optionally, You can configure like `[<hashType>:contenthash:<digestType>:<length>]`
482
-
483
- * `hashType` - one of `sha1`, `md5`, `sha256`, `sha512` or any other node.js supported hash type
484
- * `digestType` - one of `hex`, `base26`, `base32`, `base36`, `base49`, `base52`, `base58`, `base62`, `base64`
485
- * `maxlength` - maximum length of the generated hash in chars
486
-
487
- **Defaults:** `[md5:contenthash:hex:9999]`
481
+ Refer webpack's [Template Strings](https://webpack.js.org/configuration/output/#template-strings) for more details
488
482
 
489
483
  ### Events
490
484
 
package/index.js CHANGED
@@ -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');
@@ -123,12 +122,19 @@ class HtmlWebpackPlugin {
123
122
  return Promise.reject(new Error('The child compilation didn\'t provide a result'));
124
123
  }
125
124
  // The LibraryTemplatePlugin stores the template result in a local variable.
126
- // To extract the result during the evaluation this part has to be removed.
127
- if (source && source.indexOf('HTML_WEBPACK_PLUGIN_RESULT') >= 0) {
125
+ // By adding it to the end the value gets extracted during evaluation
126
+ if (source.indexOf('HTML_WEBPACK_PLUGIN_RESULT') >= 0) {
128
127
  source += ';\nHTML_WEBPACK_PLUGIN_RESULT';
129
128
  }
130
129
  const templateWithoutLoaders = templateFilename.replace(/^.+!/, '').replace(/\?.+$/, '');
131
- const vmContext = vm.createContext({ HTML_WEBPACK_PLUGIN: true, require: require, htmlWebpackPluginPublicPath: publicPath, ...global });
130
+ const vmContext = vm.createContext({
131
+ ...global,
132
+ HTML_WEBPACK_PLUGIN: true,
133
+ require: require,
134
+ htmlWebpackPluginPublicPath: publicPath,
135
+ URL: require('url').URL,
136
+ __filename: templateWithoutLoaders
137
+ });
132
138
  const vmScript = new vm.Script(source, { filename: templateWithoutLoaders });
133
139
  // Evaluate code and cast to string
134
140
  let newSource;
@@ -147,7 +153,8 @@ class HtmlWebpackPlugin {
147
153
  }
148
154
 
149
155
  /**
150
- * apply is called by the webpack main compiler during the start phase
156
+ * connect the html-webpack-plugin to the webpack compiler lifecycle hooks
157
+ *
151
158
  * @param {import('webpack').Compiler} compiler
152
159
  * @param {ProcessedHtmlWebpackOptions} options
153
160
  * @param {HtmlWebpackPlugin} plugin
@@ -180,13 +187,6 @@ function hookIntoCompiler (compiler, options, plugin) {
180
187
  options.filename = path.relative(outputPath, filename);
181
188
  }
182
189
 
183
- // `contenthash` is introduced in webpack v4.3
184
- // which conflicts with the plugin's existing `contenthash` method,
185
- // hence it is renamed to `templatehash` to avoid conflicts
186
- options.filename = options.filename.replace(/\[(?:(\w+):)?contenthash(?::([a-z]+\d*))?(?::(\d+))?\]/ig, (match) => {
187
- return match.replace('contenthash', 'templatehash');
188
- });
189
-
190
190
  // Check if webpack is running in production mode
191
191
  // @see https://github.com/webpack/webpack/blob/3366421f1784c449f415cda5930a8e445086f688/lib/WebpackOptionsDefaulter.js#L12-L14
192
192
  const isProductionLikeMode = compiler.options.mode === 'production' || !compiler.options.mode;
@@ -240,21 +240,12 @@ function hookIntoCompiler (compiler, options, plugin) {
240
240
  compilation.errors.push(prettyError(templateResult.error, compiler.context).toString());
241
241
  }
242
242
 
243
- const compiledEntries = 'compiledEntry' in templateResult ? {
244
- hash: templateResult.compiledEntry.hash,
245
- chunk: templateResult.compiledEntry.entry
246
- } : {
247
- hash: templateResult.mainCompilationHash
248
- };
249
-
250
- const childCompilationOutputName = compilation.getAssetPath(options.filename, compiledEntries);
251
-
252
243
  // If the child compilation was not executed during a previous main compile run
253
244
  // it is a cached result
254
245
  const isCompilationCached = templateResult.mainCompilationHash !== compilation.hash;
255
246
 
256
247
  /** The public path used inside the html file */
257
- const htmlPublicPath = getPublicPath(compilation, childCompilationOutputName, options.publicPath);
248
+ const htmlPublicPath = getPublicPath(compilation, options.filename, options.publicPath);
258
249
 
259
250
  /** Generated file paths from the entry point names */
260
251
  const assets = htmlWebpackPluginAssets(compilation, sortedEntryNames, htmlPublicPath);
@@ -279,7 +270,7 @@ function hookIntoCompiler (compiler, options, plugin) {
279
270
  assets.favicon = faviconPath;
280
271
  return getHtmlWebpackPluginHooks(compilation).beforeAssetTagGeneration.promise({
281
272
  assets: assets,
282
- outputName: childCompilationOutputName,
273
+ outputName: options.filename,
283
274
  plugin: plugin
284
275
  });
285
276
  });
@@ -297,7 +288,7 @@ function hookIntoCompiler (compiler, options, plugin) {
297
288
  ...generateFaviconTags(assets.favicon)
298
289
  ]
299
290
  },
300
- outputName: childCompilationOutputName,
291
+ outputName: options.filename,
301
292
  publicPath: htmlPublicPath,
302
293
  plugin: plugin
303
294
  }))
@@ -311,7 +302,7 @@ function hookIntoCompiler (compiler, options, plugin) {
311
302
  return getHtmlWebpackPluginHooks(compilation).alterAssetTagGroups.promise({
312
303
  headTags: assetGroups.headTags,
313
304
  bodyTags: assetGroups.bodyTags,
314
- outputName: childCompilationOutputName,
305
+ outputName: options.filename,
315
306
  publicPath: htmlPublicPath,
316
307
  plugin: plugin
317
308
  });
@@ -342,7 +333,7 @@ function hookIntoCompiler (compiler, options, plugin) {
342
333
  const injectedHtmlPromise = Promise.all([assetTagGroupsPromise, templateExectutionPromise])
343
334
  // Allow plugins to change the html before assets are injected
344
335
  .then(([assetTags, html]) => {
345
- 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 };
346
337
  return getHtmlWebpackPluginHooks(compilation).afterTemplateExecution.promise(pluginArgs);
347
338
  })
348
339
  .then(({ html, headTags, bodyTags }) => {
@@ -352,7 +343,7 @@ function hookIntoCompiler (compiler, options, plugin) {
352
343
  const emitHtmlPromise = injectedHtmlPromise
353
344
  // Allow plugins to change the html after assets are injected
354
345
  .then((html) => {
355
- const pluginArgs = { html, plugin: plugin, outputName: childCompilationOutputName };
346
+ const pluginArgs = { html, plugin: plugin, outputName: options.filename };
356
347
  return getHtmlWebpackPluginHooks(compilation).beforeEmit.promise(pluginArgs)
357
348
  .then(result => result.html);
358
349
  })
@@ -363,16 +354,15 @@ function hookIntoCompiler (compiler, options, plugin) {
363
354
  return options.showErrors ? prettyError(err, compiler.context).toHtml() : 'ERROR';
364
355
  })
365
356
  .then(html => {
366
- // Allow to use [templatehash] as placeholder for the html-webpack-plugin name
367
- // See also https://survivejs.com/webpack/optimizing/adding-hashes-to-filenames/
368
- // From https://github.com/webpack-contrib/extract-text-webpack-plugin/blob/8de6558e33487e7606e7cd7cb2adc2cccafef272/src/index.js#L212-L214
369
- const finalOutputName = childCompilationOutputName.replace(/\[(?:(\w+):)?templatehash(?::([a-z]+\d*))?(?::(\d+))?\]/ig, (_, hashType, digestType, maxLength) => {
370
- return loaderUtils.getHashDigest(Buffer.from(html, 'utf8'), hashType, digestType, parseInt(maxLength, 10));
371
- });
357
+ const filename = options.filename.replace(/\[templatehash([^\]]*)\]/g, require('util').deprecate(
358
+ (match, options) => `[contenthash${options}]`,
359
+ '[templatehash] is now [contenthash]')
360
+ );
361
+ const replacedFilename = replacePlaceholdersInFilename(filename, html, compilation);
372
362
  // Add the evaluated html code to the webpack assets
373
- compilation.emitAsset(finalOutputName, new webpack.sources.RawSource(html, false));
374
- previousEmittedAssets.push({ name: finalOutputName, html });
375
- 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;
376
366
  })
377
367
  .then((finalOutputName) => getHtmlWebpackPluginHooks(compilation).afterEmit.promise({
378
368
  outputName: finalOutputName,
@@ -510,6 +500,38 @@ function hookIntoCompiler (compiler, options, plugin) {
510
500
  });
511
501
  }
512
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
+
513
535
  /**
514
536
  * Helper to sort chunks
515
537
  * @param {string[]} entryNames
@@ -75,6 +75,7 @@ class HtmlWebpackChildCompiler {
75
75
  const webpack = mainCompilation.compiler.webpack;
76
76
  const Compilation = webpack.Compilation;
77
77
 
78
+ const NodeTemplatePlugin = webpack.node.NodeTemplatePlugin;
78
79
  const NodeTargetPlugin = webpack.node.NodeTargetPlugin;
79
80
  const LoaderTargetPlugin = webpack.LoaderTargetPlugin;
80
81
  const EntryPlugin = webpack.EntryPlugin;
@@ -103,6 +104,7 @@ class HtmlWebpackChildCompiler {
103
104
  const childCompiler = mainCompilation.createChildCompiler(compilerName, outputOptions, [
104
105
  // Compile the template to nodejs javascript
105
106
  new NodeTargetPlugin(),
107
+ new NodeTemplatePlugin(),
106
108
  new LoaderTargetPlugin('node'),
107
109
  new webpack.library.EnableLibraryPlugin('var')
108
110
  ]);
@@ -114,10 +116,18 @@ class HtmlWebpackChildCompiler {
114
116
 
115
117
  // Add all templates
116
118
  this.templates.forEach((template, index) => {
117
- new EntryPlugin(childCompiler.context, 'data:text/javascript,__webpack_public_path__ = htmlWebpackPluginPublicPath;', `HtmlWebpackPlugin_${index}-${this.id}`).apply(childCompiler);
119
+ new EntryPlugin(childCompiler.context, 'data:text/javascript,__webpack_public_path__ = __webpack_base_uri__ = htmlWebpackPluginPublicPath;', `HtmlWebpackPlugin_${index}-${this.id}`).apply(childCompiler);
118
120
  new EntryPlugin(childCompiler.context, template, `HtmlWebpackPlugin_${index}-${this.id}`).apply(childCompiler);
119
121
  });
120
122
 
123
+ // The templates are compiled and executed by NodeJS - similar to server side rendering
124
+ // Unfortunately this causes issues as some loaders require an absolute URL to support ES Modules
125
+ // The following config enables relative URL support for the child compiler
126
+ childCompiler.options.module = { ...childCompiler.options.module };
127
+ childCompiler.options.module.parser = { ...childCompiler.options.module.parser };
128
+ childCompiler.options.module.parser.javascript = { ...childCompiler.options.module.parser.javascript,
129
+ url: 'relative' };
130
+
121
131
  this.compilationStartedTimestamp = new Date().getTime();
122
132
  this.compilationPromise = new Promise((resolve, reject) => {
123
133
  const extractedAssets = [];
package/lib/html-tags.js CHANGED
@@ -25,12 +25,12 @@ const voidTags = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'k
25
25
  * A tag element according to the htmlWebpackPlugin object notation
26
26
  *
27
27
  * @param xhtml {boolean}
28
- * Wether the generated html should add closing slashes to be xhtml compliant
28
+ * Whether the generated html should add closing slashes to be xhtml compliant
29
29
  */
30
30
  function htmlTagObjectToString (tagDefinition, xhtml) {
31
31
  const attributes = Object.keys(tagDefinition.attributes || {})
32
32
  .filter(function (attributeName) {
33
- return tagDefinition.attributes[attributeName] !== false;
33
+ return tagDefinition.attributes[attributeName] === '' || tagDefinition.attributes[attributeName];
34
34
  })
35
35
  .map(function (attributeName) {
36
36
  if (tagDefinition.attributes[attributeName] === true) {
@@ -49,13 +49,13 @@ function htmlTagObjectToString (tagDefinition, xhtml) {
49
49
  * @param {string} tagName
50
50
  * the name of the tag e.g. 'div'
51
51
  *
52
- * @param {{[attributeName: string]: string|boolean}} [attributes]
52
+ * @param {{[attributeName: string]: string|boolean|null|undefined}} [attributes]
53
53
  * tag attributes e.g. `{ 'class': 'example', disabled: true }`
54
54
  *
55
55
  * @param {string} [innerHTML]
56
56
  *
57
- * @param {{[attributeName: string]: string|boolean}} [meta]
58
- * meta information about the tag e.g. `{ 'pluhin': 'html-webpack-plugin' }`
57
+ * @param {{[attributeName: string]: string|boolean|null|undefined}} [meta]
58
+ * meta information about the tag e.g. `{ 'plugin': 'html-webpack-plugin' }`
59
59
  *
60
60
  * @returns {HtmlTagObject}
61
61
  */
package/lib/loader.js CHANGED
@@ -2,20 +2,26 @@
2
2
  // @ts-nocheck
3
3
  'use strict';
4
4
  const _ = require('lodash');
5
- const loaderUtils = require('loader-utils');
6
5
 
7
6
  module.exports = function (source) {
8
7
  // Get templating options
9
- const options = this.query !== '' ? loaderUtils.getOptions(this) : {};
8
+ const options = this.getOptions();
10
9
  const force = options.force || false;
11
10
 
12
- const allLoadersButThisOne = this.loaders.filter(function (loader) {
13
- return loader.normal !== module.exports;
14
- });
11
+ const allLoadersButThisOne = this.loaders.filter((loader) => loader.normal !== module.exports);
12
+
15
13
  // This loader shouldn't kick in if there is any other loader (unless it's explicitly enforced)
16
14
  if (allLoadersButThisOne.length > 0 && !force) {
17
15
  return source;
18
16
  }
17
+
18
+ // Allow only one html-webpack-plugin loader to allow loader options in the webpack config
19
+ const htmlWebpackPluginLoaders = this.loaders.filter((loader) => loader.normal === module.exports);
20
+ const lastHtmlWebpackPluginLoader = htmlWebpackPluginLoaders[htmlWebpackPluginLoaders.length - 1];
21
+ if (this.loaders[this.loaderIndex] !== lastHtmlWebpackPluginLoader) {
22
+ return source;
23
+ }
24
+
19
25
  // Skip .js files (unless it's explicitly enforced)
20
26
  if (/\.js$/.test(this.resourcePath) && !force) {
21
27
  return source;
@@ -23,7 +29,7 @@ module.exports = function (source) {
23
29
 
24
30
  // The following part renders the template with lodash as a minimalistic loader
25
31
  //
26
- const template = _.template(source, _.defaults(options, { interpolate: /<%=([\s\S]+?)%>/g, variable: 'data' }));
32
+ const template = _.template(source, { interpolate: /<%=([\s\S]+?)%>/g, variable: 'data', ...options });
27
33
  // Use __non_webpack_require__ to enforce using the native nodejs require
28
34
  // during template execution
29
35
  return 'var _ = __non_webpack_require__(' + JSON.stringify(require.resolve('lodash')) + ');' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "html-webpack-plugin",
3
- "version": "5.0.0",
3
+ "version": "5.3.1",
4
4
  "license": "MIT",
5
5
  "description": "Simplifies creation of HTML files to serve your webpack bundles",
6
6
  "author": "Jan Nicklas <j.nicklas@me.com> (https://github.com/jantimon)",
@@ -28,17 +28,15 @@
28
28
  ]
29
29
  },
30
30
  "devDependencies": {
31
- "@types/loader-utils": "2.0.1",
32
31
  "@types/node": "11.13.9",
33
32
  "commitizen": "4.2.1",
34
33
  "css-loader": "5.0.1",
35
34
  "cz-conventional-changelog": "2.1.0",
36
35
  "dir-compare": "1.7.2",
37
- "file-loader": "6.2.0",
38
- "html-loader": "1.3.2",
36
+ "html-loader": "2.1.1",
39
37
  "jest": "26.5.3",
40
38
  "mini-css-extract-plugin": "1.0.0",
41
- "pug": "2.0.3",
39
+ "pug": "3.0.2",
42
40
  "pug-loader": "2.4.0",
43
41
  "raw-loader": "4.0.2",
44
42
  "rimraf": "2.6.3",
@@ -46,14 +44,13 @@
46
44
  "standard-version": "9.1.0",
47
45
  "style-loader": "2.0.0",
48
46
  "typescript": "4.1.3",
49
- "webpack": "^5.20.0",
47
+ "webpack": "5.24.3",
50
48
  "webpack-recompilation-simulator": "3.2.0",
51
- "webpack-cli": "4.2.0"
49
+ "webpack-cli": "4.5.0"
52
50
  },
53
51
  "dependencies": {
54
52
  "@types/html-minifier-terser": "^5.0.0",
55
53
  "html-minifier-terser": "^5.0.1",
56
- "loader-utils": "^2.0.0",
57
54
  "lodash": "^4.17.20",
58
55
  "pretty-error": "^2.1.1",
59
56
  "tapable": "^2.0.0"
package/typings.d.ts CHANGED
@@ -94,7 +94,7 @@ declare namespace HtmlWebpackPlugin {
94
94
  * blocking will result in <script src="..."></script>
95
95
  * defer will result in <script defer src="..."></script>
96
96
  *
97
- * @default 'blocking'
97
+ * @default 'defer'
98
98
  */
99
99
  scriptLoading?: "blocking" | "defer";
100
100
  /**
@@ -263,7 +263,7 @@ declare namespace HtmlWebpackPlugin {
263
263
  * E.g. `{'disabled': true, 'value': 'demo'}`
264
264
  */
265
265
  attributes: {
266
- [attributeName: string]: string | boolean;
266
+ [attributeName: string]: string | boolean | null | undefined;
267
267
  };
268
268
  /**
269
269
  * The tag name e.g. `'div'`