Skip to content

Commit d245481

Browse files
committed
fix: when using integrity occurs ERROR in RealContentHashPlugin in serv/watch mode after changes by using dynamic import
1 parent 1aca813 commit d245481

13 files changed

Lines changed: 173 additions & 32 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Change log
22

3+
## 4.0.0-beta.1 (2024-08-13)
4+
5+
- fix: when using integrity occurs ERROR in RealContentHashPlugin in serv/watch mode after changes by using dynamic import
6+
37
## 4.0.0-beta.0 (2024-08-10)
48

59
### BREAKING CHANGES

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
</h1>
77
</div>
88

9-
[![npm](https://img.shields.io/npm/v/html-bundler-webpack-plugin?logo=npm&color=brightgreen 'npm package')](https://www.npmjs.com/package/html-bundler-webpack-plugin 'download npm package')
9+
[![npm](https://img.shields.io/npm/v/html-bundler-webpack-plugin?logo=npm&color=brightgreen 'npm package')](https://www.npmjs.com/package/html-bundler-webpack-plugin/v/4.0.0-beta.1 'download npm package')
1010
[![node](https://img.shields.io/node/v/html-bundler-webpack-plugin)](https://nodejs.org)
1111
[![node](https://img.shields.io/github/package-json/dependency-version/webdiscus/html-bundler-webpack-plugin/peer/webpack)](https://webpack.js.org/)
1212
[![Test](https://github.com/webdiscus/html-bundler-webpack-plugin/actions/workflows/test.yml/badge.svg)](https://github.com/webdiscus/html-bundler-webpack-plugin/actions/workflows/test.yml)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "html-bundler-webpack-plugin",
3-
"version": "4.0.0-beta.0",
3+
"version": "4.0.0-beta.1",
44
"description": "HTML bundler plugin for webpack handles a template as an entry point, extracts CSS and JS from their sources referenced in HTML, supports template engines like Eta, EJS, Handlebars, Nunjucks.",
55
"keywords": [
66
"html",

src/Plugin/Extras/Integrity.js

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ class Integrity {
2727

2828
this.options = options;
2929
this.chunkChildChunksMap = new WeakMap();
30-
this.referencePlaceholders = new Map();
31-
this.placeholderByChunkId = new Map();
3230
this.chunkByChunkId = new Map();
31+
this.templateByChunkId = new Map();
32+
this.placeholderByChunkId = new Map();
3333
}
3434

3535
apply(compiler) {
@@ -69,12 +69,12 @@ class Integrity {
6969
this.isRealContentHash = this.options.isRealContentHash();
7070

7171
// dynamically import a JS file
72-
mainTemplate.hooks.jsonpScript.tap(pluginName, (source) => this.addReference('script', source));
73-
mainTemplate.hooks.linkPreload.tap(pluginName, (source) => this.addReference('link', source));
74-
mainTemplate.hooks.localVars.tap(pluginName, this.setReferencePlaceholder.bind(this));
72+
mainTemplate.hooks.jsonpScript.tap(pluginName, (source) => this.getTemplateByTag('script', source));
73+
mainTemplate.hooks.linkPreload.tap(pluginName, (source) => this.getTemplateByTag('link', source));
74+
mainTemplate.hooks.localVars.tap(pluginName, this.getTemplateByChunk.bind(this));
7575

7676
compilation.hooks.beforeRuntimeRequirements.tap(pluginName, () => {
77-
this.placeholderByChunkId.clear();
77+
// note: don't clear the cached placeholderByChunkId
7878
});
7979

8080
compilation.hooks.processAssets.tap(
@@ -134,6 +134,7 @@ class Integrity {
134134
}
135135

136136
// TODO: find the use case when childChunk.files.size > 1
137+
// the size of childChunk.files is always 1
137138
const childChunkFile = [...childChunk.files][0];
138139
const placeholder = this.placeholderByChunkId.get(childChunk.id);
139140

@@ -143,16 +144,22 @@ class Integrity {
143144
childChunkFile,
144145
(source) => source,
145146
(assetInfo) => {
146-
return assetInfo
147-
? {
148-
...assetInfo,
149-
contenthash: Array.isArray(assetInfo.contenthash)
150-
? [...new Set([...assetInfo.contenthash, placeholder])]
151-
: assetInfo.contenthash
152-
? [...new Set([assetInfo.contenthash, placeholder])]
153-
: placeholder,
154-
}
155-
: undefined;
147+
if (!assetInfo) {
148+
return undefined;
149+
}
150+
151+
let contenthash = placeholder;
152+
153+
if (Array.isArray(assetInfo.contenthash)) {
154+
contenthash = [...new Set([...assetInfo.contenthash, placeholder])];
155+
} else if (assetInfo.contenthash) {
156+
contenthash = [...new Set([assetInfo.contenthash, placeholder])];
157+
}
158+
159+
return {
160+
...assetInfo,
161+
contenthash,
162+
};
156163
}
157164
);
158165
} else {
@@ -172,13 +179,13 @@ class Integrity {
172179
}
173180

174181
/**
175-
* Add the reference of integrity hashes into a tag object.
182+
* Create the integrity template by the tag.
176183
*
177184
* @param {string} tagName
178185
* @param {string} source
179186
* @return {string}
180187
*/
181-
addReference = (tagName, source) => {
188+
getTemplateByTag = (tagName, source) => {
182189
const { compilation, pluginName } = this;
183190
const { Template } = compilation.compiler.webpack;
184191
const { crossOriginLoading } = compilation.outputOptions;
@@ -191,19 +198,21 @@ class Integrity {
191198
};
192199

193200
/**
194-
* Set the placeholder in the hash reference using the hash of a chunk file.
201+
* Create the integrity template by the chunk.
202+
*
203+
* Saves the placeholder in the hash reference using the hash of a chunk file.
195204
* When the asset is processed, the placeholder will be replaced
196205
* with real integrity hash of the processed asset.
197206
*
198207
* @param {string} source
199208
* @param {Chunk} chunk
200209
* @return {string}
201210
*/
202-
setReferencePlaceholder(source, chunk) {
211+
getTemplateByChunk(source, chunk) {
203212
const { Template } = this.compilation.compiler.webpack;
204213

205-
if (this.referencePlaceholders.has(chunk.id)) {
206-
return this.referencePlaceholders.get(chunk.id);
214+
if (this.templateByChunkId.has(chunk.id)) {
215+
return this.templateByChunkId.get(chunk.id);
207216
}
208217

209218
const childChunks = chunk.getAllAsyncChunks();
@@ -218,10 +227,10 @@ class Integrity {
218227
}
219228

220229
if (Object.keys(placeholders).length > 0) {
221-
const refTemplate = Template.asString([source, `${hashesReference} = ${JSON.stringify(placeholders)};`]);
222-
this.referencePlaceholders.set(chunk.id, refTemplate);
230+
const template = Template.asString([source, `${hashesReference} = ${JSON.stringify(placeholders)};`]);
231+
this.templateByChunkId.set(chunk.id, template);
223232

224-
return refTemplate;
233+
return template;
225234
}
226235

227236
return source;
@@ -320,10 +329,10 @@ class Integrity {
320329
*/
321330
const getPlaceholder = (chunkId) => {
322331
// the prefix must be exact 7 chars, the same length as a hash function name, e.g. 'sha256-'
323-
const placeholderPrefix = '___TMP-';
332+
const prefix = 'xxxxxx-';
324333
const hash = Integrity.computeIntegrity(chunkId);
325334

326-
return placeholderPrefix + hash.slice(placeholderPrefix.length);
335+
return prefix + hash.slice(prefix.length);
327336
};
328337

329338
module.exports = Integrity;

test/cases/integrity-dynamic-chunks-import-assets-dev/expected/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<title>Dev</title>
55
<!-- load source script -->
66
<link href="main.css" rel="stylesheet" integrity="sha384-P3uRZYJvNVccCqk2iQVGvwDZOYfrwSq1FHv6Ahsf4lBoPPD3ODc0xdEdeom27+CM" crossorigin="anonymous">
7-
<script src="main.6180b06e.js" defer="defer" integrity="sha384-Z4FhgIhPOjwFF+fQqBxQN+0fSOAaqGSti1rzQNtVlipdTz8Ruwa+NFI68hsRe75h" crossorigin="anonymous"></script>
7+
<script src="main.b2802b44.js" defer="defer" integrity="sha384-0oaEWvg3ko+CNViLGy2MgqEQe65Jbi+2m0/2Q0Mmx5UOsruQcchdOezxnn1odKxD" crossorigin="anonymous"></script>
88
</head>
99
<body>
1010
<h1>Hello World!</h1>

test/cases/integrity-dynamic-chunks-import-assets-dev/expected/main.6180b06e.js renamed to test/cases/integrity-dynamic-chunks-import-assets-dev/expected/main.b2802b44.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)