WebpackOptionsApply.js 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const APIPlugin = require("./APIPlugin");
  7. const CompatibilityPlugin = require("./CompatibilityPlugin");
  8. const ConstPlugin = require("./ConstPlugin");
  9. const EntryOptionPlugin = require("./EntryOptionPlugin");
  10. const ExportsInfoApiPlugin = require("./ExportsInfoApiPlugin");
  11. const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");
  12. const JavascriptMetaInfoPlugin = require("./JavascriptMetaInfoPlugin");
  13. const NodeStuffPlugin = require("./NodeStuffPlugin");
  14. const OptionsApply = require("./OptionsApply");
  15. const RecordIdsPlugin = require("./RecordIdsPlugin");
  16. const RuntimePlugin = require("./RuntimePlugin");
  17. const TemplatedPathPlugin = require("./TemplatedPathPlugin");
  18. const UseStrictPlugin = require("./UseStrictPlugin");
  19. const WarnCaseSensitiveModulesPlugin = require("./WarnCaseSensitiveModulesPlugin");
  20. const WebpackIsIncludedPlugin = require("./WebpackIsIncludedPlugin");
  21. const AssetModulesPlugin = require("./asset/AssetModulesPlugin");
  22. const InferAsyncModulesPlugin = require("./async-modules/InferAsyncModulesPlugin");
  23. const ResolverCachePlugin = require("./cache/ResolverCachePlugin");
  24. const CommonJsPlugin = require("./dependencies/CommonJsPlugin");
  25. const HarmonyModulesPlugin = require("./dependencies/HarmonyModulesPlugin");
  26. const ImportMetaContextPlugin = require("./dependencies/ImportMetaContextPlugin");
  27. const ImportMetaPlugin = require("./dependencies/ImportMetaPlugin");
  28. const ImportPlugin = require("./dependencies/ImportPlugin");
  29. const LoaderPlugin = require("./dependencies/LoaderPlugin");
  30. const RequireContextPlugin = require("./dependencies/RequireContextPlugin");
  31. const RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
  32. const RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");
  33. const SystemPlugin = require("./dependencies/SystemPlugin");
  34. const URLPlugin = require("./dependencies/URLPlugin");
  35. const WorkerAndWorkletPlugin = require("./dependencies/WorkerAndWorkletPlugin");
  36. const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
  37. const JsonModulesPlugin = require("./json/JsonModulesPlugin");
  38. const ChunkPrefetchPreloadPlugin = require("./prefetch/ChunkPrefetchPreloadPlugin");
  39. const ResourceHintPlugin = require("./prefetch/ResourceHintPlugin");
  40. const DataUriPlugin = require("./schemes/DataUriPlugin");
  41. const FileUriPlugin = require("./schemes/FileUriPlugin");
  42. const DefaultStatsFactoryPlugin = require("./stats/DefaultStatsFactoryPlugin");
  43. const DefaultStatsPresetPlugin = require("./stats/DefaultStatsPresetPlugin");
  44. const DefaultStatsPrinterPlugin = require("./stats/DefaultStatsPrinterPlugin");
  45. const { cleverMerge } = require("./util/cleverMerge");
  46. const { NODE_MODULES_REGEXP } = require("./util/identifier");
  47. /** @import { WebpackPluginFunction } from "./webpack" */
  48. /**
  49. * @import {
  50. * WebpackOptionsNormalizedWithDefaults as WebpackOptions
  51. * } from "./config/defaults"
  52. */
  53. /** @import { WebpackOptionsInterception } from "./config/normalization" */
  54. /** @import Compiler from "./Compiler" */
  55. /** @import { InputFileSystem, IntermediateFileSystem } from "./util/fs" */
  56. const CLASS_NAME = "WebpackOptionsApply";
  57. class WebpackOptionsApply extends OptionsApply {
  58. constructor() {
  59. super();
  60. }
  61. /**
  62. * Returns options object.
  63. * @param {WebpackOptions} options options object
  64. * @param {Compiler} compiler compiler object
  65. * @param {WebpackOptionsInterception=} interception intercepted options
  66. * @returns {WebpackOptions} options object
  67. */
  68. process(options, compiler, interception) {
  69. compiler.outputPath = options.output.path;
  70. compiler.recordsInputPath = options.recordsInputPath || null;
  71. compiler.recordsOutputPath = options.recordsOutputPath || null;
  72. compiler.name = options.name;
  73. if (options.externals) {
  74. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  75. const ExternalsPlugin = require("./ExternalsPlugin");
  76. new ExternalsPlugin(options.externalsType, options.externals).apply(
  77. compiler
  78. );
  79. }
  80. if (options.externalsPresets.node) {
  81. const NodeTargetPlugin = require("./node/NodeTargetPlugin");
  82. // Some older versions of Node.js don't support all built-in modules via import, only via `require`,
  83. // but it seems like there shouldn't be a warning here since these versions are rarely used in real applications
  84. new NodeTargetPlugin(
  85. options.output.module ? "module-import" : "node-commonjs"
  86. ).apply(compiler);
  87. // Handle external CSS `@import` and `url()`
  88. if (options.experiments.css) {
  89. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  90. const ExternalsPlugin = require("./ExternalsPlugin");
  91. new ExternalsPlugin(
  92. "module",
  93. ({ request, dependencyType, contextInfo }, callback) => {
  94. if (
  95. /\.css(?:\?|$)/.test(contextInfo.issuer) &&
  96. /^(?:\/\/|https?:\/\/|#)/.test(request)
  97. ) {
  98. if (dependencyType === "url") {
  99. return callback(null, `asset ${request}`);
  100. } else if (
  101. (dependencyType === "css-import" ||
  102. dependencyType === "css-import-local-module" ||
  103. dependencyType === "css-import-global-module") &&
  104. options.experiments.css
  105. ) {
  106. return callback(null, `css-import ${request}`);
  107. }
  108. }
  109. callback();
  110. }
  111. ).apply(compiler);
  112. }
  113. }
  114. if (options.externalsPresets.nodeModules) {
  115. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  116. const ExternalsPlugin = require("./ExternalsPlugin");
  117. const type = options.output.module ? "module-import" : "node-commonjs";
  118. const preset = options.externalsPresets.nodeModules;
  119. const allowlist = preset === true ? undefined : preset.allowlist;
  120. /**
  121. * @param {string} request the request
  122. * @returns {boolean} true when the request should stay bundled
  123. */
  124. const isAllowed = (request) =>
  125. allowlist !== undefined &&
  126. allowlist.some((entry) =>
  127. entry instanceof RegExp
  128. ? entry.test(request)
  129. : typeof entry === "function"
  130. ? entry(request)
  131. : entry === request
  132. );
  133. // Relative/absolute requests are never installed packages, and `#` subpath
  134. // imports only resolve against the importing package's own `imports` field.
  135. const NEVER_EXTERNAL = /^(?:\.\.?(?:\/|$)|\/|[A-Za-z]:[\\/]|#)/;
  136. // Only JS-loadable resolutions are externalized; a package's CSS/asset
  137. // imported from JS must stay bundled so webpack can process it.
  138. const RUNTIME_LOADABLE = /\.(?:m|c)?js$|\.json$|\.node$/i;
  139. /**
  140. * @param {string} request a request or a path below a `node_modules` directory
  141. * @returns {string} the package name it belongs to
  142. */
  143. const getPackageName = (request) => {
  144. const parts = request.split("/");
  145. return request.startsWith("@") ? `${parts[0]}/${parts[1]}` : parts[0];
  146. };
  147. // `url()`/CSS `@import` references are handled by their own presets.
  148. const NON_JS_DEPENDENCY_TYPES = new Set([
  149. "url",
  150. "css-import",
  151. "css-import-local-module",
  152. "css-import-global-module"
  153. ]);
  154. new ExternalsPlugin(
  155. // Keep `require()` semantics for CommonJS deps even with module output.
  156. (dependency) =>
  157. dependency.category === "commonjs" ? "node-commonjs" : type,
  158. ({ request, context, dependencyType, getResolve }, callback) => {
  159. if (
  160. NEVER_EXTERNAL.test(request) ||
  161. NON_JS_DEPENDENCY_TYPES.has(dependencyType) ||
  162. isAllowed(request)
  163. ) {
  164. return callback();
  165. }
  166. const resolve =
  167. /** @type {(context: string, request: string, callback: (err?: Error | null, result?: string | false) => void) => void} */
  168. (getResolve());
  169. // Externalize the package only when it resolves to a runtime-loadable
  170. // file inside a node_modules directory.
  171. resolve(context, request, (err, result) => {
  172. if (
  173. err ||
  174. !result ||
  175. !NODE_MODULES_REGEXP.test(result) ||
  176. !RUNTIME_LOADABLE.test(result)
  177. ) {
  178. return callback();
  179. }
  180. // The external keeps the original request, so requests that
  181. // `resolve.alias` sends to another package must stay bundled.
  182. const resolvedPath = result.split(NODE_MODULES_REGEXP).pop();
  183. const resolvedPackageName = getPackageName(
  184. /** @type {string} */ (resolvedPath).replace(/\\/g, "/")
  185. );
  186. callback(
  187. null,
  188. resolvedPackageName === getPackageName(request) ? true : undefined
  189. );
  190. });
  191. }
  192. ).apply(compiler);
  193. }
  194. if (options.externalsPresets.deno) {
  195. const DenoTargetPlugin = require("./deno/DenoTargetPlugin");
  196. new DenoTargetPlugin().apply(compiler);
  197. }
  198. if (options.externalsPresets.bun) {
  199. const BunTargetPlugin = require("./bun/BunTargetPlugin");
  200. new BunTargetPlugin().apply(compiler);
  201. }
  202. if (options.externalsPresets.webAsync || options.externalsPresets.web) {
  203. const type = options.externalsPresets.webAsync ? "import" : "module";
  204. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  205. const ExternalsPlugin = require("./ExternalsPlugin");
  206. new ExternalsPlugin(type, ({ request, dependencyType }, callback) => {
  207. if (/^(?:\/\/|https?:\/\/|#|std:|jsr:|npm:)/.test(request)) {
  208. if (dependencyType === "url") {
  209. return callback(null, `asset ${request}`);
  210. } else if (
  211. (dependencyType === "css-import" ||
  212. dependencyType === "css-import-local-module" ||
  213. dependencyType === "css-import-global-module") &&
  214. options.experiments.css
  215. ) {
  216. return callback(null, `css-import ${request}`);
  217. } else if (/^(?:\/\/|https?:\/\/|std:|jsr:|npm:)/.test(request)) {
  218. return callback(null, `${type} ${request}`);
  219. }
  220. }
  221. callback();
  222. }).apply(compiler);
  223. }
  224. if (options.externalsPresets.electron) {
  225. // Use ESM imports only when the targeted electron version supports them
  226. const type =
  227. options.output.module && options.output.environment.module
  228. ? "module-import"
  229. : "node-commonjs";
  230. // Warn when ESM output is requested but the electron version lacks it (added in electron 28)
  231. if (options.output.module && !options.output.environment.module) {
  232. const WebpackError = require("./WebpackError");
  233. compiler.hooks.thisCompilation.tap(CLASS_NAME, (compilation) => {
  234. compilation.warnings.push(
  235. new WebpackError(
  236. "'output.module' is enabled, but the targeted electron version does not support ECMAScript modules (added in electron 28). Electron built-in modules are externalized as 'node-commonjs'."
  237. )
  238. );
  239. });
  240. }
  241. if (options.externalsPresets.electronMain) {
  242. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  243. const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
  244. new ElectronTargetPlugin("main", type).apply(compiler);
  245. }
  246. if (options.externalsPresets.electronPreload) {
  247. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  248. const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
  249. new ElectronTargetPlugin("preload", type).apply(compiler);
  250. }
  251. if (options.externalsPresets.electronRenderer) {
  252. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  253. const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
  254. new ElectronTargetPlugin("renderer", type).apply(compiler);
  255. }
  256. if (
  257. !options.externalsPresets.electronMain &&
  258. !options.externalsPresets.electronPreload &&
  259. !options.externalsPresets.electronRenderer
  260. ) {
  261. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  262. const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
  263. new ElectronTargetPlugin(undefined, type).apply(compiler);
  264. }
  265. }
  266. if (options.externalsPresets.nwjs) {
  267. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  268. const ExternalsPlugin = require("./ExternalsPlugin");
  269. new ExternalsPlugin("node-commonjs", "nw.gui").apply(compiler);
  270. }
  271. new ChunkPrefetchPreloadPlugin().apply(compiler);
  272. new ResourceHintPlugin(options.output.resourceHints).apply(compiler);
  273. if (typeof options.output.chunkFormat === "string") {
  274. switch (options.output.chunkFormat) {
  275. case "array-push": {
  276. const ArrayPushCallbackChunkFormatPlugin = require("./javascript/ArrayPushCallbackChunkFormatPlugin");
  277. new ArrayPushCallbackChunkFormatPlugin().apply(compiler);
  278. break;
  279. }
  280. case "commonjs": {
  281. const CommonJsChunkFormatPlugin = require("./javascript/CommonJsChunkFormatPlugin");
  282. new CommonJsChunkFormatPlugin().apply(compiler);
  283. break;
  284. }
  285. case "module": {
  286. const ModuleChunkFormatPlugin = require("./esm/ModuleChunkFormatPlugin");
  287. new ModuleChunkFormatPlugin().apply(compiler);
  288. break;
  289. }
  290. default:
  291. throw new Error(
  292. `Unsupported chunk format '${options.output.chunkFormat}'.`
  293. );
  294. }
  295. }
  296. const enabledChunkLoadingTypes =
  297. /** @type {NonNullable<WebpackOptions["output"]["enabledChunkLoadingTypes"]>} */
  298. (options.output.enabledChunkLoadingTypes);
  299. if (enabledChunkLoadingTypes.length > 0) {
  300. for (const type of enabledChunkLoadingTypes) {
  301. const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin");
  302. new EnableChunkLoadingPlugin(type).apply(compiler);
  303. }
  304. }
  305. const enabledWasmLoadingTypes =
  306. /** @type {NonNullable<WebpackOptions["output"]["enabledWasmLoadingTypes"]>} */
  307. (options.output.enabledWasmLoadingTypes);
  308. if (enabledWasmLoadingTypes.length > 0) {
  309. for (const type of enabledWasmLoadingTypes) {
  310. const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin");
  311. new EnableWasmLoadingPlugin(type).apply(compiler);
  312. }
  313. }
  314. const enabledLibraryTypes =
  315. /** @type {NonNullable<WebpackOptions["output"]["enabledLibraryTypes"]>} */
  316. (options.output.enabledLibraryTypes);
  317. if (enabledLibraryTypes.length > 0) {
  318. let once = true;
  319. for (const type of enabledLibraryTypes) {
  320. const EnableLibraryPlugin = require("./library/EnableLibraryPlugin");
  321. new EnableLibraryPlugin(type, {
  322. // eslint-disable-next-line no-loop-func
  323. additionalApply: () => {
  324. if (!once) return;
  325. once = false;
  326. // We rely on `exportInfo` to generate the `export statement` in certain library bundles.
  327. // Therefore, we ignore the disabling of `optimization.providedExport` and continue to apply `FlagDependencyExportsPlugin`.
  328. if (
  329. ["module", "commonjs-static", "modern-module"].includes(type) &&
  330. !options.optimization.providedExports
  331. ) {
  332. new FlagDependencyExportsPlugin().apply(compiler);
  333. }
  334. }
  335. }).apply(compiler);
  336. }
  337. }
  338. if (options.output.pathinfo) {
  339. const ModuleInfoHeaderPlugin = require("./ModuleInfoHeaderPlugin");
  340. new ModuleInfoHeaderPlugin(options.output.pathinfo !== true).apply(
  341. compiler
  342. );
  343. }
  344. if (options.output.clean) {
  345. const CleanPlugin = require("./CleanPlugin");
  346. new CleanPlugin(
  347. options.output.clean === true ? {} : options.output.clean
  348. ).apply(compiler);
  349. }
  350. if (options.dotenv) {
  351. const DotenvPlugin = require("./DotenvPlugin");
  352. new DotenvPlugin(
  353. typeof options.dotenv === "boolean" ? {} : options.dotenv
  354. ).apply(compiler);
  355. }
  356. let devtool =
  357. interception === undefined ? options.devtool : interception.devtool;
  358. devtool = Array.isArray(devtool)
  359. ? devtool
  360. : typeof devtool === "string"
  361. ? [{ type: "all", use: devtool }]
  362. : [];
  363. for (const item of devtool) {
  364. const { type, use } = item;
  365. if (use) {
  366. if (use.includes("source-map")) {
  367. const hidden = use.includes("hidden");
  368. const inline = use.includes("inline");
  369. const evalWrapped = use.includes("eval");
  370. const cheap = use.includes("cheap");
  371. const moduleMaps = use.includes("module");
  372. const noSources = use.includes("nosources");
  373. const debugIds = use.includes("debugids");
  374. const Plugin = evalWrapped
  375. ? require("./EvalSourceMapDevToolPlugin")
  376. : require("./SourceMapDevToolPlugin");
  377. const assetExt =
  378. type === "javascript"
  379. ? /\.((c|m)?js)($|\?)/i
  380. : type === "css"
  381. ? /\.(css)($|\?)/i
  382. : /\.((c|m)?js|css)($|\?)/i;
  383. new Plugin({
  384. test: evalWrapped ? undefined : assetExt,
  385. filename: inline ? null : options.output.sourceMapFilename,
  386. moduleFilenameTemplate:
  387. options.output.devtoolModuleFilenameTemplate,
  388. fallbackModuleFilenameTemplate:
  389. options.output.devtoolFallbackModuleFilenameTemplate,
  390. append: hidden ? false : undefined,
  391. module: moduleMaps ? true : !cheap,
  392. columns: !cheap,
  393. noSources,
  394. namespace: options.output.devtoolNamespace,
  395. debugIds
  396. }).apply(compiler);
  397. } else if (use.includes("eval")) {
  398. const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
  399. new EvalDevToolModulePlugin({
  400. moduleFilenameTemplate:
  401. options.output.devtoolModuleFilenameTemplate,
  402. namespace: options.output.devtoolNamespace
  403. }).apply(compiler);
  404. }
  405. }
  406. }
  407. new JavascriptModulesPlugin().apply(compiler);
  408. new JsonModulesPlugin().apply(compiler);
  409. new AssetModulesPlugin({
  410. sideEffectFree: options.experiments.futureDefaults
  411. }).apply(compiler);
  412. if (!options.experiments.outputModule) {
  413. if (options.output.module) {
  414. throw new Error(
  415. "'output.module: true' is only allowed when 'experiments.outputModule' is enabled"
  416. );
  417. }
  418. if (options.output.enabledLibraryTypes.includes("module")) {
  419. throw new Error(
  420. "library type \"module\" is only allowed when 'experiments.outputModule' is enabled"
  421. );
  422. }
  423. if (options.output.enabledLibraryTypes.includes("modern-module")) {
  424. throw new Error(
  425. "library type \"modern-module\" is only allowed when 'experiments.outputModule' is enabled"
  426. );
  427. }
  428. if (
  429. options.externalsType === "module" ||
  430. options.externalsType === "module-import"
  431. ) {
  432. throw new Error(
  433. "'externalsType: \"module\"' is only allowed when 'experiments.outputModule' is enabled"
  434. );
  435. }
  436. }
  437. if (options.output.module) {
  438. // Analyzable output is ESM output, so this is every build that can reserve a name.
  439. const RuntimeTemplate = require("./RuntimeTemplate");
  440. RuntimeTemplate.fillReservedNames(compiler);
  441. }
  442. if (options.experiments.syncWebAssembly) {
  443. const WebAssemblyModulesPlugin = require("./wasm-sync/WebAssemblyModulesPlugin");
  444. new WebAssemblyModulesPlugin({
  445. mangleImports: options.optimization.mangleWasmImports
  446. }).apply(compiler);
  447. }
  448. if (options.experiments.asyncWebAssembly) {
  449. const AsyncWebAssemblyModulesPlugin = require("./wasm-async/AsyncWebAssemblyModulesPlugin");
  450. new AsyncWebAssemblyModulesPlugin({
  451. mangleImports: options.optimization.mangleWasmImports
  452. }).apply(compiler);
  453. }
  454. if (options.experiments.css) {
  455. const CssModulesPlugin = require("./css/CssModulesPlugin");
  456. new CssModulesPlugin().apply(compiler);
  457. }
  458. if (options.experiments.html) {
  459. const HtmlModulesPlugin = require("./html/HtmlModulesPlugin");
  460. new HtmlModulesPlugin().apply(compiler);
  461. }
  462. if (options.experiments.typescript) {
  463. const TypeScriptPlugin = require("./typescript/TypeScriptPlugin");
  464. new TypeScriptPlugin().apply(compiler);
  465. }
  466. if (options.experiments.lazyCompilation) {
  467. const LazyCompilationPlugin = require("./hmr/LazyCompilationPlugin");
  468. const lazyOptions =
  469. typeof options.experiments.lazyCompilation === "object"
  470. ? options.experiments.lazyCompilation
  471. : {};
  472. const isUniversalTarget =
  473. options.output.module &&
  474. compiler.platform.node === null &&
  475. compiler.platform.web === null;
  476. if (isUniversalTarget) {
  477. const emitter = require.resolve("../hot/emitter-event-target.js");
  478. const NormalModuleReplacementPlugin = require("./NormalModuleReplacementPlugin");
  479. // Override emitter that using `EventEmitter` to `EventTarget`
  480. // TODO webpack 6 - migrate to `EventTarget` by default
  481. new NormalModuleReplacementPlugin(/emitter(\.js)?$/, (result) => {
  482. if (
  483. /webpack[/\\]hot|webpack-dev-server[/\\]client|webpack-hot-middleware[/\\]client/.test(
  484. result.context
  485. )
  486. ) {
  487. result.request = emitter;
  488. }
  489. return result;
  490. }).apply(compiler);
  491. }
  492. const backend = require.resolve(
  493. isUniversalTarget
  494. ? "../hot/lazy-compilation-universal.js"
  495. : `../hot/lazy-compilation-${
  496. options.externalsPresets.node ? "node" : "web"
  497. }.js`
  498. );
  499. new LazyCompilationPlugin({
  500. backend:
  501. typeof lazyOptions.backend === "function"
  502. ? lazyOptions.backend
  503. : require("./hmr/lazyCompilationBackend")({
  504. ...lazyOptions.backend,
  505. client:
  506. (lazyOptions.backend && lazyOptions.backend.client) || backend
  507. }),
  508. entries: !lazyOptions || lazyOptions.entries !== false,
  509. imports: !lazyOptions || lazyOptions.imports !== false,
  510. test: (lazyOptions && lazyOptions.test) || undefined
  511. }).apply(compiler);
  512. }
  513. if (options.experiments.buildHttp) {
  514. const HttpUriPlugin = require("./schemes/HttpUriPlugin");
  515. const httpOptions = options.experiments.buildHttp;
  516. new HttpUriPlugin(httpOptions).apply(compiler);
  517. }
  518. new EntryOptionPlugin().apply(compiler);
  519. compiler.hooks.entryOption.call(options.context, options.entry);
  520. new RuntimePlugin().apply(compiler);
  521. new InferAsyncModulesPlugin().apply(compiler);
  522. new DataUriPlugin().apply(compiler);
  523. new FileUriPlugin().apply(compiler);
  524. new CompatibilityPlugin().apply(compiler);
  525. new HarmonyModulesPlugin({
  526. deferImport: options.experiments.deferImport
  527. }).apply(compiler);
  528. if (options.amd !== false) {
  529. const AMDPlugin = require("./dependencies/AMDPlugin");
  530. const RequireJsStuffPlugin = require("./dependencies/RequireJsStuffPlugin");
  531. new AMDPlugin(options.amd || {}).apply(compiler);
  532. new RequireJsStuffPlugin().apply(compiler);
  533. }
  534. new CommonJsPlugin().apply(compiler);
  535. new LoaderPlugin().apply(compiler);
  536. new NodeStuffPlugin({
  537. global: options.node ? options.node.global : false,
  538. __dirname: options.node ? options.node.__dirname : false,
  539. __filename: options.node ? options.node.__filename : false
  540. }).apply(compiler);
  541. new APIPlugin().apply(compiler);
  542. new ExportsInfoApiPlugin().apply(compiler);
  543. new WebpackIsIncludedPlugin().apply(compiler);
  544. new ConstPlugin().apply(compiler);
  545. new UseStrictPlugin().apply(compiler);
  546. new RequireIncludePlugin().apply(compiler);
  547. new RequireEnsurePlugin().apply(compiler);
  548. new RequireContextPlugin().apply(compiler);
  549. new ImportPlugin().apply(compiler);
  550. new ImportMetaContextPlugin().apply(compiler);
  551. new SystemPlugin().apply(compiler);
  552. new ImportMetaPlugin().apply(compiler);
  553. new URLPlugin().apply(compiler);
  554. new WorkerAndWorkletPlugin(
  555. options.output.workerChunkLoading,
  556. options.output.workerWasmLoading,
  557. options.output.module,
  558. options.output.workerPublicPath,
  559. options.experiments.futureDefaults
  560. ).apply(compiler);
  561. new DefaultStatsFactoryPlugin().apply(compiler);
  562. new DefaultStatsPresetPlugin().apply(compiler);
  563. new DefaultStatsPrinterPlugin().apply(compiler);
  564. new JavascriptMetaInfoPlugin().apply(compiler);
  565. if (typeof options.mode !== "string") {
  566. const WarnNoModeSetPlugin = require("./WarnNoModeSetPlugin");
  567. new WarnNoModeSetPlugin().apply(compiler);
  568. }
  569. const EnsureChunkConditionsPlugin = require("./optimize/EnsureChunkConditionsPlugin");
  570. new EnsureChunkConditionsPlugin().apply(compiler);
  571. if (options.optimization.removeAvailableModules) {
  572. const RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin");
  573. new RemoveParentModulesPlugin().apply(compiler);
  574. }
  575. if (options.optimization.removeEmptyChunks) {
  576. const RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin");
  577. new RemoveEmptyChunksPlugin().apply(compiler);
  578. }
  579. if (options.optimization.mergeDuplicateChunks) {
  580. const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");
  581. new MergeDuplicateChunksPlugin().apply(compiler);
  582. }
  583. if (options.optimization.flagIncludedChunks) {
  584. const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");
  585. new FlagIncludedChunksPlugin().apply(compiler);
  586. }
  587. if (options.optimization.sideEffects) {
  588. const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin");
  589. new SideEffectsFlagPlugin(
  590. options.optimization.sideEffects === true
  591. ).apply(compiler);
  592. }
  593. if (options.optimization.providedExports) {
  594. new FlagDependencyExportsPlugin().apply(compiler);
  595. }
  596. if (options.optimization.usedExports) {
  597. const FlagDependencyUsagePlugin = require("./FlagDependencyUsagePlugin");
  598. new FlagDependencyUsagePlugin(
  599. options.optimization.usedExports === "global",
  600. // Keep an escaping module's exports mangleable when mangling is on.
  601. Boolean(options.optimization.mangleExports)
  602. ).apply(compiler);
  603. }
  604. if (options.optimization.innerGraph) {
  605. const InnerGraphPlugin = require("./optimize/InnerGraphPlugin");
  606. new InnerGraphPlugin().apply(compiler);
  607. }
  608. const circularHints =
  609. options.performance && options.performance.circularDependencies
  610. ? options.performance.hints
  611. : false;
  612. if (options.mode === "production" || circularHints) {
  613. const CircularModulesPlugin = require("./CircularModulesPlugin");
  614. new CircularModulesPlugin({ hints: circularHints }).apply(compiler);
  615. }
  616. const ConstExportsPlugin = require("./optimize/ConstExportsPlugin");
  617. new ConstExportsPlugin({
  618. inlineExports: options.optimization.inlineExports
  619. }).apply(compiler);
  620. if (options.optimization.mangleExports) {
  621. const MangleExportsPlugin = require("./optimize/MangleExportsPlugin");
  622. new MangleExportsPlugin(
  623. options.optimization.mangleExports !== "size"
  624. ).apply(compiler);
  625. }
  626. if (options.optimization.concatenateModules) {
  627. const ModuleConcatenationPlugin = require("./optimize/ModuleConcatenationPlugin");
  628. new ModuleConcatenationPlugin().apply(compiler);
  629. }
  630. if (options.optimization.splitChunks) {
  631. const SplitChunksPlugin = require("./optimize/SplitChunksPlugin");
  632. new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler);
  633. }
  634. if (options.optimization.runtimeChunk) {
  635. const RuntimeChunkPlugin = require("./optimize/RuntimeChunkPlugin");
  636. new RuntimeChunkPlugin(options.optimization.runtimeChunk).apply(compiler);
  637. }
  638. if (!options.optimization.emitOnErrors) {
  639. const NoEmitOnErrorsPlugin = require("./NoEmitOnErrorsPlugin");
  640. new NoEmitOnErrorsPlugin().apply(compiler);
  641. }
  642. if (options.optimization.realContentHash) {
  643. const RealContentHashPlugin = require("./optimize/RealContentHashPlugin");
  644. new RealContentHashPlugin({
  645. hashFunction:
  646. /** @type {NonNullable<WebpackOptions["output"]["hashFunction"]>} */
  647. (options.output.hashFunction),
  648. hashDigest:
  649. /** @type {NonNullable<WebpackOptions["output"]["hashDigest"]>} */
  650. (options.output.hashDigest)
  651. }).apply(compiler);
  652. }
  653. if (options.optimization.checkWasmTypes) {
  654. const WasmFinalizeExportsPlugin = require("./wasm-sync/WasmFinalizeExportsPlugin");
  655. new WasmFinalizeExportsPlugin().apply(compiler);
  656. }
  657. const moduleIds = options.optimization.moduleIds;
  658. if (moduleIds) {
  659. switch (moduleIds) {
  660. case "natural": {
  661. const NaturalModuleIdsPlugin = require("./ids/NaturalModuleIdsPlugin");
  662. new NaturalModuleIdsPlugin().apply(compiler);
  663. break;
  664. }
  665. case "named": {
  666. const NamedModuleIdsPlugin = require("./ids/NamedModuleIdsPlugin");
  667. new NamedModuleIdsPlugin().apply(compiler);
  668. break;
  669. }
  670. case "hashed": {
  671. const WarnDeprecatedOptionPlugin = require("./WarnDeprecatedOptionPlugin");
  672. const HashedModuleIdsPlugin = require("./ids/HashedModuleIdsPlugin");
  673. new WarnDeprecatedOptionPlugin(
  674. "optimization.moduleIds",
  675. "hashed",
  676. "deterministic"
  677. ).apply(compiler);
  678. new HashedModuleIdsPlugin({
  679. hashFunction: options.output.hashFunction
  680. }).apply(compiler);
  681. break;
  682. }
  683. case "deterministic": {
  684. const DeterministicModuleIdsPlugin = require("./ids/DeterministicModuleIdsPlugin");
  685. new DeterministicModuleIdsPlugin().apply(compiler);
  686. break;
  687. }
  688. case "size": {
  689. const OccurrenceModuleIdsPlugin = require("./ids/OccurrenceModuleIdsPlugin");
  690. new OccurrenceModuleIdsPlugin({
  691. prioritiseInitial: true
  692. }).apply(compiler);
  693. break;
  694. }
  695. default:
  696. throw new Error(
  697. `webpack bug: moduleIds: ${moduleIds} is not implemented`
  698. );
  699. }
  700. }
  701. const chunkIds = options.optimization.chunkIds;
  702. if (chunkIds) {
  703. switch (chunkIds) {
  704. case "natural": {
  705. const NaturalChunkIdsPlugin = require("./ids/NaturalChunkIdsPlugin");
  706. new NaturalChunkIdsPlugin().apply(compiler);
  707. break;
  708. }
  709. case "named": {
  710. const NamedChunkIdsPlugin = require("./ids/NamedChunkIdsPlugin");
  711. new NamedChunkIdsPlugin().apply(compiler);
  712. break;
  713. }
  714. case "deterministic": {
  715. const DeterministicChunkIdsPlugin = require("./ids/DeterministicChunkIdsPlugin");
  716. new DeterministicChunkIdsPlugin().apply(compiler);
  717. break;
  718. }
  719. case "size": {
  720. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  721. const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");
  722. new OccurrenceChunkIdsPlugin({
  723. prioritiseInitial: true
  724. }).apply(compiler);
  725. break;
  726. }
  727. case "total-size": {
  728. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  729. const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");
  730. new OccurrenceChunkIdsPlugin({
  731. prioritiseInitial: false
  732. }).apply(compiler);
  733. break;
  734. }
  735. default:
  736. throw new Error(
  737. `webpack bug: chunkIds: ${chunkIds} is not implemented`
  738. );
  739. }
  740. }
  741. if (options.optimization.nodeEnv) {
  742. const DefinePlugin = require("./DefinePlugin");
  743. const defValue = JSON.stringify(options.optimization.nodeEnv);
  744. const development = options.mode === "development";
  745. // SSR = server-only build (node, not browser); a universal (node+browser) target is null here, so not SSR.
  746. const ssr =
  747. compiler.platform.node === true && compiler.platform.browser !== true;
  748. const { publicPath } = options.output;
  749. // Vite-compatible base URL; fall back to "/" for runtime ("auto") or empty publicPath.
  750. const baseUrl =
  751. typeof publicPath === "string" &&
  752. publicPath !== "auto" &&
  753. publicPath !== ""
  754. ? publicPath
  755. : "/";
  756. // Marked internal: these keys are webpack's, so `performance.unusedDefines`
  757. // must not report them against the user.
  758. DefinePlugin.markInternal(
  759. new DefinePlugin({
  760. "process.env.NODE_ENV": defValue,
  761. "import.meta.env.NODE_ENV": defValue,
  762. "import.meta.env.MODE": defValue,
  763. "import.meta.env.DEV": JSON.stringify(development),
  764. "import.meta.env.PROD": JSON.stringify(!development),
  765. "import.meta.env.SSR": JSON.stringify(ssr),
  766. "import.meta.env.BASE_URL": JSON.stringify(baseUrl)
  767. })
  768. ).apply(compiler);
  769. }
  770. if (options.optimization.minimize) {
  771. for (const minimizer of options.optimization.minimizer) {
  772. if (typeof minimizer === "function") {
  773. /** @type {WebpackPluginFunction} */
  774. (minimizer).call(compiler, compiler);
  775. } else if (minimizer !== "..." && minimizer) {
  776. minimizer.apply(compiler);
  777. }
  778. }
  779. }
  780. if (options.performance) {
  781. if (options.performance.hotspots) {
  782. const HotspotsPlugin = require("./performance/HotspotsPlugin");
  783. new HotspotsPlugin(options.performance).apply(compiler);
  784. }
  785. const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin");
  786. new SizeLimitsPlugin(options.performance).apply(compiler);
  787. if (options.performance.duplicatePackages) {
  788. const DuplicatePackagesPlugin = require("./performance/DuplicatePackagesPlugin");
  789. new DuplicatePackagesPlugin(options.performance).apply(compiler);
  790. }
  791. if (options.performance.cacheEffectiveness) {
  792. const CacheEffectivenessPlugin = require("./performance/CacheEffectivenessPlugin");
  793. new CacheEffectivenessPlugin(options.performance).apply(compiler);
  794. }
  795. if (options.performance.duplicateModules) {
  796. const DuplicateModulesPlugin = require("./performance/DuplicateModulesPlugin");
  797. new DuplicateModulesPlugin(options.performance).apply(compiler);
  798. }
  799. if (options.performance.redundantDynamicImports) {
  800. const RedundantDynamicImportsPlugin = require("./performance/RedundantDynamicImportsPlugin");
  801. new RedundantDynamicImportsPlugin(options.performance).apply(compiler);
  802. }
  803. if (options.performance.entrypointOverlap) {
  804. const EntrypointOverlapPlugin = require("./performance/EntrypointOverlapPlugin");
  805. new EntrypointOverlapPlugin(options.performance).apply(compiler);
  806. }
  807. if (options.performance.largeModules) {
  808. const LargeModulesPlugin = require("./performance/LargeModulesPlugin");
  809. new LargeModulesPlugin(options.performance).apply(compiler);
  810. }
  811. if (options.performance.asyncChunkWaterfalls) {
  812. const AsyncChunkWaterfallsPlugin = require("./performance/AsyncChunkWaterfallsPlugin");
  813. new AsyncChunkWaterfallsPlugin(options.performance).apply(compiler);
  814. }
  815. if (options.performance.broadContexts) {
  816. const BroadContextsPlugin = require("./performance/BroadContextsPlugin");
  817. new BroadContextsPlugin(options.performance).apply(compiler);
  818. }
  819. if (options.performance.legacyJavascript) {
  820. const LegacyJavascriptPlugin = require("./performance/LegacyJavascriptPlugin");
  821. new LegacyJavascriptPlugin(options.performance).apply(compiler);
  822. }
  823. if (options.performance.mixedExports) {
  824. const MixedExportsPlugin = require("./performance/MixedExportsPlugin");
  825. new MixedExportsPlugin(options.performance).apply(compiler);
  826. }
  827. if (options.performance.pureAnnotations) {
  828. const PureAnnotationsPlugin = require("./performance/PureAnnotationsPlugin");
  829. new PureAnnotationsPlugin(options.performance).apply(compiler);
  830. }
  831. if (options.performance.evalUsage) {
  832. const EvalUsagePlugin = require("./performance/EvalUsagePlugin");
  833. new EvalUsagePlugin(options.performance).apply(compiler);
  834. }
  835. if (options.performance.tinyChunks) {
  836. const TinyChunksPlugin = require("./performance/TinyChunksPlugin");
  837. new TinyChunksPlugin(options.performance).apply(compiler);
  838. }
  839. if (options.performance.topLevelThis) {
  840. const TopLevelThisPlugin = require("./performance/TopLevelThisPlugin");
  841. new TopLevelThisPlugin(options.performance).apply(compiler);
  842. }
  843. if (options.performance.unsplitVendors) {
  844. const UnsplitVendorsPlugin = require("./performance/UnsplitVendorsPlugin");
  845. new UnsplitVendorsPlugin(options.performance).apply(compiler);
  846. }
  847. if (options.performance.splitChunksCapped) {
  848. const SplitChunksCappedPlugin = require("./performance/SplitChunksCappedPlugin");
  849. new SplitChunksCappedPlugin(options.performance).apply(compiler);
  850. }
  851. if (options.performance.dynamicExports) {
  852. const DynamicExportsPlugin = require("./performance/DynamicExportsPlugin");
  853. new DynamicExportsPlugin(options.performance).apply(compiler);
  854. }
  855. if (options.performance.embeddedSourceMaps) {
  856. const EmbeddedSourceMapsPlugin = require("./performance/EmbeddedSourceMapsPlugin");
  857. new EmbeddedSourceMapsPlugin(options.performance).apply(compiler);
  858. }
  859. if (options.performance.inlinedAssets) {
  860. const InlinedAssetsPlugin = require("./performance/InlinedAssetsPlugin");
  861. new InlinedAssetsPlugin(options.performance).apply(compiler);
  862. }
  863. if (options.performance.missingSideEffects) {
  864. const MissingSideEffectsPlugin = require("./performance/MissingSideEffectsPlugin");
  865. new MissingSideEffectsPlugin(options.performance).apply(compiler);
  866. }
  867. if (options.performance.scopeHoistingBailouts) {
  868. const ScopeHoistingBailoutsPlugin = require("./performance/ScopeHoistingBailoutsPlugin");
  869. new ScopeHoistingBailoutsPlugin(options.performance).apply(compiler);
  870. }
  871. if (options.performance.unusedReexports) {
  872. const UnusedReexportsPlugin = require("./performance/UnusedReexportsPlugin");
  873. new UnusedReexportsPlugin(options.performance).apply(compiler);
  874. }
  875. // Deliberately not gated on `hints`, like `unusedRules` below: a rule
  876. // that only matches on one OS is a configuration mistake, not a size.
  877. if (options.performance.osDependentRules) {
  878. const OsDependentRuleWarningPlugin = require("./performance/OsDependentRuleWarningPlugin");
  879. new OsDependentRuleWarningPlugin(options.performance).apply(compiler);
  880. }
  881. // Deliberately not gated on `hints`: an alias nothing matches is a
  882. // configuration mistake, not a size.
  883. if (options.performance.unusedAliases) {
  884. const UnusedAliasesPlugin = require("./performance/UnusedAliasesPlugin");
  885. new UnusedAliasesPlugin(options.performance).apply(compiler);
  886. }
  887. // Deliberately not gated on `hints`: a key nothing reads is a
  888. // configuration mistake, not a size.
  889. if (options.performance.unusedDefines) {
  890. const UnusedDefinesPlugin = require("./performance/UnusedDefinesPlugin");
  891. new UnusedDefinesPlugin(options.performance).apply(compiler);
  892. }
  893. // Deliberately not gated on `hints`: a misspelled external gets bundled
  894. // instead, which no size limit would explain.
  895. if (options.performance.unusedExternals) {
  896. const UnusedExternalsPlugin = require("./performance/UnusedExternalsPlugin");
  897. new UnusedExternalsPlugin(options.performance).apply(compiler);
  898. }
  899. // Deliberately not gated on `hints`: asking for both directives on one
  900. // import is a configuration mistake, not a size.
  901. if (options.performance.conflictingResourceHints) {
  902. const ConflictingResourceHintsPlugin = require("./performance/ConflictingResourceHintsPlugin");
  903. new ConflictingResourceHintsPlugin(options.performance).apply(compiler);
  904. }
  905. // Deliberately not gated on `hints`: a dead rule is a configuration
  906. // mistake worth reporting even where size hints are off.
  907. if (options.performance.unusedRules) {
  908. const UnusedRuleWarningPlugin = require("./performance/UnusedRuleWarningPlugin");
  909. new UnusedRuleWarningPlugin(options.performance).apply(compiler);
  910. }
  911. }
  912. new TemplatedPathPlugin().apply(compiler);
  913. new RecordIdsPlugin({
  914. portableIds: options.optimization.portableRecords
  915. }).apply(compiler);
  916. new WarnCaseSensitiveModulesPlugin().apply(compiler);
  917. const AddManagedPathsPlugin = require("./cache/AddManagedPathsPlugin");
  918. new AddManagedPathsPlugin(
  919. /** @type {NonNullable<WebpackOptions["snapshot"]["managedPaths"]>} */
  920. (options.snapshot.managedPaths),
  921. /** @type {NonNullable<WebpackOptions["snapshot"]["managedPaths"]>} */
  922. (options.snapshot.immutablePaths),
  923. /** @type {NonNullable<WebpackOptions["snapshot"]["managedPaths"]>} */
  924. (options.snapshot.unmanagedPaths)
  925. ).apply(compiler);
  926. if (options.cache && typeof options.cache === "object") {
  927. const cacheOptions = options.cache;
  928. switch (cacheOptions.type) {
  929. case "memory": {
  930. if (Number.isFinite(cacheOptions.maxGenerations)) {
  931. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  932. const MemoryWithGcCachePlugin = require("./cache/MemoryWithGcCachePlugin");
  933. new MemoryWithGcCachePlugin({
  934. maxGenerations:
  935. /** @type {number} */
  936. (cacheOptions.maxGenerations)
  937. }).apply(compiler);
  938. } else {
  939. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  940. const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
  941. new MemoryCachePlugin().apply(compiler);
  942. }
  943. if (cacheOptions.cacheUnaffected) {
  944. if (!options.experiments.cacheUnaffected) {
  945. throw new Error(
  946. "'cache.cacheUnaffected: true' is only allowed when 'experiments.cacheUnaffected' is enabled"
  947. );
  948. }
  949. compiler.moduleMemCaches = new Map();
  950. }
  951. break;
  952. }
  953. case "filesystem": {
  954. const AddBuildDependenciesPlugin = require("./cache/AddBuildDependenciesPlugin");
  955. for (const key in cacheOptions.buildDependencies) {
  956. const list = cacheOptions.buildDependencies[key];
  957. new AddBuildDependenciesPlugin(list).apply(compiler);
  958. }
  959. if (!Number.isFinite(cacheOptions.maxMemoryGenerations)) {
  960. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  961. const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
  962. new MemoryCachePlugin().apply(compiler);
  963. } else if (cacheOptions.maxMemoryGenerations !== 0) {
  964. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  965. const MemoryWithGcCachePlugin = require("./cache/MemoryWithGcCachePlugin");
  966. new MemoryWithGcCachePlugin({
  967. maxGenerations:
  968. /** @type {number} */
  969. (cacheOptions.maxMemoryGenerations)
  970. }).apply(compiler);
  971. }
  972. if (cacheOptions.memoryCacheUnaffected) {
  973. if (!options.experiments.cacheUnaffected) {
  974. throw new Error(
  975. "'cache.memoryCacheUnaffected: true' is only allowed when 'experiments.cacheUnaffected' is enabled"
  976. );
  977. }
  978. compiler.moduleMemCaches = new Map();
  979. }
  980. switch (cacheOptions.store) {
  981. case "pack": {
  982. const IdleFileCachePlugin = require("./cache/IdleFileCachePlugin");
  983. const PackFileCacheStrategy = require("./cache/PackFileCacheStrategy");
  984. new IdleFileCachePlugin(
  985. new PackFileCacheStrategy({
  986. compiler,
  987. fs:
  988. /** @type {IntermediateFileSystem} */
  989. (compiler.intermediateFileSystem),
  990. context: options.context,
  991. cacheLocation:
  992. /** @type {string} */
  993. (cacheOptions.cacheLocation),
  994. version: /** @type {string} */ (cacheOptions.version),
  995. logger: compiler.getInfrastructureLogger(
  996. "webpack.cache.PackFileCacheStrategy"
  997. ),
  998. snapshot: options.snapshot,
  999. maxAge: /** @type {number} */ (cacheOptions.maxAge),
  1000. profile: cacheOptions.profile,
  1001. allowCollectingMemory: cacheOptions.allowCollectingMemory,
  1002. compression: cacheOptions.compression,
  1003. readonly: cacheOptions.readonly
  1004. }),
  1005. /** @type {number} */
  1006. (cacheOptions.idleTimeout),
  1007. /** @type {number} */
  1008. (cacheOptions.idleTimeoutForInitialStore),
  1009. /** @type {number} */
  1010. (cacheOptions.idleTimeoutAfterLargeChanges)
  1011. ).apply(compiler);
  1012. break;
  1013. }
  1014. default:
  1015. throw new Error("Unhandled value for cache.store");
  1016. }
  1017. break;
  1018. }
  1019. default:
  1020. // @ts-expect-error Property 'type' does not exist on type 'never'. ts(2339)
  1021. throw new Error(`Unknown cache type ${cacheOptions.type}`);
  1022. }
  1023. }
  1024. new ResolverCachePlugin().apply(compiler);
  1025. if (options.ignoreWarnings && options.ignoreWarnings.length > 0) {
  1026. const IgnoreWarningsPlugin = require("./IgnoreWarningsPlugin");
  1027. new IgnoreWarningsPlugin(options.ignoreWarnings).apply(compiler);
  1028. }
  1029. compiler.hooks.afterPlugins.call(compiler);
  1030. if (!compiler.inputFileSystem) {
  1031. throw new Error("No input filesystem provided");
  1032. }
  1033. compiler.resolverFactory.hooks.resolveOptions
  1034. .for("normal")
  1035. .tap(CLASS_NAME, (resolveOptions) => {
  1036. resolveOptions = cleverMerge(options.resolve, resolveOptions);
  1037. resolveOptions.fileSystem =
  1038. /** @type {InputFileSystem} */
  1039. (compiler.inputFileSystem);
  1040. return resolveOptions;
  1041. });
  1042. compiler.resolverFactory.hooks.resolveOptions
  1043. .for("context")
  1044. .tap(CLASS_NAME, (resolveOptions) => {
  1045. resolveOptions = cleverMerge(options.resolve, resolveOptions);
  1046. resolveOptions.fileSystem =
  1047. /** @type {InputFileSystem} */
  1048. (compiler.inputFileSystem);
  1049. resolveOptions.resolveToContext = true;
  1050. return resolveOptions;
  1051. });
  1052. compiler.resolverFactory.hooks.resolveOptions
  1053. .for("loader")
  1054. .tap(CLASS_NAME, (resolveOptions) => {
  1055. resolveOptions = cleverMerge(options.resolveLoader, resolveOptions);
  1056. resolveOptions.fileSystem =
  1057. /** @type {InputFileSystem} */
  1058. (compiler.inputFileSystem);
  1059. return resolveOptions;
  1060. });
  1061. compiler.hooks.afterResolvers.call(compiler);
  1062. return options;
  1063. }
  1064. }
  1065. module.exports = WebpackOptionsApply;