Skip to content

Commit a214736

Browse files
fix: reemit assets from loaders (#1811)
1 parent 0db3c2b commit a214736

File tree

3 files changed

+59
-26
lines changed

3 files changed

+59
-26
lines changed

index.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const getHtmlWebpackPluginHooks = require('./lib/hooks.js').getHtmlWebpackPlugin
2121
/** @typedef {import("webpack").Compiler} Compiler */
2222
/** @typedef {ReturnType<Compiler["getInfrastructureLogger"]>} Logger */
2323
/** @typedef {import("webpack/lib/Compilation.js")} Compilation */
24-
/** @typedef {Array<{ source: import('webpack').sources.Source, name: string }>} PreviousEmittedAssets */
24+
/** @typedef {Array<{ name: string, source: import('webpack').sources.Source, info?: import('webpack').AssetInfo }>} PreviousEmittedAssets */
2525
/** @typedef {{ publicPath: string, js: Array<string>, css: Array<string>, manifest?: string, favicon?: string }} AssetsInformationByGroups */
2626

2727
class HtmlWebpackPlugin {
@@ -1023,8 +1023,8 @@ class HtmlWebpackPlugin {
10231023
const newAssetJson = JSON.stringify(this.getAssetFiles(assetsInformationByGroups));
10241024

10251025
if (isCompilationCached && this.options.cache && assetJson.value === newAssetJson) {
1026-
previousEmittedAssets.forEach(({ name, source }) => {
1027-
compilation.emitAsset(name, source);
1026+
previousEmittedAssets.forEach(({ name, source, info }) => {
1027+
compilation.emitAsset(name, source, info);
10281028
});
10291029
return callback();
10301030
} else {
@@ -1084,15 +1084,26 @@ class HtmlWebpackPlugin {
10841084
if ('error' in templateResult) {
10851085
return this.options.showErrors ? prettyError(templateResult.error, compiler.context).toHtml() : 'ERROR';
10861086
}
1087+
10871088
// Allow to use a custom function / string instead
10881089
if (this.options.templateContent !== false) {
10891090
return this.options.templateContent;
10901091
}
1091-
// Once everything is compiled evaluate the html factory
1092-
// and replace it with its content
1093-
return ('compiledEntry' in templateResult)
1094-
? this.evaluateCompilationResult(templateResult.compiledEntry.content, assetsInformationByGroups.publicPath, this.options.template)
1095-
: Promise.reject(new Error('Child compilation contained no compiledEntry'));
1092+
1093+
// Once everything is compiled evaluate the html factory and replace it with its content
1094+
if ('compiledEntry' in templateResult) {
1095+
const compiledEntry = templateResult.compiledEntry;
1096+
const assets = compiledEntry.assets;
1097+
1098+
// Store assets from child compiler to reemit them later
1099+
for (const name in assets) {
1100+
previousEmittedAssets.push({ name, source: assets[name].source, info: assets[name].info });
1101+
}
1102+
1103+
return this.evaluateCompilationResult(compiledEntry.content, assetsInformationByGroups.publicPath, this.options.template);
1104+
}
1105+
1106+
return Promise.reject(new Error('Child compilation contained no compiledEntry'));
10961107
});
10971108
const templateExectutionPromise = Promise.all([assetsPromise, assetTagGroupsPromise, templateEvaluationPromise])
10981109
// Execute the template

lib/cached-child-compiler.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727
/** @typedef {import("webpack").Compiler} Compiler */
2828
/** @typedef {import("webpack").Compilation} Compilation */
2929
/** @typedef {import("webpack/lib/FileSystemInfo").Snapshot} Snapshot */
30-
/** @typedef {{hash: string, entry: any, content: string }} ChildCompilationResultEntry */
30+
/** @typedef {import("./child-compiler").ChildCompilationTemplateResult} ChildCompilationTemplateResult */
3131
/** @typedef {{fileDependencies: string[], contextDependencies: string[], missingDependencies: string[]}} FileDependencies */
3232
/** @typedef {{
3333
dependencies: FileDependencies,
34-
compiledEntries: {[entryName: string]: ChildCompilationResultEntry}
34+
compiledEntries: {[entryName: string]: ChildCompilationTemplateResult}
3535
} | {
3636
dependencies: FileDependencies,
3737
error: Error
@@ -96,7 +96,7 @@ class CachedChildCompilation {
9696
* @param {string} entry
9797
* @returns {
9898
| { mainCompilationHash: string, error: Error }
99-
| { mainCompilationHash: string, compiledEntry: ChildCompilationResultEntry }
99+
| { mainCompilationHash: string, compiledEntry: ChildCompilationTemplateResult }
100100
}
101101
*/
102102
getCompilationEntryResult (entry) {

lib/child-compiler.js

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
/** @typedef {import("webpack").Chunk} Chunk */
1313
/** @typedef {import("webpack").sources.Source} Source */
14+
/** @typedef {{hash: string, entry: Chunk, content: string, assets: {[name: string]: { source: Source, info: import("webpack").AssetInfo }}}} ChildCompilationTemplateResult */
1415

1516
let instanceId = 0;
1617
/**
@@ -30,17 +31,11 @@ class HtmlWebpackChildCompiler {
3031
* The template array will allow us to keep track which input generated which output
3132
*/
3233
this.templates = templates;
33-
/**
34-
* @type {Promise<{[templatePath: string]: { content: string, hash: string, entry: Chunk }}>}
35-
*/
34+
/** @type {Promise<{[templatePath: string]: ChildCompilationTemplateResult}>} */
3635
this.compilationPromise; // eslint-disable-line
37-
/**
38-
* @type {number}
39-
*/
36+
/** @type {number | undefined} */
4037
this.compilationStartedTimestamp; // eslint-disable-line
41-
/**
42-
* @type {number}
43-
*/
38+
/** @type {number | undefined} */
4439
this.compilationEndedTimestamp; // eslint-disable-line
4540
/**
4641
* All file dependencies of the child compiler
@@ -51,6 +46,7 @@ class HtmlWebpackChildCompiler {
5146

5247
/**
5348
* Returns true if the childCompiler is currently compiling
49+
*
5450
* @returns {boolean}
5551
*/
5652
isCompiling () {
@@ -59,6 +55,8 @@ class HtmlWebpackChildCompiler {
5955

6056
/**
6157
* Returns true if the childCompiler is done compiling
58+
*
59+
* @returns {boolean}
6260
*/
6361
didCompile () {
6462
return this.compilationEndedTimestamp !== undefined;
@@ -69,7 +67,7 @@ class HtmlWebpackChildCompiler {
6967
* once it is started no more templates can be added
7068
*
7169
* @param {import('webpack').Compilation} mainCompilation
72-
* @returns {Promise<{[templatePath: string]: { content: string, hash: string, entry: Chunk }}>}
70+
* @returns {Promise<{[templatePath: string]: ChildCompilationTemplateResult}>}
7371
*/
7472
compileTemplates (mainCompilation) {
7573
const webpack = mainCompilation.compiler.webpack;
@@ -125,13 +123,17 @@ class HtmlWebpackChildCompiler {
125123
// The following config enables relative URL support for the child compiler
126124
childCompiler.options.module = { ...childCompiler.options.module };
127125
childCompiler.options.module.parser = { ...childCompiler.options.module.parser };
128-
childCompiler.options.module.parser.javascript = { ...childCompiler.options.module.parser.javascript,
129-
url: 'relative' };
126+
childCompiler.options.module.parser.javascript = {
127+
...childCompiler.options.module.parser.javascript,
128+
url: 'relative'
129+
};
130130

131131
this.compilationStartedTimestamp = new Date().getTime();
132+
/** @type {Promise<{[templatePath: string]: ChildCompilationTemplateResult}>} */
132133
this.compilationPromise = new Promise((resolve, reject) => {
133134
/** @type {Source[]} */
134135
const extractedAssets = [];
136+
135137
childCompiler.hooks.thisCompilation.tap('HtmlWebpackPlugin', (compilation) => {
136138
compilation.hooks.processAssets.tap(
137139
{
@@ -142,6 +144,7 @@ class HtmlWebpackChildCompiler {
142144
temporaryTemplateNames.forEach((temporaryTemplateName) => {
143145
if (assets[temporaryTemplateName]) {
144146
extractedAssets.push(assets[temporaryTemplateName]);
147+
145148
compilation.deleteAsset(temporaryTemplateName);
146149
}
147150
});
@@ -151,13 +154,16 @@ class HtmlWebpackChildCompiler {
151154

152155
childCompiler.runAsChild((err, entries, childCompilation) => {
153156
// Extract templates
157+
// TODO fine a better way to store entries and results, to avoid duplicate chunks and assets
154158
const compiledTemplates = entries
155159
? extractedAssets.map((asset) => asset.source())
156160
: [];
161+
157162
// Extract file dependencies
158163
if (entries && childCompilation) {
159164
this.fileDependencies = { fileDependencies: Array.from(childCompilation.fileDependencies), contextDependencies: Array.from(childCompilation.contextDependencies), missingDependencies: Array.from(childCompilation.missingDependencies) };
160165
}
166+
161167
// Reject the promise if the childCompilation contains error
162168
if (childCompilation && childCompilation.errors && childCompilation.errors.length) {
163169
const errorDetails = childCompilation.errors.map(error => {
@@ -167,34 +173,50 @@ class HtmlWebpackChildCompiler {
167173
}
168174
return message;
169175
}).join('\n');
176+
170177
reject(new Error('Child compilation failed:\n' + errorDetails));
178+
171179
return;
172180
}
181+
173182
// Reject if the error object contains errors
174183
if (err) {
175184
reject(err);
176185
return;
177186
}
187+
178188
if (!childCompilation || !entries) {
179189
reject(new Error('Empty child compilation'));
180190
return;
181191
}
192+
182193
/**
183-
* @type {{[templatePath: string]: { content: string, hash: string, entry: Chunk }}}
194+
* @type {{[templatePath: string]: ChildCompilationTemplateResult}}
184195
*/
185196
const result = {};
197+
198+
/** @type {{[name: string]: { source: Source, info: import("webpack").AssetInfo }}} */
199+
const assets = {};
200+
201+
for (const asset of childCompilation.getAssets()) {
202+
assets[asset.name] = { source: asset.source, info: asset.info };
203+
}
204+
186205
compiledTemplates.forEach((templateSource, entryIndex) => {
187206
// The compiledTemplates are generated from the entries added in
188207
// the addTemplate function.
189-
// Therefore the array index of this.templates should be the as entryIndex.
208+
// Therefore, the array index of this.templates should be the as entryIndex.
190209
result[this.templates[entryIndex]] = {
191210
// TODO, can we have Buffer here?
192211
content: /** @type {string} */ (templateSource),
193212
hash: childCompilation.hash || 'XXXX',
194-
entry: entries[entryIndex]
213+
entry: entries[entryIndex],
214+
assets
195215
};
196216
});
217+
197218
this.compilationEndedTimestamp = new Date().getTime();
219+
198220
resolve(result);
199221
});
200222
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy