UNPKG

20.6 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const OptionsApply = require("./OptionsApply");
9
10const AssetModulesPlugin = require("./asset/AssetModulesPlugin");
11const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
12const JsonModulesPlugin = require("./json/JsonModulesPlugin");
13
14const ChunkPrefetchPreloadPlugin = require("./prefetch/ChunkPrefetchPreloadPlugin");
15
16const EntryOptionPlugin = require("./EntryOptionPlugin");
17const RecordIdsPlugin = require("./RecordIdsPlugin");
18
19const RuntimePlugin = require("./RuntimePlugin");
20
21const APIPlugin = require("./APIPlugin");
22const CompatibilityPlugin = require("./CompatibilityPlugin");
23const ConstPlugin = require("./ConstPlugin");
24const ExportsInfoApiPlugin = require("./ExportsInfoApiPlugin");
25
26const TemplatedPathPlugin = require("./TemplatedPathPlugin");
27const UseStrictPlugin = require("./UseStrictPlugin");
28const WarnCaseSensitiveModulesPlugin = require("./WarnCaseSensitiveModulesPlugin");
29
30const DataUriPlugin = require("./schemes/DataUriPlugin");
31const FileUriPlugin = require("./schemes/FileUriPlugin");
32
33const ResolverCachePlugin = require("./cache/ResolverCachePlugin");
34
35const CommonJsPlugin = require("./dependencies/CommonJsPlugin");
36const HarmonyModulesPlugin = require("./dependencies/HarmonyModulesPlugin");
37const ImportMetaPlugin = require("./dependencies/ImportMetaPlugin");
38const ImportPlugin = require("./dependencies/ImportPlugin");
39const LoaderPlugin = require("./dependencies/LoaderPlugin");
40const RequireContextPlugin = require("./dependencies/RequireContextPlugin");
41const RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
42const RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");
43const SystemPlugin = require("./dependencies/SystemPlugin");
44const URLPlugin = require("./dependencies/URLPlugin");
45
46const InferAsyncModulesPlugin = require("./async-modules/InferAsyncModulesPlugin");
47
48const FlagUsingEvalPlugin = require("./FlagUsingEvalPlugin");
49const DefaultStatsFactoryPlugin = require("./stats/DefaultStatsFactoryPlugin");
50const DefaultStatsPresetPlugin = require("./stats/DefaultStatsPresetPlugin");
51const DefaultStatsPrinterPlugin = require("./stats/DefaultStatsPrinterPlugin");
52
53const { cleverMerge } = require("./util/cleverMerge");
54
55/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
56/** @typedef {import("./Compiler")} Compiler */
57
58class WebpackOptionsApply extends OptionsApply {
59 constructor() {
60 super();
61 }
62
63 /**
64 * @param {WebpackOptions} options options object
65 * @param {Compiler} compiler compiler object
66 * @returns {WebpackOptions} options object
67 */
68 process(options, compiler) {
69 compiler.outputPath = options.output.path;
70 compiler.recordsInputPath = options.recordsInputPath || null;
71 compiler.recordsOutputPath = options.recordsOutputPath || null;
72 compiler.name = options.name;
73
74 if (options.externalsPresets.node) {
75 const NodeTargetPlugin = require("./node/NodeTargetPlugin");
76 new NodeTargetPlugin().apply(compiler);
77 }
78 if (options.externalsPresets.electronMain) {
79 const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
80 new ElectronTargetPlugin("main").apply(compiler);
81 }
82 if (options.externalsPresets.electronPreload) {
83 const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
84 new ElectronTargetPlugin("preload").apply(compiler);
85 }
86 if (options.externalsPresets.electronRenderer) {
87 const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
88 new ElectronTargetPlugin("renderer").apply(compiler);
89 }
90 if (
91 options.externalsPresets.electron &&
92 !options.externalsPresets.electronMain &&
93 !options.externalsPresets.electronPreload &&
94 !options.externalsPresets.electronRenderer
95 ) {
96 const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
97 new ElectronTargetPlugin().apply(compiler);
98 }
99 if (options.externalsPresets.nwjs) {
100 const ExternalsPlugin = require("./ExternalsPlugin");
101 new ExternalsPlugin("commonjs", "nw.gui").apply(compiler);
102 }
103 if (options.externalsPresets.webAsync) {
104 const ExternalsPlugin = require("./ExternalsPlugin");
105 new ExternalsPlugin("import", /^(https?:\/\/|std:)/).apply(compiler);
106 } else if (options.externalsPresets.web) {
107 const ExternalsPlugin = require("./ExternalsPlugin");
108 new ExternalsPlugin("module", /^(https?:\/\/|std:)/).apply(compiler);
109 }
110
111 new ChunkPrefetchPreloadPlugin().apply(compiler);
112
113 if (typeof options.output.chunkFormat === "string") {
114 switch (options.output.chunkFormat) {
115 case "array-push": {
116 const ArrayPushCallbackChunkFormatPlugin = require("./javascript/ArrayPushCallbackChunkFormatPlugin");
117 new ArrayPushCallbackChunkFormatPlugin().apply(compiler);
118 break;
119 }
120 case "commonjs": {
121 const CommonJsChunkFormatPlugin = require("./javascript/CommonJsChunkFormatPlugin");
122 new CommonJsChunkFormatPlugin().apply(compiler);
123 break;
124 }
125 case "module":
126 throw new Error(
127 "EcmaScript Module CHunk Format is not implemented yet"
128 );
129 default:
130 throw new Error(
131 "Unsupported chunk format '" + options.output.chunkFormat + "'."
132 );
133 }
134 }
135
136 if (options.output.enabledChunkLoadingTypes.length > 0) {
137 for (const type of options.output.enabledChunkLoadingTypes) {
138 const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin");
139 new EnableChunkLoadingPlugin(type).apply(compiler);
140 }
141 }
142
143 if (options.output.enabledWasmLoadingTypes.length > 0) {
144 for (const type of options.output.enabledWasmLoadingTypes) {
145 const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin");
146 new EnableWasmLoadingPlugin(type).apply(compiler);
147 }
148 }
149
150 if (options.output.enabledLibraryTypes.length > 0) {
151 for (const type of options.output.enabledLibraryTypes) {
152 const EnableLibraryPlugin = require("./library/EnableLibraryPlugin");
153 new EnableLibraryPlugin(type).apply(compiler);
154 }
155 }
156
157 if (options.externals) {
158 const ExternalsPlugin = require("./ExternalsPlugin");
159 new ExternalsPlugin(options.externalsType, options.externals).apply(
160 compiler
161 );
162 }
163
164 if (options.output.pathinfo) {
165 const ModuleInfoHeaderPlugin = require("./ModuleInfoHeaderPlugin");
166 new ModuleInfoHeaderPlugin().apply(compiler);
167 }
168
169 if (options.devtool) {
170 if (options.devtool.includes("source-map")) {
171 const hidden = options.devtool.includes("hidden");
172 const inline = options.devtool.includes("inline");
173 const evalWrapped = options.devtool.includes("eval");
174 const cheap = options.devtool.includes("cheap");
175 const moduleMaps = options.devtool.includes("module");
176 const noSources = options.devtool.includes("nosources");
177 const Plugin = evalWrapped
178 ? require("./EvalSourceMapDevToolPlugin")
179 : require("./SourceMapDevToolPlugin");
180 new Plugin({
181 filename: inline ? null : options.output.sourceMapFilename,
182 moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
183 fallbackModuleFilenameTemplate:
184 options.output.devtoolFallbackModuleFilenameTemplate,
185 append: hidden ? false : undefined,
186 module: moduleMaps ? true : cheap ? false : true,
187 columns: cheap ? false : true,
188 noSources: noSources,
189 namespace: options.output.devtoolNamespace
190 }).apply(compiler);
191 } else if (options.devtool.includes("eval")) {
192 const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
193 new EvalDevToolModulePlugin({
194 moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
195 namespace: options.output.devtoolNamespace
196 }).apply(compiler);
197 }
198 }
199
200 new JavascriptModulesPlugin().apply(compiler);
201 new JsonModulesPlugin().apply(compiler);
202 new AssetModulesPlugin().apply(compiler);
203
204 if (!options.experiments.outputModule) {
205 if (options.output.module) {
206 throw new Error(
207 "'output.module: true' is only allowed when 'experiments.outputModule' is enabled"
208 );
209 }
210 if (options.output.enabledLibraryTypes.includes("module")) {
211 throw new Error(
212 "library type \"module\" is only allowed when 'experiments.outputModule' is enabled"
213 );
214 }
215 if (options.externalsType === "module") {
216 throw new Error(
217 "'externalsType: \"module\"' is only allowed when 'experiments.outputModule' is enabled"
218 );
219 }
220 }
221
222 if (options.experiments.syncWebAssembly) {
223 const WebAssemblyModulesPlugin = require("./wasm-sync/WebAssemblyModulesPlugin");
224 new WebAssemblyModulesPlugin({
225 mangleImports: options.optimization.mangleWasmImports
226 }).apply(compiler);
227 }
228
229 if (options.experiments.asyncWebAssembly) {
230 const AsyncWebAssemblyModulesPlugin = require("./wasm-async/AsyncWebAssemblyModulesPlugin");
231 new AsyncWebAssemblyModulesPlugin({
232 mangleImports: options.optimization.mangleWasmImports
233 }).apply(compiler);
234 }
235
236 new EntryOptionPlugin().apply(compiler);
237 compiler.hooks.entryOption.call(options.context, options.entry);
238
239 new RuntimePlugin().apply(compiler);
240
241 new InferAsyncModulesPlugin().apply(compiler);
242
243 new DataUriPlugin().apply(compiler);
244 new FileUriPlugin().apply(compiler);
245
246 new CompatibilityPlugin().apply(compiler);
247 new HarmonyModulesPlugin({
248 module: options.module,
249 topLevelAwait: options.experiments.topLevelAwait
250 }).apply(compiler);
251 if (options.amd !== false) {
252 const AMDPlugin = require("./dependencies/AMDPlugin");
253 const RequireJsStuffPlugin = require("./RequireJsStuffPlugin");
254 new AMDPlugin(options.module, options.amd || {}).apply(compiler);
255 new RequireJsStuffPlugin().apply(compiler);
256 }
257 new CommonJsPlugin(options.module).apply(compiler);
258 new LoaderPlugin().apply(compiler);
259 if (options.node !== false) {
260 const NodeStuffPlugin = require("./NodeStuffPlugin");
261 new NodeStuffPlugin(options.node).apply(compiler);
262 }
263 new APIPlugin().apply(compiler);
264 new ExportsInfoApiPlugin().apply(compiler);
265 new ConstPlugin().apply(compiler);
266 new UseStrictPlugin().apply(compiler);
267 new RequireIncludePlugin().apply(compiler);
268 new RequireEnsurePlugin().apply(compiler);
269 new RequireContextPlugin().apply(compiler);
270 new ImportPlugin(options.module).apply(compiler);
271 new SystemPlugin(options.module).apply(compiler);
272 new ImportMetaPlugin().apply(compiler);
273 new URLPlugin().apply(compiler);
274
275 if (options.output.workerChunkLoading) {
276 const WorkerPlugin = require("./dependencies/WorkerPlugin");
277 new WorkerPlugin(options.output.workerChunkLoading).apply(compiler);
278 }
279
280 new DefaultStatsFactoryPlugin().apply(compiler);
281 new DefaultStatsPresetPlugin().apply(compiler);
282 new DefaultStatsPrinterPlugin().apply(compiler);
283
284 new FlagUsingEvalPlugin().apply(compiler);
285
286 if (typeof options.mode !== "string") {
287 const WarnNoModeSetPlugin = require("./WarnNoModeSetPlugin");
288 new WarnNoModeSetPlugin().apply(compiler);
289 }
290
291 const EnsureChunkConditionsPlugin = require("./optimize/EnsureChunkConditionsPlugin");
292 new EnsureChunkConditionsPlugin().apply(compiler);
293 if (options.optimization.removeAvailableModules) {
294 const RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin");
295 new RemoveParentModulesPlugin().apply(compiler);
296 }
297 if (options.optimization.removeEmptyChunks) {
298 const RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin");
299 new RemoveEmptyChunksPlugin().apply(compiler);
300 }
301 if (options.optimization.mergeDuplicateChunks) {
302 const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");
303 new MergeDuplicateChunksPlugin().apply(compiler);
304 }
305 if (options.optimization.flagIncludedChunks) {
306 const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");
307 new FlagIncludedChunksPlugin().apply(compiler);
308 }
309 if (options.optimization.sideEffects) {
310 const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin");
311 new SideEffectsFlagPlugin().apply(compiler);
312 }
313 if (options.optimization.providedExports) {
314 const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");
315 new FlagDependencyExportsPlugin().apply(compiler);
316 }
317 if (options.optimization.usedExports) {
318 const FlagDependencyUsagePlugin = require("./FlagDependencyUsagePlugin");
319 new FlagDependencyUsagePlugin(
320 options.optimization.usedExports === "global"
321 ).apply(compiler);
322 }
323 if (options.optimization.innerGraph) {
324 const InnerGraphPlugin = require("./optimize/InnerGraphPlugin");
325 new InnerGraphPlugin().apply(compiler);
326 }
327 if (options.optimization.mangleExports) {
328 const MangleExportsPlugin = require("./optimize/MangleExportsPlugin");
329 new MangleExportsPlugin(
330 options.optimization.mangleExports !== "size"
331 ).apply(compiler);
332 }
333 if (options.optimization.concatenateModules) {
334 const ModuleConcatenationPlugin = require("./optimize/ModuleConcatenationPlugin");
335 new ModuleConcatenationPlugin().apply(compiler);
336 }
337 if (options.optimization.splitChunks) {
338 const SplitChunksPlugin = require("./optimize/SplitChunksPlugin");
339 new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler);
340 }
341 if (options.optimization.runtimeChunk) {
342 const RuntimeChunkPlugin = require("./optimize/RuntimeChunkPlugin");
343 new RuntimeChunkPlugin(options.optimization.runtimeChunk).apply(compiler);
344 }
345 if (!options.optimization.emitOnErrors) {
346 const NoEmitOnErrorsPlugin = require("./NoEmitOnErrorsPlugin");
347 new NoEmitOnErrorsPlugin().apply(compiler);
348 }
349 if (options.optimization.realContentHash) {
350 const RealContentHashPlugin = require("./optimize/RealContentHashPlugin");
351 new RealContentHashPlugin({
352 hashFunction: options.output.hashFunction,
353 hashDigest: options.output.hashDigest
354 }).apply(compiler);
355 }
356 if (options.optimization.checkWasmTypes) {
357 const WasmFinalizeExportsPlugin = require("./wasm-sync/WasmFinalizeExportsPlugin");
358 new WasmFinalizeExportsPlugin().apply(compiler);
359 }
360 const moduleIds = options.optimization.moduleIds;
361 if (moduleIds) {
362 switch (moduleIds) {
363 case "natural": {
364 const NaturalModuleIdsPlugin = require("./ids/NaturalModuleIdsPlugin");
365 new NaturalModuleIdsPlugin().apply(compiler);
366 break;
367 }
368 case "named": {
369 const NamedModuleIdsPlugin = require("./ids/NamedModuleIdsPlugin");
370 new NamedModuleIdsPlugin().apply(compiler);
371 break;
372 }
373 case "hashed": {
374 const WarnDeprecatedOptionPlugin = require("./WarnDeprecatedOptionPlugin");
375 const HashedModuleIdsPlugin = require("./ids/HashedModuleIdsPlugin");
376 new WarnDeprecatedOptionPlugin(
377 "optimization.moduleIds",
378 "hashed",
379 "deterministic"
380 ).apply(compiler);
381 new HashedModuleIdsPlugin().apply(compiler);
382 break;
383 }
384 case "deterministic": {
385 const DeterministicModuleIdsPlugin = require("./ids/DeterministicModuleIdsPlugin");
386 new DeterministicModuleIdsPlugin().apply(compiler);
387 break;
388 }
389 case "size": {
390 const OccurrenceModuleIdsPlugin = require("./ids/OccurrenceModuleIdsPlugin");
391 new OccurrenceModuleIdsPlugin({
392 prioritiseInitial: true
393 }).apply(compiler);
394 break;
395 }
396 default:
397 throw new Error(
398 `webpack bug: moduleIds: ${moduleIds} is not implemented`
399 );
400 }
401 }
402 const chunkIds = options.optimization.chunkIds;
403 if (chunkIds) {
404 switch (chunkIds) {
405 case "natural": {
406 const NaturalChunkIdsPlugin = require("./ids/NaturalChunkIdsPlugin");
407 new NaturalChunkIdsPlugin().apply(compiler);
408 break;
409 }
410 case "named": {
411 const NamedChunkIdsPlugin = require("./ids/NamedChunkIdsPlugin");
412 new NamedChunkIdsPlugin().apply(compiler);
413 break;
414 }
415 case "deterministic": {
416 const DeterministicChunkIdsPlugin = require("./ids/DeterministicChunkIdsPlugin");
417 new DeterministicChunkIdsPlugin().apply(compiler);
418 break;
419 }
420 case "size": {
421 const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");
422 new OccurrenceChunkIdsPlugin({
423 prioritiseInitial: true
424 }).apply(compiler);
425 break;
426 }
427 case "total-size": {
428 const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");
429 new OccurrenceChunkIdsPlugin({
430 prioritiseInitial: false
431 }).apply(compiler);
432 break;
433 }
434 default:
435 throw new Error(
436 `webpack bug: chunkIds: ${chunkIds} is not implemented`
437 );
438 }
439 }
440 if (options.optimization.nodeEnv) {
441 const DefinePlugin = require("./DefinePlugin");
442 new DefinePlugin({
443 "process.env.NODE_ENV": JSON.stringify(options.optimization.nodeEnv)
444 }).apply(compiler);
445 }
446 if (options.optimization.minimize) {
447 for (const minimizer of options.optimization.minimizer) {
448 if (typeof minimizer === "function") {
449 minimizer.call(compiler, compiler);
450 } else if (minimizer !== "...") {
451 minimizer.apply(compiler);
452 }
453 }
454 }
455
456 if (options.performance) {
457 const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin");
458 new SizeLimitsPlugin(options.performance).apply(compiler);
459 }
460
461 new TemplatedPathPlugin().apply(compiler);
462
463 new RecordIdsPlugin({
464 portableIds: options.optimization.portableRecords
465 }).apply(compiler);
466
467 new WarnCaseSensitiveModulesPlugin().apply(compiler);
468
469 const AddManagedPathsPlugin = require("./cache/AddManagedPathsPlugin");
470 new AddManagedPathsPlugin(
471 options.snapshot.managedPaths,
472 options.snapshot.immutablePaths
473 ).apply(compiler);
474
475 if (options.cache && typeof options.cache === "object") {
476 const cacheOptions = options.cache;
477 switch (cacheOptions.type) {
478 case "memory": {
479 const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
480 new MemoryCachePlugin().apply(compiler);
481 break;
482 }
483 case "filesystem": {
484 const AddBuildDependenciesPlugin = require("./cache/AddBuildDependenciesPlugin");
485 for (const key in cacheOptions.buildDependencies) {
486 const list = cacheOptions.buildDependencies[key];
487 new AddBuildDependenciesPlugin(list).apply(compiler);
488 }
489 const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
490 new MemoryCachePlugin().apply(compiler);
491 switch (cacheOptions.store) {
492 case "pack": {
493 const IdleFileCachePlugin = require("./cache/IdleFileCachePlugin");
494 const PackFileCacheStrategy = require("./cache/PackFileCacheStrategy");
495 new IdleFileCachePlugin(
496 new PackFileCacheStrategy({
497 compiler,
498 fs: compiler.intermediateFileSystem,
499 context: options.context,
500 cacheLocation: cacheOptions.cacheLocation,
501 version: cacheOptions.version,
502 logger: compiler.getInfrastructureLogger(
503 "webpack.cache.PackFileCacheStrategy"
504 ),
505 snapshot: options.snapshot
506 }),
507 cacheOptions.idleTimeout,
508 cacheOptions.idleTimeoutForInitialStore
509 ).apply(compiler);
510 break;
511 }
512 default:
513 throw new Error("Unhandled value for cache.store");
514 }
515 break;
516 }
517 default:
518 // @ts-expect-error Property 'type' does not exist on type 'never'. ts(2339)
519 throw new Error(`Unknown cache type ${cacheOptions.type}`);
520 }
521 }
522 new ResolverCachePlugin().apply(compiler);
523
524 if (options.ignoreWarnings && options.ignoreWarnings.length > 0) {
525 const IgnoreWarningsPlugin = require("./IgnoreWarningsPlugin");
526 new IgnoreWarningsPlugin(options.ignoreWarnings).apply(compiler);
527 }
528
529 compiler.hooks.afterPlugins.call(compiler);
530 if (!compiler.inputFileSystem) {
531 throw new Error("No input filesystem provided");
532 }
533 compiler.resolverFactory.hooks.resolveOptions
534 .for("normal")
535 .tap("WebpackOptionsApply", resolveOptions => {
536 resolveOptions = cleverMerge(options.resolve, resolveOptions);
537 resolveOptions.fileSystem = compiler.inputFileSystem;
538 return resolveOptions;
539 });
540 compiler.resolverFactory.hooks.resolveOptions
541 .for("context")
542 .tap("WebpackOptionsApply", resolveOptions => {
543 resolveOptions = cleverMerge(options.resolve, resolveOptions);
544 resolveOptions.fileSystem = compiler.inputFileSystem;
545 resolveOptions.resolveToContext = true;
546 return resolveOptions;
547 });
548 compiler.resolverFactory.hooks.resolveOptions
549 .for("loader")
550 .tap("WebpackOptionsApply", resolveOptions => {
551 resolveOptions = cleverMerge(options.resolveLoader, resolveOptions);
552 resolveOptions.fileSystem = compiler.inputFileSystem;
553 return resolveOptions;
554 });
555 compiler.hooks.afterResolvers.call(compiler);
556 return options;
557 }
558}
559
560module.exports = WebpackOptionsApply;