Projekt

Obecné

Profil

Stáhnout (11.8 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 path = require("path");
8

    
9
const OptionsDefaulter = require("./OptionsDefaulter");
10
const Template = require("./Template");
11

    
12
const isProductionLikeMode = options => {
13
	return options.mode === "production" || !options.mode;
14
};
15

    
16
const isWebLikeTarget = options => {
17
	return options.target === "web" || options.target === "webworker";
18
};
19

    
20
const getDevtoolNamespace = library => {
21
	// if options.output.library is a string
22
	if (Array.isArray(library)) {
23
		return library.join(".");
24
	} else if (typeof library === "object") {
25
		return getDevtoolNamespace(library.root);
26
	}
27
	return library || "";
28
};
29

    
30
class WebpackOptionsDefaulter extends OptionsDefaulter {
31
	constructor() {
32
		super();
33

    
34
		this.set("entry", "./src");
35

    
36
		this.set("devtool", "make", options =>
37
			options.mode === "development" ? "eval" : false
38
		);
39
		this.set("cache", "make", options => options.mode === "development");
40

    
41
		this.set("context", process.cwd());
42
		this.set("target", "web");
43

    
44
		this.set("module", "call", value => Object.assign({}, value));
45
		this.set("module.unknownContextRequest", ".");
46
		this.set("module.unknownContextRegExp", false);
47
		this.set("module.unknownContextRecursive", true);
48
		this.set("module.unknownContextCritical", true);
49
		this.set("module.exprContextRequest", ".");
50
		this.set("module.exprContextRegExp", false);
51
		this.set("module.exprContextRecursive", true);
52
		this.set("module.exprContextCritical", true);
53
		this.set("module.wrappedContextRegExp", /.*/);
54
		this.set("module.wrappedContextRecursive", true);
55
		this.set("module.wrappedContextCritical", false);
56
		this.set("module.strictExportPresence", false);
57
		this.set("module.strictThisContextOnImports", false);
58
		this.set("module.unsafeCache", "make", options => !!options.cache);
59
		this.set("module.rules", []);
60
		this.set("module.defaultRules", "make", options => [
61
			{
62
				type: "javascript/auto",
63
				resolve: {}
64
			},
65
			{
66
				test: /\.mjs$/i,
67
				type: "javascript/esm",
68
				resolve: {
69
					mainFields:
70
						options.target === "web" ||
71
						options.target === "webworker" ||
72
						options.target === "electron-renderer"
73
							? ["browser", "main"]
74
							: ["main"]
75
				}
76
			},
77
			{
78
				test: /\.json$/i,
79
				type: "json"
80
			},
81
			{
82
				test: /\.wasm$/i,
83
				type: "webassembly/experimental"
84
			}
85
		]);
86

    
87
		this.set("output", "call", (value, options) => {
88
			if (typeof value === "string") {
89
				return {
90
					filename: value
91
				};
92
			} else if (typeof value !== "object") {
93
				return {};
94
			} else {
95
				return Object.assign({}, value);
96
			}
97
		});
98

    
99
		this.set("output.filename", "[name].js");
100
		this.set("output.chunkFilename", "make", options => {
101
			const filename = options.output.filename;
102
			if (typeof filename !== "function") {
103
				const hasName = filename.includes("[name]");
104
				const hasId = filename.includes("[id]");
105
				const hasChunkHash = filename.includes("[chunkhash]");
106
				// Anything changing depending on chunk is fine
107
				if (hasChunkHash || hasName || hasId) return filename;
108
				// Elsewise prefix "[id]." in front of the basename to make it changing
109
				return filename.replace(/(^|\/)([^/]*(?:\?|$))/, "$1[id].$2");
110
			}
111
			return "[id].js";
112
		});
113
		this.set("output.webassemblyModuleFilename", "[modulehash].module.wasm");
114
		this.set("output.library", "");
115
		this.set("output.hotUpdateFunction", "make", options => {
116
			return Template.toIdentifier(
117
				"webpackHotUpdate" + Template.toIdentifier(options.output.library)
118
			);
119
		});
120
		this.set("output.jsonpFunction", "make", options => {
121
			return Template.toIdentifier(
122
				"webpackJsonp" + Template.toIdentifier(options.output.library)
123
			);
124
		});
125
		this.set("output.chunkCallbackName", "make", options => {
126
			return Template.toIdentifier(
127
				"webpackChunk" + Template.toIdentifier(options.output.library)
128
			);
129
		});
130
		this.set("output.globalObject", "make", options => {
131
			switch (options.target) {
132
				case "web":
133
				case "electron-renderer":
134
				case "node-webkit":
135
					return "window";
136
				case "webworker":
137
					return "self";
138
				case "node":
139
				case "async-node":
140
				case "electron-main":
141
					return "global";
142
				default:
143
					return "self";
144
			}
145
		});
146
		this.set("output.devtoolNamespace", "make", options => {
147
			return getDevtoolNamespace(options.output.library);
148
		});
149
		this.set("output.libraryTarget", "var");
150
		this.set("output.path", path.join(process.cwd(), "dist"));
151
		this.set(
152
			"output.pathinfo",
153
			"make",
154
			options => options.mode === "development"
155
		);
156
		this.set("output.sourceMapFilename", "[file].map[query]");
157
		this.set("output.hotUpdateChunkFilename", "[id].[hash].hot-update.js");
158
		this.set("output.hotUpdateMainFilename", "[hash].hot-update.json");
159
		this.set("output.crossOriginLoading", false);
160
		this.set("output.jsonpScriptType", false);
161
		this.set("output.chunkLoadTimeout", 120000);
162
		this.set("output.hashFunction", "md4");
163
		this.set("output.hashDigest", "hex");
164
		this.set("output.hashDigestLength", 20);
165
		this.set("output.devtoolLineToLine", false);
166
		this.set("output.strictModuleExceptionHandling", false);
167

    
168
		this.set("node", "call", value => {
169
			if (typeof value === "boolean") {
170
				return value;
171
			} else {
172
				return Object.assign({}, value);
173
			}
174
		});
175
		this.set("node.console", false);
176
		this.set("node.process", true);
177
		this.set("node.global", true);
178
		this.set("node.Buffer", true);
179
		this.set("node.setImmediate", true);
180
		this.set("node.__filename", "mock");
181
		this.set("node.__dirname", "mock");
182

    
183
		this.set("performance", "call", (value, options) => {
184
			if (value === false) return false;
185
			if (
186
				value === undefined &&
187
				(!isProductionLikeMode(options) || !isWebLikeTarget(options))
188
			)
189
				return false;
190
			return Object.assign({}, value);
191
		});
192
		this.set("performance.maxAssetSize", 250000);
193
		this.set("performance.maxEntrypointSize", 250000);
194
		this.set("performance.hints", "make", options =>
195
			isProductionLikeMode(options) ? "warning" : false
196
		);
197

    
198
		this.set("optimization", "call", value => Object.assign({}, value));
199
		// TODO webpack 5: Disable by default in a modes
200
		this.set(
201
			"optimization.removeAvailableModules",
202
			"make",
203
			options => options.mode !== "development"
204
		);
205
		this.set("optimization.removeEmptyChunks", true);
206
		this.set("optimization.mergeDuplicateChunks", true);
207
		this.set("optimization.flagIncludedChunks", "make", options =>
208
			isProductionLikeMode(options)
209
		);
210
		// TODO webpack 5 add `moduleIds: "named"` default for development
211
		// TODO webpack 5 add `moduleIds: "size"` default for production
212
		// TODO webpack 5 remove optimization.occurrenceOrder
213
		this.set("optimization.occurrenceOrder", "make", options =>
214
			isProductionLikeMode(options)
215
		);
216
		this.set("optimization.sideEffects", "make", options =>
217
			isProductionLikeMode(options)
218
		);
219
		this.set("optimization.providedExports", true);
220
		this.set("optimization.usedExports", "make", options =>
221
			isProductionLikeMode(options)
222
		);
223
		this.set("optimization.concatenateModules", "make", options =>
224
			isProductionLikeMode(options)
225
		);
226
		this.set("optimization.splitChunks", {});
227
		this.set("optimization.splitChunks.hidePathInfo", "make", options => {
228
			return isProductionLikeMode(options);
229
		});
230
		this.set("optimization.splitChunks.chunks", "async");
231
		this.set("optimization.splitChunks.minSize", "make", options => {
232
			return isProductionLikeMode(options) ? 30000 : 10000;
233
		});
234
		this.set("optimization.splitChunks.minChunks", 1);
235
		this.set("optimization.splitChunks.maxAsyncRequests", "make", options => {
236
			return isProductionLikeMode(options) ? 5 : Infinity;
237
		});
238
		this.set("optimization.splitChunks.automaticNameDelimiter", "~");
239
		this.set("optimization.splitChunks.automaticNameMaxLength", 109);
240
		this.set("optimization.splitChunks.maxInitialRequests", "make", options => {
241
			return isProductionLikeMode(options) ? 3 : Infinity;
242
		});
243
		this.set("optimization.splitChunks.name", true);
244
		this.set("optimization.splitChunks.cacheGroups", {});
245
		this.set("optimization.splitChunks.cacheGroups.default", {
246
			automaticNamePrefix: "",
247
			reuseExistingChunk: true,
248
			minChunks: 2,
249
			priority: -20
250
		});
251
		this.set("optimization.splitChunks.cacheGroups.vendors", {
252
			automaticNamePrefix: "vendors",
253
			test: /[\\/]node_modules[\\/]/,
254
			priority: -10
255
		});
256
		this.set("optimization.runtimeChunk", "call", value => {
257
			if (value === "single") {
258
				return {
259
					name: "runtime"
260
				};
261
			}
262
			if (value === true || value === "multiple") {
263
				return {
264
					name: entrypoint => `runtime~${entrypoint.name}`
265
				};
266
			}
267
			return value;
268
		});
269
		this.set("optimization.noEmitOnErrors", "make", options =>
270
			isProductionLikeMode(options)
271
		);
272
		this.set("optimization.checkWasmTypes", "make", options =>
273
			isProductionLikeMode(options)
274
		);
275
		this.set("optimization.mangleWasmImports", false);
276
		// TODO webpack 5 remove optimization.namedModules
277
		this.set(
278
			"optimization.namedModules",
279
			"make",
280
			options => options.mode === "development"
281
		);
282
		this.set("optimization.hashedModuleIds", false);
283
		// TODO webpack 5 add `chunkIds: "named"` default for development
284
		// TODO webpack 5 add `chunkIds: "size"` default for production
285
		// TODO webpack 5 remove optimization.namedChunks
286
		this.set(
287
			"optimization.namedChunks",
288
			"make",
289
			options => options.mode === "development"
290
		);
291
		this.set(
292
			"optimization.portableRecords",
293
			"make",
294
			options =>
295
				!!(
296
					options.recordsInputPath ||
297
					options.recordsOutputPath ||
298
					options.recordsPath
299
				)
300
		);
301
		this.set("optimization.minimize", "make", options =>
302
			isProductionLikeMode(options)
303
		);
304
		this.set("optimization.minimizer", "make", options => [
305
			{
306
				apply: compiler => {
307
					// Lazy load the Terser plugin
308
					const TerserPlugin = require("terser-webpack-plugin");
309
					const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin");
310
					new TerserPlugin({
311
						cache: true,
312
						parallel: true,
313
						sourceMap:
314
							(options.devtool && /source-?map/.test(options.devtool)) ||
315
							(options.plugins &&
316
								options.plugins.some(p => p instanceof SourceMapDevToolPlugin))
317
					}).apply(compiler);
318
				}
319
			}
320
		]);
321
		this.set("optimization.nodeEnv", "make", options => {
322
			// TODO: In webpack 5, it should return `false` when mode is `none`
323
			return options.mode || "production";
324
		});
325

    
326
		this.set("resolve", "call", value => Object.assign({}, value));
327
		this.set("resolve.unsafeCache", true);
328
		this.set("resolve.modules", ["node_modules"]);
329
		this.set("resolve.extensions", [".wasm", ".mjs", ".js", ".json"]);
330
		this.set("resolve.mainFiles", ["index"]);
331
		this.set("resolve.aliasFields", "make", options => {
332
			if (
333
				options.target === "web" ||
334
				options.target === "webworker" ||
335
				options.target === "electron-renderer"
336
			) {
337
				return ["browser"];
338
			} else {
339
				return [];
340
			}
341
		});
342
		this.set("resolve.mainFields", "make", options => {
343
			if (
344
				options.target === "web" ||
345
				options.target === "webworker" ||
346
				options.target === "electron-renderer"
347
			) {
348
				return ["browser", "module", "main"];
349
			} else {
350
				return ["module", "main"];
351
			}
352
		});
353
		this.set("resolve.cacheWithContext", "make", options => {
354
			return (
355
				Array.isArray(options.resolve.plugins) &&
356
				options.resolve.plugins.length > 0
357
			);
358
		});
359

    
360
		this.set("resolveLoader", "call", value => Object.assign({}, value));
361
		this.set("resolveLoader.unsafeCache", true);
362
		this.set("resolveLoader.mainFields", ["loader", "main"]);
363
		this.set("resolveLoader.extensions", [".js", ".json"]);
364
		this.set("resolveLoader.mainFiles", ["index"]);
365
		this.set("resolveLoader.cacheWithContext", "make", options => {
366
			return (
367
				Array.isArray(options.resolveLoader.plugins) &&
368
				options.resolveLoader.plugins.length > 0
369
			);
370
		});
371

    
372
		this.set("infrastructureLogging", "call", value =>
373
			Object.assign({}, value)
374
		);
375
		this.set("infrastructureLogging.level", "info");
376
		this.set("infrastructureLogging.debug", false);
377
	}
378
}
379

    
380
module.exports = WebpackOptionsDefaulter;
(137-137/144)