Projekt

Obecné

Profil

Stáhnout (18.9 KB) Statistiky
| Větev: | Revize:
1
/*
2
	MIT License http://www.opensource.org/licenses/mit-license.php
3
	Author Tobias Koppers @sokra
4
*/
5
"use strict";
6

    
7
const OptionsApply = require("./OptionsApply");
8

    
9
const JavascriptModulesPlugin = require("./JavascriptModulesPlugin");
10
const JsonModulesPlugin = require("./JsonModulesPlugin");
11
const WebAssemblyModulesPlugin = require("./wasm/WebAssemblyModulesPlugin");
12

    
13
const LoaderTargetPlugin = require("./LoaderTargetPlugin");
14
const FunctionModulePlugin = require("./FunctionModulePlugin");
15
const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
16
const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin");
17
const EvalSourceMapDevToolPlugin = require("./EvalSourceMapDevToolPlugin");
18

    
19
const EntryOptionPlugin = require("./EntryOptionPlugin");
20
const RecordIdsPlugin = require("./RecordIdsPlugin");
21

    
22
const APIPlugin = require("./APIPlugin");
23
const ConstPlugin = require("./ConstPlugin");
24
const CommonJsStuffPlugin = require("./CommonJsStuffPlugin");
25
const CompatibilityPlugin = require("./CompatibilityPlugin");
26

    
27
const TemplatedPathPlugin = require("./TemplatedPathPlugin");
28
const WarnCaseSensitiveModulesPlugin = require("./WarnCaseSensitiveModulesPlugin");
29
const UseStrictPlugin = require("./UseStrictPlugin");
30

    
31
const LoaderPlugin = require("./dependencies/LoaderPlugin");
32
const CommonJsPlugin = require("./dependencies/CommonJsPlugin");
33
const HarmonyModulesPlugin = require("./dependencies/HarmonyModulesPlugin");
34
const SystemPlugin = require("./dependencies/SystemPlugin");
35
const ImportPlugin = require("./dependencies/ImportPlugin");
36
const RequireContextPlugin = require("./dependencies/RequireContextPlugin");
37
const RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
38
const RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");
39

    
40
const { cachedCleverMerge } = require("./util/cleverMerge");
41

    
42
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
43
/** @typedef {import("./Compiler")} Compiler */
44

    
45
class WebpackOptionsApply extends OptionsApply {
46
	constructor() {
47
		super();
48
	}
49

    
50
	/**
51
	 * @param {WebpackOptions} options options object
52
	 * @param {Compiler} compiler compiler object
53
	 * @returns {WebpackOptions} options object
54
	 */
55
	process(options, compiler) {
56
		let ExternalsPlugin;
57
		compiler.outputPath = options.output.path;
58
		compiler.recordsInputPath = options.recordsInputPath || options.recordsPath;
59
		compiler.recordsOutputPath =
60
			options.recordsOutputPath || options.recordsPath;
61
		compiler.name = options.name;
62
		// TODO webpack 5 refactor this to MultiCompiler.setDependencies() with a WeakMap
63
		// @ts-ignore TODO
64
		compiler.dependencies = options.dependencies;
65
		if (typeof options.target === "string") {
66
			let JsonpTemplatePlugin;
67
			let FetchCompileWasmTemplatePlugin;
68
			let ReadFileCompileWasmTemplatePlugin;
69
			let NodeSourcePlugin;
70
			let NodeTargetPlugin;
71
			let NodeTemplatePlugin;
72

    
73
			switch (options.target) {
74
				case "web":
75
					JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin");
76
					FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin");
77
					NodeSourcePlugin = require("./node/NodeSourcePlugin");
78
					new JsonpTemplatePlugin().apply(compiler);
79
					new FetchCompileWasmTemplatePlugin({
80
						mangleImports: options.optimization.mangleWasmImports
81
					}).apply(compiler);
82
					new FunctionModulePlugin().apply(compiler);
83
					new NodeSourcePlugin(options.node).apply(compiler);
84
					new LoaderTargetPlugin(options.target).apply(compiler);
85
					break;
86
				case "webworker": {
87
					let WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin");
88
					FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin");
89
					NodeSourcePlugin = require("./node/NodeSourcePlugin");
90
					new WebWorkerTemplatePlugin().apply(compiler);
91
					new FetchCompileWasmTemplatePlugin({
92
						mangleImports: options.optimization.mangleWasmImports
93
					}).apply(compiler);
94
					new FunctionModulePlugin().apply(compiler);
95
					new NodeSourcePlugin(options.node).apply(compiler);
96
					new LoaderTargetPlugin(options.target).apply(compiler);
97
					break;
98
				}
99
				case "node":
100
				case "async-node":
101
					NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
102
					ReadFileCompileWasmTemplatePlugin = require("./node/ReadFileCompileWasmTemplatePlugin");
103
					NodeTargetPlugin = require("./node/NodeTargetPlugin");
104
					new NodeTemplatePlugin({
105
						asyncChunkLoading: options.target === "async-node"
106
					}).apply(compiler);
107
					new ReadFileCompileWasmTemplatePlugin({
108
						mangleImports: options.optimization.mangleWasmImports
109
					}).apply(compiler);
110
					new FunctionModulePlugin().apply(compiler);
111
					new NodeTargetPlugin().apply(compiler);
112
					new LoaderTargetPlugin("node").apply(compiler);
113
					break;
114
				case "node-webkit":
115
					JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin");
116
					NodeTargetPlugin = require("./node/NodeTargetPlugin");
117
					ExternalsPlugin = require("./ExternalsPlugin");
118
					new JsonpTemplatePlugin().apply(compiler);
119
					new FunctionModulePlugin().apply(compiler);
120
					new NodeTargetPlugin().apply(compiler);
121
					new ExternalsPlugin("commonjs", "nw.gui").apply(compiler);
122
					new LoaderTargetPlugin(options.target).apply(compiler);
123
					break;
124
				case "electron-main":
125
					NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
126
					NodeTargetPlugin = require("./node/NodeTargetPlugin");
127
					ExternalsPlugin = require("./ExternalsPlugin");
128
					new NodeTemplatePlugin({
129
						asyncChunkLoading: true
130
					}).apply(compiler);
131
					new FunctionModulePlugin().apply(compiler);
132
					new NodeTargetPlugin().apply(compiler);
133
					new ExternalsPlugin("commonjs", [
134
						"app",
135
						"auto-updater",
136
						"browser-window",
137
						"clipboard",
138
						"content-tracing",
139
						"crash-reporter",
140
						"dialog",
141
						"electron",
142
						"global-shortcut",
143
						"ipc",
144
						"ipc-main",
145
						"menu",
146
						"menu-item",
147
						"native-image",
148
						"original-fs",
149
						"power-monitor",
150
						"power-save-blocker",
151
						"protocol",
152
						"screen",
153
						"session",
154
						"shell",
155
						"tray",
156
						"web-contents"
157
					]).apply(compiler);
158
					new LoaderTargetPlugin(options.target).apply(compiler);
159
					break;
160
				case "electron-renderer":
161
				case "electron-preload":
162
					FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin");
163
					NodeTargetPlugin = require("./node/NodeTargetPlugin");
164
					ExternalsPlugin = require("./ExternalsPlugin");
165
					if (options.target === "electron-renderer") {
166
						JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin");
167
						new JsonpTemplatePlugin().apply(compiler);
168
					} else if (options.target === "electron-preload") {
169
						NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
170
						new NodeTemplatePlugin({
171
							asyncChunkLoading: true
172
						}).apply(compiler);
173
					}
174
					new FetchCompileWasmTemplatePlugin({
175
						mangleImports: options.optimization.mangleWasmImports
176
					}).apply(compiler);
177
					new FunctionModulePlugin().apply(compiler);
178
					new NodeTargetPlugin().apply(compiler);
179
					new ExternalsPlugin("commonjs", [
180
						"clipboard",
181
						"crash-reporter",
182
						"desktop-capturer",
183
						"electron",
184
						"ipc",
185
						"ipc-renderer",
186
						"native-image",
187
						"original-fs",
188
						"remote",
189
						"screen",
190
						"shell",
191
						"web-frame"
192
					]).apply(compiler);
193
					new LoaderTargetPlugin(options.target).apply(compiler);
194
					break;
195
				default:
196
					throw new Error("Unsupported target '" + options.target + "'.");
197
			}
198
		}
199
		// @ts-ignore This is always true, which is good this way
200
		else if (options.target !== false) {
201
			options.target(compiler);
202
		} else {
203
			throw new Error("Unsupported target '" + options.target + "'.");
204
		}
205

    
206
		if (options.output.library || options.output.libraryTarget !== "var") {
207
			const LibraryTemplatePlugin = require("./LibraryTemplatePlugin");
208
			new LibraryTemplatePlugin(
209
				options.output.library,
210
				options.output.libraryTarget,
211
				options.output.umdNamedDefine,
212
				options.output.auxiliaryComment || "",
213
				options.output.libraryExport
214
			).apply(compiler);
215
		}
216
		if (options.externals) {
217
			ExternalsPlugin = require("./ExternalsPlugin");
218
			new ExternalsPlugin(
219
				options.output.libraryTarget,
220
				options.externals
221
			).apply(compiler);
222
		}
223

    
224
		let noSources;
225
		let legacy;
226
		let modern;
227
		let comment;
228
		if (
229
			options.devtool &&
230
			(options.devtool.includes("sourcemap") ||
231
				options.devtool.includes("source-map"))
232
		) {
233
			const hidden = options.devtool.includes("hidden");
234
			const inline = options.devtool.includes("inline");
235
			const evalWrapped = options.devtool.includes("eval");
236
			const cheap = options.devtool.includes("cheap");
237
			const moduleMaps = options.devtool.includes("module");
238
			noSources = options.devtool.includes("nosources");
239
			legacy = options.devtool.includes("@");
240
			modern = options.devtool.includes("#");
241
			comment =
242
				legacy && modern
243
					? "\n/*\n//@ source" +
244
					  "MappingURL=[url]\n//# source" +
245
					  "MappingURL=[url]\n*/"
246
					: legacy
247
					? "\n/*\n//@ source" + "MappingURL=[url]\n*/"
248
					: modern
249
					? "\n//# source" + "MappingURL=[url]"
250
					: null;
251
			const Plugin = evalWrapped
252
				? EvalSourceMapDevToolPlugin
253
				: SourceMapDevToolPlugin;
254
			new Plugin({
255
				filename: inline ? null : options.output.sourceMapFilename,
256
				moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
257
				fallbackModuleFilenameTemplate:
258
					options.output.devtoolFallbackModuleFilenameTemplate,
259
				append: hidden ? false : comment,
260
				module: moduleMaps ? true : cheap ? false : true,
261
				columns: cheap ? false : true,
262
				lineToLine: options.output.devtoolLineToLine,
263
				noSources: noSources,
264
				namespace: options.output.devtoolNamespace
265
			}).apply(compiler);
266
		} else if (options.devtool && options.devtool.includes("eval")) {
267
			legacy = options.devtool.includes("@");
268
			modern = options.devtool.includes("#");
269
			comment =
270
				legacy && modern
271
					? "\n//@ sourceURL=[url]\n//# sourceURL=[url]"
272
					: legacy
273
					? "\n//@ sourceURL=[url]"
274
					: modern
275
					? "\n//# sourceURL=[url]"
276
					: null;
277
			new EvalDevToolModulePlugin({
278
				sourceUrlComment: comment,
279
				moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
280
				namespace: options.output.devtoolNamespace
281
			}).apply(compiler);
282
		}
283

    
284
		new JavascriptModulesPlugin().apply(compiler);
285
		new JsonModulesPlugin().apply(compiler);
286
		new WebAssemblyModulesPlugin({
287
			mangleImports: options.optimization.mangleWasmImports
288
		}).apply(compiler);
289

    
290
		new EntryOptionPlugin().apply(compiler);
291
		compiler.hooks.entryOption.call(options.context, options.entry);
292

    
293
		new CompatibilityPlugin().apply(compiler);
294
		new HarmonyModulesPlugin(options.module).apply(compiler);
295
		if (options.amd !== false) {
296
			const AMDPlugin = require("./dependencies/AMDPlugin");
297
			const RequireJsStuffPlugin = require("./RequireJsStuffPlugin");
298
			new AMDPlugin(options.module, options.amd || {}).apply(compiler);
299
			new RequireJsStuffPlugin().apply(compiler);
300
		}
301
		new CommonJsPlugin(options.module).apply(compiler);
302
		new LoaderPlugin().apply(compiler);
303
		if (options.node !== false) {
304
			const NodeStuffPlugin = require("./NodeStuffPlugin");
305
			new NodeStuffPlugin(options.node).apply(compiler);
306
		}
307
		new CommonJsStuffPlugin().apply(compiler);
308
		new APIPlugin().apply(compiler);
309
		new ConstPlugin().apply(compiler);
310
		new UseStrictPlugin().apply(compiler);
311
		new RequireIncludePlugin().apply(compiler);
312
		new RequireEnsurePlugin().apply(compiler);
313
		new RequireContextPlugin(
314
			options.resolve.modules,
315
			options.resolve.extensions,
316
			options.resolve.mainFiles
317
		).apply(compiler);
318
		new ImportPlugin(options.module).apply(compiler);
319
		new SystemPlugin(options.module).apply(compiler);
320

    
321
		if (typeof options.mode !== "string") {
322
			const WarnNoModeSetPlugin = require("./WarnNoModeSetPlugin");
323
			new WarnNoModeSetPlugin().apply(compiler);
324
		}
325

    
326
		const EnsureChunkConditionsPlugin = require("./optimize/EnsureChunkConditionsPlugin");
327
		new EnsureChunkConditionsPlugin().apply(compiler);
328
		if (options.optimization.removeAvailableModules) {
329
			const RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin");
330
			new RemoveParentModulesPlugin().apply(compiler);
331
		}
332
		if (options.optimization.removeEmptyChunks) {
333
			const RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin");
334
			new RemoveEmptyChunksPlugin().apply(compiler);
335
		}
336
		if (options.optimization.mergeDuplicateChunks) {
337
			const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");
338
			new MergeDuplicateChunksPlugin().apply(compiler);
339
		}
340
		if (options.optimization.flagIncludedChunks) {
341
			const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");
342
			new FlagIncludedChunksPlugin().apply(compiler);
343
		}
344
		if (options.optimization.sideEffects) {
345
			const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin");
346
			new SideEffectsFlagPlugin().apply(compiler);
347
		}
348
		if (options.optimization.providedExports) {
349
			const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");
350
			new FlagDependencyExportsPlugin().apply(compiler);
351
		}
352
		if (options.optimization.usedExports) {
353
			const FlagDependencyUsagePlugin = require("./FlagDependencyUsagePlugin");
354
			new FlagDependencyUsagePlugin().apply(compiler);
355
		}
356
		if (options.optimization.concatenateModules) {
357
			const ModuleConcatenationPlugin = require("./optimize/ModuleConcatenationPlugin");
358
			new ModuleConcatenationPlugin().apply(compiler);
359
		}
360
		if (options.optimization.splitChunks) {
361
			const SplitChunksPlugin = require("./optimize/SplitChunksPlugin");
362
			new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler);
363
		}
364
		if (options.optimization.runtimeChunk) {
365
			const RuntimeChunkPlugin = require("./optimize/RuntimeChunkPlugin");
366
			new RuntimeChunkPlugin(options.optimization.runtimeChunk).apply(compiler);
367
		}
368
		if (options.optimization.noEmitOnErrors) {
369
			const NoEmitOnErrorsPlugin = require("./NoEmitOnErrorsPlugin");
370
			new NoEmitOnErrorsPlugin().apply(compiler);
371
		}
372
		if (options.optimization.checkWasmTypes) {
373
			const WasmFinalizeExportsPlugin = require("./wasm/WasmFinalizeExportsPlugin");
374
			new WasmFinalizeExportsPlugin().apply(compiler);
375
		}
376
		let moduleIds = options.optimization.moduleIds;
377
		if (moduleIds === undefined) {
378
			// TODO webpack 5 remove all these options
379
			if (options.optimization.occurrenceOrder) {
380
				moduleIds = "size";
381
			}
382
			if (options.optimization.namedModules) {
383
				moduleIds = "named";
384
			}
385
			if (options.optimization.hashedModuleIds) {
386
				moduleIds = "hashed";
387
			}
388
			if (moduleIds === undefined) {
389
				moduleIds = "natural";
390
			}
391
		}
392
		if (moduleIds) {
393
			const NamedModulesPlugin = require("./NamedModulesPlugin");
394
			const HashedModuleIdsPlugin = require("./HashedModuleIdsPlugin");
395
			const OccurrenceModuleOrderPlugin = require("./optimize/OccurrenceModuleOrderPlugin");
396
			switch (moduleIds) {
397
				case "natural":
398
					// TODO webpack 5: see hint in Compilation.sortModules
399
					break;
400
				case "named":
401
					new NamedModulesPlugin().apply(compiler);
402
					break;
403
				case "hashed":
404
					new HashedModuleIdsPlugin().apply(compiler);
405
					break;
406
				case "size":
407
					new OccurrenceModuleOrderPlugin({
408
						prioritiseInitial: true
409
					}).apply(compiler);
410
					break;
411
				case "total-size":
412
					new OccurrenceModuleOrderPlugin({
413
						prioritiseInitial: false
414
					}).apply(compiler);
415
					break;
416
				default:
417
					throw new Error(
418
						`webpack bug: moduleIds: ${moduleIds} is not implemented`
419
					);
420
			}
421
		}
422
		let chunkIds = options.optimization.chunkIds;
423
		if (chunkIds === undefined) {
424
			// TODO webpack 5 remove all these options
425
			if (options.optimization.occurrenceOrder) {
426
				// This looks weird but it's for backward-compat
427
				// This bug already existed before adding this feature
428
				chunkIds = "total-size";
429
			}
430
			if (options.optimization.namedChunks) {
431
				chunkIds = "named";
432
			}
433
			if (chunkIds === undefined) {
434
				chunkIds = "natural";
435
			}
436
		}
437
		if (chunkIds) {
438
			const NaturalChunkOrderPlugin = require("./optimize/NaturalChunkOrderPlugin");
439
			const NamedChunksPlugin = require("./NamedChunksPlugin");
440
			const OccurrenceChunkOrderPlugin = require("./optimize/OccurrenceChunkOrderPlugin");
441
			switch (chunkIds) {
442
				case "natural":
443
					new NaturalChunkOrderPlugin().apply(compiler);
444
					break;
445
				case "named":
446
					// TODO webapck 5: for backward-compat this need to have OccurrenceChunkOrderPlugin too
447
					// The NamedChunksPlugin doesn't give every chunk a name
448
					// This should be fixed, and the OccurrenceChunkOrderPlugin should be removed here.
449
					new OccurrenceChunkOrderPlugin({
450
						prioritiseInitial: false
451
					}).apply(compiler);
452
					new NamedChunksPlugin().apply(compiler);
453
					break;
454
				case "size":
455
					new OccurrenceChunkOrderPlugin({
456
						prioritiseInitial: true
457
					}).apply(compiler);
458
					break;
459
				case "total-size":
460
					new OccurrenceChunkOrderPlugin({
461
						prioritiseInitial: false
462
					}).apply(compiler);
463
					break;
464
				default:
465
					throw new Error(
466
						`webpack bug: chunkIds: ${chunkIds} is not implemented`
467
					);
468
			}
469
		}
470
		if (options.optimization.nodeEnv) {
471
			const DefinePlugin = require("./DefinePlugin");
472
			new DefinePlugin({
473
				"process.env.NODE_ENV": JSON.stringify(options.optimization.nodeEnv)
474
			}).apply(compiler);
475
		}
476
		if (options.optimization.minimize) {
477
			for (const minimizer of options.optimization.minimizer) {
478
				if (typeof minimizer === "function") {
479
					minimizer.call(compiler, compiler);
480
				} else {
481
					minimizer.apply(compiler);
482
				}
483
			}
484
		}
485

    
486
		if (options.performance) {
487
			const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin");
488
			new SizeLimitsPlugin(options.performance).apply(compiler);
489
		}
490

    
491
		new TemplatedPathPlugin().apply(compiler);
492

    
493
		new RecordIdsPlugin({
494
			portableIds: options.optimization.portableRecords
495
		}).apply(compiler);
496

    
497
		new WarnCaseSensitiveModulesPlugin().apply(compiler);
498

    
499
		if (options.cache) {
500
			const CachePlugin = require("./CachePlugin");
501
			new CachePlugin(
502
				typeof options.cache === "object" ? options.cache : null
503
			).apply(compiler);
504
		}
505

    
506
		compiler.hooks.afterPlugins.call(compiler);
507
		if (!compiler.inputFileSystem) {
508
			throw new Error("No input filesystem provided");
509
		}
510
		compiler.resolverFactory.hooks.resolveOptions
511
			.for("normal")
512
			.tap("WebpackOptionsApply", resolveOptions => {
513
				return Object.assign(
514
					{
515
						fileSystem: compiler.inputFileSystem
516
					},
517
					cachedCleverMerge(options.resolve, resolveOptions)
518
				);
519
			});
520
		compiler.resolverFactory.hooks.resolveOptions
521
			.for("context")
522
			.tap("WebpackOptionsApply", resolveOptions => {
523
				return Object.assign(
524
					{
525
						fileSystem: compiler.inputFileSystem,
526
						resolveToContext: true
527
					},
528
					cachedCleverMerge(options.resolve, resolveOptions)
529
				);
530
			});
531
		compiler.resolverFactory.hooks.resolveOptions
532
			.for("loader")
533
			.tap("WebpackOptionsApply", resolveOptions => {
534
				return Object.assign(
535
					{
536
						fileSystem: compiler.inputFileSystem
537
					},
538
					cachedCleverMerge(options.resolveLoader, resolveOptions)
539
				);
540
			});
541
		compiler.hooks.afterResolvers.call(compiler);
542
		return options;
543
	}
544
}
545

    
546
module.exports = WebpackOptionsApply;
(136-136/144)