1 |
|
2 | "use strict";
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | class HtmlWebpackChildCompiler {
|
21 | |
22 |
|
23 |
|
24 |
|
25 | constructor(templates) {
|
26 | |
27 |
|
28 |
|
29 |
|
30 | this.templates = templates;
|
31 |
|
32 | this.compilationPromise;
|
33 |
|
34 | this.compilationStartedTimestamp;
|
35 |
|
36 | this.compilationEndedTimestamp;
|
37 | |
38 |
|
39 |
|
40 |
|
41 | this.fileDependencies = {
|
42 | fileDependencies: [],
|
43 | contextDependencies: [],
|
44 | missingDependencies: [],
|
45 | };
|
46 | }
|
47 |
|
48 | |
49 |
|
50 |
|
51 |
|
52 |
|
53 | isCompiling() {
|
54 | return !this.didCompile() && this.compilationStartedTimestamp !== undefined;
|
55 | }
|
56 |
|
57 | |
58 |
|
59 |
|
60 |
|
61 |
|
62 | didCompile() {
|
63 | return this.compilationEndedTimestamp !== undefined;
|
64 | }
|
65 |
|
66 | |
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | compileTemplates(mainCompilation) {
|
74 | const webpack = mainCompilation.compiler.webpack;
|
75 | const Compilation = webpack.Compilation;
|
76 |
|
77 | const NodeTemplatePlugin = webpack.node.NodeTemplatePlugin;
|
78 | const NodeTargetPlugin = webpack.node.NodeTargetPlugin;
|
79 | const LoaderTargetPlugin = webpack.LoaderTargetPlugin;
|
80 | const EntryPlugin = webpack.EntryPlugin;
|
81 |
|
82 |
|
83 |
|
84 |
|
85 | if (this.compilationPromise) {
|
86 | return this.compilationPromise;
|
87 | }
|
88 |
|
89 | const outputOptions = {
|
90 | filename: "__child-[name]",
|
91 | publicPath: "",
|
92 | library: {
|
93 | type: "var",
|
94 | name: "HTML_WEBPACK_PLUGIN_RESULT",
|
95 | },
|
96 | scriptType: ("text/javascript"),
|
97 | iife: true,
|
98 | };
|
99 | const compilerName = "HtmlWebpackCompiler";
|
100 |
|
101 |
|
102 |
|
103 | const childCompiler = mainCompilation.createChildCompiler(
|
104 | compilerName,
|
105 | outputOptions,
|
106 | [
|
107 |
|
108 | new NodeTargetPlugin(),
|
109 | new NodeTemplatePlugin(),
|
110 | new LoaderTargetPlugin("node"),
|
111 | new webpack.library.EnableLibraryPlugin("var"),
|
112 | ],
|
113 | );
|
114 |
|
115 | childCompiler.context = mainCompilation.compiler.context;
|
116 |
|
117 |
|
118 | const temporaryTemplateNames = this.templates.map(
|
119 | (template, index) => `__child-HtmlWebpackPlugin_${index}-${template}`,
|
120 | );
|
121 |
|
122 |
|
123 | this.templates.forEach((template, index) => {
|
124 | new EntryPlugin(
|
125 | childCompiler.context,
|
126 | "data:text/javascript,__webpack_public_path__ = __webpack_base_uri__ = htmlWebpackPluginPublicPath;",
|
127 | `HtmlWebpackPlugin_${index}-${template}`,
|
128 | ).apply(childCompiler);
|
129 | new EntryPlugin(
|
130 | childCompiler.context,
|
131 | template,
|
132 | `HtmlWebpackPlugin_${index}-${template}`,
|
133 | ).apply(childCompiler);
|
134 | });
|
135 |
|
136 |
|
137 |
|
138 |
|
139 | childCompiler.options.module = { ...childCompiler.options.module };
|
140 | childCompiler.options.module.parser = {
|
141 | ...childCompiler.options.module.parser,
|
142 | };
|
143 | childCompiler.options.module.parser.javascript = {
|
144 | ...childCompiler.options.module.parser.javascript,
|
145 | url: "relative",
|
146 | };
|
147 |
|
148 | this.compilationStartedTimestamp = new Date().getTime();
|
149 |
|
150 | this.compilationPromise = new Promise((resolve, reject) => {
|
151 |
|
152 | const extractedAssets = [];
|
153 |
|
154 | childCompiler.hooks.thisCompilation.tap(
|
155 | "HtmlWebpackPlugin",
|
156 | (compilation) => {
|
157 | compilation.hooks.processAssets.tap(
|
158 | {
|
159 | name: "HtmlWebpackPlugin",
|
160 | stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
|
161 | },
|
162 | (assets) => {
|
163 | temporaryTemplateNames.forEach((temporaryTemplateName) => {
|
164 | if (assets[temporaryTemplateName]) {
|
165 | extractedAssets.push(assets[temporaryTemplateName]);
|
166 |
|
167 | compilation.deleteAsset(temporaryTemplateName);
|
168 | }
|
169 | });
|
170 | },
|
171 | );
|
172 | },
|
173 | );
|
174 |
|
175 | childCompiler.runAsChild((err, entries, childCompilation) => {
|
176 |
|
177 |
|
178 | const compiledTemplates = entries
|
179 | ? extractedAssets.map((asset) => asset.source())
|
180 | : [];
|
181 |
|
182 |
|
183 | if (entries && childCompilation) {
|
184 | this.fileDependencies = {
|
185 | fileDependencies: Array.from(childCompilation.fileDependencies),
|
186 | contextDependencies: Array.from(
|
187 | childCompilation.contextDependencies,
|
188 | ),
|
189 | missingDependencies: Array.from(
|
190 | childCompilation.missingDependencies,
|
191 | ),
|
192 | };
|
193 | }
|
194 |
|
195 |
|
196 | if (
|
197 | childCompilation &&
|
198 | childCompilation.errors &&
|
199 | childCompilation.errors.length
|
200 | ) {
|
201 | const errorDetailsArray = [];
|
202 | for (const error of childCompilation.errors) {
|
203 | let message = error.message;
|
204 | if (error.stack) {
|
205 | message += "\n" + error.stack;
|
206 | }
|
207 | errorDetailsArray.push(message);
|
208 | }
|
209 | const errorDetails = errorDetailsArray.join("\n");
|
210 |
|
211 | reject(new Error("Child compilation failed:\n" + errorDetails));
|
212 |
|
213 | return;
|
214 | }
|
215 |
|
216 |
|
217 | if (err) {
|
218 | reject(err);
|
219 | return;
|
220 | }
|
221 |
|
222 | if (!childCompilation || !entries) {
|
223 | reject(new Error("Empty child compilation"));
|
224 | return;
|
225 | }
|
226 |
|
227 | |
228 |
|
229 |
|
230 | const result = {};
|
231 |
|
232 |
|
233 | const assets = {};
|
234 |
|
235 | for (const asset of childCompilation.getAssets()) {
|
236 | assets[asset.name] = { source: asset.source, info: asset.info };
|
237 | }
|
238 |
|
239 | compiledTemplates.forEach((templateSource, entryIndex) => {
|
240 |
|
241 |
|
242 |
|
243 | result[this.templates[entryIndex]] = {
|
244 |
|
245 | content: (templateSource),
|
246 | hash: childCompilation.hash || "XXXX",
|
247 | entry: entries[entryIndex],
|
248 | assets,
|
249 | };
|
250 | });
|
251 |
|
252 | this.compilationEndedTimestamp = new Date().getTime();
|
253 |
|
254 | resolve(result);
|
255 | });
|
256 | });
|
257 |
|
258 | return this.compilationPromise;
|
259 | }
|
260 | }
|
261 |
|
262 | module.exports = {
|
263 | HtmlWebpackChildCompiler,
|
264 | };
|