1 |
|
2 |
|
3 |
|
4 |
|
5 | 'use strict';
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | 'use strict';
|
14 | const NodeTemplatePlugin = require('webpack/lib/node/NodeTemplatePlugin');
|
15 | const NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
|
16 | const LoaderTargetPlugin = require('webpack/lib/LoaderTargetPlugin');
|
17 | const LibraryTemplatePlugin = require('webpack/lib/LibraryTemplatePlugin');
|
18 | const SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | class HtmlWebpackChildCompiler {
|
25 | |
26 |
|
27 |
|
28 |
|
29 | constructor (templates) {
|
30 | |
31 |
|
32 |
|
33 |
|
34 | this.templates = templates;
|
35 | |
36 |
|
37 |
|
38 | this.compilationPromise;
|
39 | |
40 |
|
41 |
|
42 | this.compilationStartedTimestamp;
|
43 | |
44 |
|
45 |
|
46 | this.compilationEndedTimestamp;
|
47 | |
48 |
|
49 |
|
50 |
|
51 | this.fileDependencies = { fileDependencies: [], contextDependencies: [], missingDependencies: [] };
|
52 | }
|
53 |
|
54 | |
55 |
|
56 |
|
57 |
|
58 | isCompiling () {
|
59 | return !this.didCompile() && this.compilationStartedTimestamp !== undefined;
|
60 | }
|
61 |
|
62 | |
63 |
|
64 |
|
65 | didCompile () {
|
66 | return this.compilationEndedTimestamp !== undefined;
|
67 | }
|
68 |
|
69 | |
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 | compileTemplates (mainCompilation) {
|
77 |
|
78 |
|
79 |
|
80 | if (this.compilationPromise) {
|
81 | return this.compilationPromise;
|
82 | }
|
83 |
|
84 |
|
85 |
|
86 | const outputOptions = {
|
87 | filename: '__child-[name]',
|
88 | publicPath: mainCompilation.outputOptions.publicPath
|
89 | };
|
90 | const compilerName = 'HtmlWebpackCompiler';
|
91 |
|
92 |
|
93 |
|
94 | const childCompiler = mainCompilation.createChildCompiler(compilerName, outputOptions);
|
95 |
|
96 | childCompiler.context = mainCompilation.compiler.context;
|
97 |
|
98 | new NodeTemplatePlugin(outputOptions).apply(childCompiler);
|
99 | new NodeTargetPlugin().apply(childCompiler);
|
100 | new LibraryTemplatePlugin('HTML_WEBPACK_PLUGIN_RESULT', 'var').apply(childCompiler);
|
101 | new LoaderTargetPlugin('node').apply(childCompiler);
|
102 |
|
103 |
|
104 | this.templates.forEach((template, index) => {
|
105 | new SingleEntryPlugin(childCompiler.context, template, `HtmlWebpackPlugin_${index}`).apply(childCompiler);
|
106 | });
|
107 |
|
108 | this.compilationStartedTimestamp = new Date().getTime();
|
109 | this.compilationPromise = new Promise((resolve, reject) => {
|
110 | childCompiler.runAsChild((err, entries, childCompilation) => {
|
111 |
|
112 | const compiledTemplates = entries
|
113 | ? extractHelperFilesFromCompilation(mainCompilation, childCompilation, outputOptions.filename, entries)
|
114 | : [];
|
115 |
|
116 | if (entries) {
|
117 | this.fileDependencies = { fileDependencies: Array.from(childCompilation.fileDependencies), contextDependencies: Array.from(childCompilation.contextDependencies), missingDependencies: Array.from(childCompilation.missingDependencies) };
|
118 | }
|
119 |
|
120 | if (childCompilation && childCompilation.errors && childCompilation.errors.length) {
|
121 | const errorDetails = childCompilation.errors.map(error => {
|
122 | let message = error.message;
|
123 | if (error.error) {
|
124 | message += ':\n' + error.error;
|
125 | }
|
126 | if (error.stack) {
|
127 | message += '\n' + error.stack;
|
128 | }
|
129 | return message;
|
130 | }).join('\n');
|
131 | reject(new Error('Child compilation failed:\n' + errorDetails));
|
132 | return;
|
133 | }
|
134 |
|
135 | if (err) {
|
136 | reject(err);
|
137 | return;
|
138 | }
|
139 | |
140 |
|
141 |
|
142 | const result = {};
|
143 | compiledTemplates.forEach((templateSource, entryIndex) => {
|
144 |
|
145 |
|
146 |
|
147 | result[this.templates[entryIndex]] = {
|
148 | content: templateSource,
|
149 | hash: childCompilation.hash,
|
150 | entry: entries[entryIndex]
|
151 | };
|
152 | });
|
153 | this.compilationEndedTimestamp = new Date().getTime();
|
154 | resolve(result);
|
155 | });
|
156 | });
|
157 |
|
158 | return this.compilationPromise;
|
159 | }
|
160 | }
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 | function extractHelperFilesFromCompilation (mainCompilation, childCompilation, filename, childEntryChunks) {
|
171 | const webpackMajorVersion = Number(require('webpack/package.json').version.split('.')[0]);
|
172 |
|
173 | const helperAssetNames = childEntryChunks.map((entryChunk, index) => {
|
174 | const entryConfig = {
|
175 | hash: childCompilation.hash,
|
176 | chunk: entryChunk,
|
177 | name: `HtmlWebpackPlugin_${index}`
|
178 | };
|
179 |
|
180 | return webpackMajorVersion === 4
|
181 | ? mainCompilation.mainTemplate.getAssetPath(filename, entryConfig)
|
182 | : mainCompilation.getAssetPath(filename, entryConfig);
|
183 | });
|
184 |
|
185 | helperAssetNames.forEach((helperFileName) => {
|
186 | delete mainCompilation.assets[helperFileName];
|
187 | });
|
188 |
|
189 | const helperContents = helperAssetNames.map((helperFileName) => {
|
190 | return childCompilation.assets[helperFileName].source();
|
191 | });
|
192 |
|
193 | return helperContents;
|
194 | }
|
195 |
|
196 | module.exports = {
|
197 | HtmlWebpackChildCompiler
|
198 | };
|