WebpackOptionsApply.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const OptionsApply = require("./OptionsApply");
  7. const AssetModulesPlugin = require("./asset/AssetModulesPlugin");
  8. const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
  9. const JsonModulesPlugin = require("./json/JsonModulesPlugin");
  10. const ChunkPrefetchPreloadPlugin = require("./prefetch/ChunkPrefetchPreloadPlugin");
  11. const EntryOptionPlugin = require("./EntryOptionPlugin");
  12. const RecordIdsPlugin = require("./RecordIdsPlugin");
  13. const RuntimePlugin = require("./RuntimePlugin");
  14. const APIPlugin = require("./APIPlugin");
  15. const CompatibilityPlugin = require("./CompatibilityPlugin");
  16. const ConstPlugin = require("./ConstPlugin");
  17. const ExportsInfoApiPlugin = require("./ExportsInfoApiPlugin");
  18. const WebpackIsIncludedPlugin = require("./WebpackIsIncludedPlugin");
  19. const TemplatedPathPlugin = require("./TemplatedPathPlugin");
  20. const UseStrictPlugin = require("./UseStrictPlugin");
  21. const WarnCaseSensitiveModulesPlugin = require("./WarnCaseSensitiveModulesPlugin");
  22. const DataUriPlugin = require("./schemes/DataUriPlugin");
  23. const FileUriPlugin = require("./schemes/FileUriPlugin");
  24. const ResolverCachePlugin = require("./cache/ResolverCachePlugin");
  25. const CommonJsPlugin = require("./dependencies/CommonJsPlugin");
  26. const HarmonyModulesPlugin = require("./dependencies/HarmonyModulesPlugin");
  27. const ImportMetaContextPlugin = require("./dependencies/ImportMetaContextPlugin");
  28. const ImportMetaPlugin = require("./dependencies/ImportMetaPlugin");
  29. const ImportPlugin = require("./dependencies/ImportPlugin");
  30. const LoaderPlugin = require("./dependencies/LoaderPlugin");
  31. const RequireContextPlugin = require("./dependencies/RequireContextPlugin");
  32. const RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
  33. const RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");
  34. const SystemPlugin = require("./dependencies/SystemPlugin");
  35. const URLPlugin = require("./dependencies/URLPlugin");
  36. const WorkerPlugin = require("./dependencies/WorkerPlugin");
  37. const InferAsyncModulesPlugin = require("./async-modules/InferAsyncModulesPlugin");
  38. const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");
  39. const JavascriptMetaInfoPlugin = require("./JavascriptMetaInfoPlugin");
  40. const DefaultStatsFactoryPlugin = require("./stats/DefaultStatsFactoryPlugin");
  41. const DefaultStatsPresetPlugin = require("./stats/DefaultStatsPresetPlugin");
  42. const DefaultStatsPrinterPlugin = require("./stats/DefaultStatsPrinterPlugin");
  43. const { cleverMerge } = require("./util/cleverMerge");
  44. /** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
  45. /** @typedef {import("../declarations/WebpackOptions").WebpackPluginFunction} WebpackPluginFunction */
  46. /** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */
  47. /** @typedef {import("./Compiler")} Compiler */
  48. /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
  49. /** @typedef {import("./util/fs").IntermediateFileSystem} IntermediateFileSystem */
  50. const CLASS_NAME = "WebpackOptionsApply";
  51. class WebpackOptionsApply extends OptionsApply {
  52. constructor() {
  53. super();
  54. }
  55. /**
  56. * @param {WebpackOptions} options options object
  57. * @param {Compiler} compiler compiler object
  58. * @returns {WebpackOptions} options object
  59. */
  60. process(options, compiler) {
  61. compiler.outputPath = /** @type {string} */ (options.output.path);
  62. compiler.recordsInputPath = options.recordsInputPath || null;
  63. compiler.recordsOutputPath = options.recordsOutputPath || null;
  64. compiler.name = options.name;
  65. if (options.externals) {
  66. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  67. const ExternalsPlugin = require("./ExternalsPlugin");
  68. new ExternalsPlugin(options.externalsType, options.externals).apply(
  69. compiler
  70. );
  71. }
  72. if (options.externalsPresets.node) {
  73. const NodeTargetPlugin = require("./node/NodeTargetPlugin");
  74. new NodeTargetPlugin().apply(compiler);
  75. }
  76. if (options.externalsPresets.electronMain) {
  77. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  78. const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
  79. new ElectronTargetPlugin("main").apply(compiler);
  80. }
  81. if (options.externalsPresets.electronPreload) {
  82. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  83. const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
  84. new ElectronTargetPlugin("preload").apply(compiler);
  85. }
  86. if (options.externalsPresets.electronRenderer) {
  87. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  88. const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
  89. new ElectronTargetPlugin("renderer").apply(compiler);
  90. }
  91. if (
  92. options.externalsPresets.electron &&
  93. !options.externalsPresets.electronMain &&
  94. !options.externalsPresets.electronPreload &&
  95. !options.externalsPresets.electronRenderer
  96. ) {
  97. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  98. const ElectronTargetPlugin = require("./electron/ElectronTargetPlugin");
  99. new ElectronTargetPlugin().apply(compiler);
  100. }
  101. if (options.externalsPresets.nwjs) {
  102. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  103. const ExternalsPlugin = require("./ExternalsPlugin");
  104. new ExternalsPlugin("node-commonjs", "nw.gui").apply(compiler);
  105. }
  106. if (options.externalsPresets.webAsync) {
  107. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  108. const ExternalsPlugin = require("./ExternalsPlugin");
  109. new ExternalsPlugin("import", ({ request, dependencyType }, callback) => {
  110. if (dependencyType === "url") {
  111. if (/^(\/\/|https?:\/\/|#)/.test(/** @type {string} */ (request)))
  112. return callback(null, `asset ${request}`);
  113. } else if (options.experiments.css && dependencyType === "css-import") {
  114. if (/^(\/\/|https?:\/\/|#)/.test(/** @type {string} */ (request)))
  115. return callback(null, `css-import ${request}`);
  116. } else if (
  117. options.experiments.css &&
  118. /^(\/\/|https?:\/\/|std:)/.test(/** @type {string} */ (request))
  119. ) {
  120. if (/^\.css(\?|$)/.test(/** @type {string} */ (request)))
  121. return callback(null, `css-import ${request}`);
  122. return callback(null, `import ${request}`);
  123. }
  124. callback();
  125. }).apply(compiler);
  126. } else if (options.externalsPresets.web) {
  127. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  128. const ExternalsPlugin = require("./ExternalsPlugin");
  129. new ExternalsPlugin("module", ({ request, dependencyType }, callback) => {
  130. if (dependencyType === "url") {
  131. if (/^(\/\/|https?:\/\/|#)/.test(/** @type {string} */ (request)))
  132. return callback(null, `asset ${request}`);
  133. } else if (options.experiments.css && dependencyType === "css-import") {
  134. if (/^(\/\/|https?:\/\/|#)/.test(/** @type {string} */ (request)))
  135. return callback(null, `css-import ${request}`);
  136. } else if (
  137. /^(\/\/|https?:\/\/|std:)/.test(/** @type {string} */ (request))
  138. ) {
  139. if (
  140. options.experiments.css &&
  141. /^\.css((\?)|$)/.test(/** @type {string} */ (request))
  142. )
  143. return callback(null, `css-import ${request}`);
  144. return callback(null, `module ${request}`);
  145. }
  146. callback();
  147. }).apply(compiler);
  148. } else if (options.externalsPresets.node && options.experiments.css) {
  149. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  150. const ExternalsPlugin = require("./ExternalsPlugin");
  151. new ExternalsPlugin("module", ({ request, dependencyType }, callback) => {
  152. if (dependencyType === "url") {
  153. if (/^(\/\/|https?:\/\/|#)/.test(/** @type {string} */ (request)))
  154. return callback(null, `asset ${request}`);
  155. } else if (dependencyType === "css-import") {
  156. if (/^(\/\/|https?:\/\/|#)/.test(/** @type {string} */ (request)))
  157. return callback(null, `css-import ${request}`);
  158. } else if (
  159. /^(\/\/|https?:\/\/|std:)/.test(/** @type {string} */ (request))
  160. ) {
  161. if (/^\.css(\?|$)/.test(/** @type {string} */ (request)))
  162. return callback(null, `css-import ${request}`);
  163. return callback(null, `module ${request}`);
  164. }
  165. callback();
  166. }).apply(compiler);
  167. }
  168. new ChunkPrefetchPreloadPlugin().apply(compiler);
  169. if (typeof options.output.chunkFormat === "string") {
  170. switch (options.output.chunkFormat) {
  171. case "array-push": {
  172. const ArrayPushCallbackChunkFormatPlugin = require("./javascript/ArrayPushCallbackChunkFormatPlugin");
  173. new ArrayPushCallbackChunkFormatPlugin().apply(compiler);
  174. break;
  175. }
  176. case "commonjs": {
  177. const CommonJsChunkFormatPlugin = require("./javascript/CommonJsChunkFormatPlugin");
  178. new CommonJsChunkFormatPlugin().apply(compiler);
  179. break;
  180. }
  181. case "module": {
  182. const ModuleChunkFormatPlugin = require("./esm/ModuleChunkFormatPlugin");
  183. new ModuleChunkFormatPlugin().apply(compiler);
  184. break;
  185. }
  186. default:
  187. throw new Error(
  188. `Unsupported chunk format '${options.output.chunkFormat}'.`
  189. );
  190. }
  191. }
  192. const enabledChunkLoadingTypes =
  193. /** @type {NonNullable<WebpackOptions["output"]["enabledChunkLoadingTypes"]>} */
  194. (options.output.enabledChunkLoadingTypes);
  195. if (enabledChunkLoadingTypes.length > 0) {
  196. for (const type of enabledChunkLoadingTypes) {
  197. const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin");
  198. new EnableChunkLoadingPlugin(type).apply(compiler);
  199. }
  200. }
  201. const enabledWasmLoadingTypes =
  202. /** @type {NonNullable<WebpackOptions["output"]["enabledWasmLoadingTypes"]>} */
  203. (options.output.enabledWasmLoadingTypes);
  204. if (enabledWasmLoadingTypes.length > 0) {
  205. for (const type of enabledWasmLoadingTypes) {
  206. const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin");
  207. new EnableWasmLoadingPlugin(type).apply(compiler);
  208. }
  209. }
  210. const enabledLibraryTypes =
  211. /** @type {NonNullable<WebpackOptions["output"]["enabledLibraryTypes"]>} */
  212. (options.output.enabledLibraryTypes);
  213. if (enabledLibraryTypes.length > 0) {
  214. let once = true;
  215. for (const type of enabledLibraryTypes) {
  216. const EnableLibraryPlugin = require("./library/EnableLibraryPlugin");
  217. new EnableLibraryPlugin(type, {
  218. // eslint-disable-next-line no-loop-func
  219. additionalApply: () => {
  220. if (!once) return;
  221. once = false;
  222. // We rely on `exportInfo` to generate the `export statement` in certain library bundles.
  223. // Therefore, we ignore the disabling of `optimization.providedExport` and continue to apply `FlagDependencyExportsPlugin`.
  224. if (
  225. ["module", "commonjs-static", "modern-module"].includes(type) &&
  226. !options.optimization.providedExports
  227. ) {
  228. new FlagDependencyExportsPlugin().apply(compiler);
  229. }
  230. }
  231. }).apply(compiler);
  232. }
  233. }
  234. if (options.output.pathinfo) {
  235. const ModuleInfoHeaderPlugin = require("./ModuleInfoHeaderPlugin");
  236. new ModuleInfoHeaderPlugin(options.output.pathinfo !== true).apply(
  237. compiler
  238. );
  239. }
  240. if (options.output.clean) {
  241. const CleanPlugin = require("./CleanPlugin");
  242. new CleanPlugin(
  243. options.output.clean === true ? {} : options.output.clean
  244. ).apply(compiler);
  245. }
  246. if (options.devtool) {
  247. if (options.devtool.includes("source-map")) {
  248. const hidden = options.devtool.includes("hidden");
  249. const inline = options.devtool.includes("inline");
  250. const evalWrapped = options.devtool.includes("eval");
  251. const cheap = options.devtool.includes("cheap");
  252. const moduleMaps = options.devtool.includes("module");
  253. const noSources = options.devtool.includes("nosources");
  254. const debugIds = options.devtool.includes("debugids");
  255. const Plugin = evalWrapped
  256. ? require("./EvalSourceMapDevToolPlugin")
  257. : require("./SourceMapDevToolPlugin");
  258. new Plugin({
  259. filename: inline ? null : options.output.sourceMapFilename,
  260. moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
  261. fallbackModuleFilenameTemplate:
  262. options.output.devtoolFallbackModuleFilenameTemplate,
  263. append: hidden ? false : undefined,
  264. module: moduleMaps ? true : !cheap,
  265. columns: !cheap,
  266. noSources,
  267. namespace: options.output.devtoolNamespace,
  268. debugIds
  269. }).apply(compiler);
  270. } else if (options.devtool.includes("eval")) {
  271. const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
  272. new EvalDevToolModulePlugin({
  273. moduleFilenameTemplate: options.output.devtoolModuleFilenameTemplate,
  274. namespace: options.output.devtoolNamespace
  275. }).apply(compiler);
  276. }
  277. }
  278. new JavascriptModulesPlugin().apply(compiler);
  279. new JsonModulesPlugin().apply(compiler);
  280. new AssetModulesPlugin().apply(compiler);
  281. if (!options.experiments.outputModule) {
  282. if (options.output.module) {
  283. throw new Error(
  284. "'output.module: true' is only allowed when 'experiments.outputModule' is enabled"
  285. );
  286. }
  287. if (options.output.enabledLibraryTypes.includes("module")) {
  288. throw new Error(
  289. "library type \"module\" is only allowed when 'experiments.outputModule' is enabled"
  290. );
  291. }
  292. if (options.output.enabledLibraryTypes.includes("modern-module")) {
  293. throw new Error(
  294. "library type \"modern-module\" is only allowed when 'experiments.outputModule' is enabled"
  295. );
  296. }
  297. if (
  298. options.externalsType === "module" ||
  299. options.externalsType === "module-import"
  300. ) {
  301. throw new Error(
  302. "'externalsType: \"module\"' is only allowed when 'experiments.outputModule' is enabled"
  303. );
  304. }
  305. }
  306. if (options.experiments.syncWebAssembly) {
  307. const WebAssemblyModulesPlugin = require("./wasm-sync/WebAssemblyModulesPlugin");
  308. new WebAssemblyModulesPlugin({
  309. mangleImports: options.optimization.mangleWasmImports
  310. }).apply(compiler);
  311. }
  312. if (options.experiments.asyncWebAssembly) {
  313. const AsyncWebAssemblyModulesPlugin = require("./wasm-async/AsyncWebAssemblyModulesPlugin");
  314. new AsyncWebAssemblyModulesPlugin({
  315. mangleImports: options.optimization.mangleWasmImports
  316. }).apply(compiler);
  317. }
  318. if (options.experiments.css) {
  319. const CssModulesPlugin = require("./css/CssModulesPlugin");
  320. new CssModulesPlugin().apply(compiler);
  321. }
  322. if (options.experiments.lazyCompilation) {
  323. const LazyCompilationPlugin = require("./hmr/LazyCompilationPlugin");
  324. const lazyOptions =
  325. typeof options.experiments.lazyCompilation === "object"
  326. ? options.experiments.lazyCompilation
  327. : {};
  328. new LazyCompilationPlugin({
  329. backend:
  330. typeof lazyOptions.backend === "function"
  331. ? lazyOptions.backend
  332. : require("./hmr/lazyCompilationBackend")({
  333. ...lazyOptions.backend,
  334. client:
  335. (lazyOptions.backend && lazyOptions.backend.client) ||
  336. require.resolve(
  337. `../hot/lazy-compilation-${
  338. options.externalsPresets.node ? "node" : "web"
  339. }.js`
  340. )
  341. }),
  342. entries: !lazyOptions || lazyOptions.entries !== false,
  343. imports: !lazyOptions || lazyOptions.imports !== false,
  344. test: (lazyOptions && lazyOptions.test) || undefined
  345. }).apply(compiler);
  346. }
  347. if (options.experiments.buildHttp) {
  348. const HttpUriPlugin = require("./schemes/HttpUriPlugin");
  349. const httpOptions = options.experiments.buildHttp;
  350. new HttpUriPlugin(httpOptions).apply(compiler);
  351. }
  352. new EntryOptionPlugin().apply(compiler);
  353. compiler.hooks.entryOption.call(
  354. /** @type {string} */
  355. (options.context),
  356. options.entry
  357. );
  358. new RuntimePlugin().apply(compiler);
  359. new InferAsyncModulesPlugin().apply(compiler);
  360. new DataUriPlugin().apply(compiler);
  361. new FileUriPlugin().apply(compiler);
  362. new CompatibilityPlugin().apply(compiler);
  363. new HarmonyModulesPlugin({
  364. topLevelAwait: options.experiments.topLevelAwait
  365. }).apply(compiler);
  366. if (options.amd !== false) {
  367. const AMDPlugin = require("./dependencies/AMDPlugin");
  368. const RequireJsStuffPlugin = require("./RequireJsStuffPlugin");
  369. new AMDPlugin(options.amd || {}).apply(compiler);
  370. new RequireJsStuffPlugin().apply(compiler);
  371. }
  372. new CommonJsPlugin().apply(compiler);
  373. new LoaderPlugin().apply(compiler);
  374. if (options.node !== false) {
  375. const NodeStuffPlugin = require("./NodeStuffPlugin");
  376. new NodeStuffPlugin(options.node).apply(compiler);
  377. }
  378. new APIPlugin({
  379. module: options.output.module
  380. }).apply(compiler);
  381. new ExportsInfoApiPlugin().apply(compiler);
  382. new WebpackIsIncludedPlugin().apply(compiler);
  383. new ConstPlugin().apply(compiler);
  384. new UseStrictPlugin().apply(compiler);
  385. new RequireIncludePlugin().apply(compiler);
  386. new RequireEnsurePlugin().apply(compiler);
  387. new RequireContextPlugin().apply(compiler);
  388. new ImportPlugin().apply(compiler);
  389. new ImportMetaContextPlugin().apply(compiler);
  390. new SystemPlugin().apply(compiler);
  391. new ImportMetaPlugin().apply(compiler);
  392. new URLPlugin().apply(compiler);
  393. new WorkerPlugin(
  394. options.output.workerChunkLoading,
  395. options.output.workerWasmLoading,
  396. options.output.module,
  397. options.output.workerPublicPath
  398. ).apply(compiler);
  399. new DefaultStatsFactoryPlugin().apply(compiler);
  400. new DefaultStatsPresetPlugin().apply(compiler);
  401. new DefaultStatsPrinterPlugin().apply(compiler);
  402. new JavascriptMetaInfoPlugin().apply(compiler);
  403. if (typeof options.mode !== "string") {
  404. const WarnNoModeSetPlugin = require("./WarnNoModeSetPlugin");
  405. new WarnNoModeSetPlugin().apply(compiler);
  406. }
  407. const EnsureChunkConditionsPlugin = require("./optimize/EnsureChunkConditionsPlugin");
  408. new EnsureChunkConditionsPlugin().apply(compiler);
  409. if (options.optimization.removeAvailableModules) {
  410. const RemoveParentModulesPlugin = require("./optimize/RemoveParentModulesPlugin");
  411. new RemoveParentModulesPlugin().apply(compiler);
  412. }
  413. if (options.optimization.removeEmptyChunks) {
  414. const RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin");
  415. new RemoveEmptyChunksPlugin().apply(compiler);
  416. }
  417. if (options.optimization.mergeDuplicateChunks) {
  418. const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");
  419. new MergeDuplicateChunksPlugin().apply(compiler);
  420. }
  421. if (options.optimization.flagIncludedChunks) {
  422. const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");
  423. new FlagIncludedChunksPlugin().apply(compiler);
  424. }
  425. if (options.optimization.sideEffects) {
  426. const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin");
  427. new SideEffectsFlagPlugin(
  428. options.optimization.sideEffects === true
  429. ).apply(compiler);
  430. }
  431. if (options.optimization.providedExports) {
  432. new FlagDependencyExportsPlugin().apply(compiler);
  433. }
  434. if (options.optimization.usedExports) {
  435. const FlagDependencyUsagePlugin = require("./FlagDependencyUsagePlugin");
  436. new FlagDependencyUsagePlugin(
  437. options.optimization.usedExports === "global"
  438. ).apply(compiler);
  439. }
  440. if (options.optimization.innerGraph) {
  441. const InnerGraphPlugin = require("./optimize/InnerGraphPlugin");
  442. new InnerGraphPlugin().apply(compiler);
  443. }
  444. if (options.optimization.mangleExports) {
  445. const MangleExportsPlugin = require("./optimize/MangleExportsPlugin");
  446. new MangleExportsPlugin(
  447. options.optimization.mangleExports !== "size"
  448. ).apply(compiler);
  449. }
  450. if (options.optimization.concatenateModules) {
  451. const ModuleConcatenationPlugin = require("./optimize/ModuleConcatenationPlugin");
  452. new ModuleConcatenationPlugin().apply(compiler);
  453. }
  454. if (options.optimization.splitChunks) {
  455. const SplitChunksPlugin = require("./optimize/SplitChunksPlugin");
  456. new SplitChunksPlugin(options.optimization.splitChunks).apply(compiler);
  457. }
  458. if (options.optimization.runtimeChunk) {
  459. const RuntimeChunkPlugin = require("./optimize/RuntimeChunkPlugin");
  460. new RuntimeChunkPlugin(options.optimization.runtimeChunk).apply(compiler);
  461. }
  462. if (!options.optimization.emitOnErrors) {
  463. const NoEmitOnErrorsPlugin = require("./NoEmitOnErrorsPlugin");
  464. new NoEmitOnErrorsPlugin().apply(compiler);
  465. }
  466. if (options.optimization.realContentHash) {
  467. const RealContentHashPlugin = require("./optimize/RealContentHashPlugin");
  468. new RealContentHashPlugin({
  469. hashFunction:
  470. /** @type {NonNullable<WebpackOptions["output"]["hashFunction"]>} */
  471. (options.output.hashFunction),
  472. hashDigest:
  473. /** @type {NonNullable<WebpackOptions["output"]["hashDigest"]>} */
  474. (options.output.hashDigest)
  475. }).apply(compiler);
  476. }
  477. if (options.optimization.checkWasmTypes) {
  478. const WasmFinalizeExportsPlugin = require("./wasm-sync/WasmFinalizeExportsPlugin");
  479. new WasmFinalizeExportsPlugin().apply(compiler);
  480. }
  481. const moduleIds = options.optimization.moduleIds;
  482. if (moduleIds) {
  483. switch (moduleIds) {
  484. case "natural": {
  485. const NaturalModuleIdsPlugin = require("./ids/NaturalModuleIdsPlugin");
  486. new NaturalModuleIdsPlugin().apply(compiler);
  487. break;
  488. }
  489. case "named": {
  490. const NamedModuleIdsPlugin = require("./ids/NamedModuleIdsPlugin");
  491. new NamedModuleIdsPlugin().apply(compiler);
  492. break;
  493. }
  494. case "hashed": {
  495. const WarnDeprecatedOptionPlugin = require("./WarnDeprecatedOptionPlugin");
  496. const HashedModuleIdsPlugin = require("./ids/HashedModuleIdsPlugin");
  497. new WarnDeprecatedOptionPlugin(
  498. "optimization.moduleIds",
  499. "hashed",
  500. "deterministic"
  501. ).apply(compiler);
  502. new HashedModuleIdsPlugin({
  503. hashFunction: options.output.hashFunction
  504. }).apply(compiler);
  505. break;
  506. }
  507. case "deterministic": {
  508. const DeterministicModuleIdsPlugin = require("./ids/DeterministicModuleIdsPlugin");
  509. new DeterministicModuleIdsPlugin().apply(compiler);
  510. break;
  511. }
  512. case "size": {
  513. const OccurrenceModuleIdsPlugin = require("./ids/OccurrenceModuleIdsPlugin");
  514. new OccurrenceModuleIdsPlugin({
  515. prioritiseInitial: true
  516. }).apply(compiler);
  517. break;
  518. }
  519. default:
  520. throw new Error(
  521. `webpack bug: moduleIds: ${moduleIds} is not implemented`
  522. );
  523. }
  524. }
  525. const chunkIds = options.optimization.chunkIds;
  526. if (chunkIds) {
  527. switch (chunkIds) {
  528. case "natural": {
  529. const NaturalChunkIdsPlugin = require("./ids/NaturalChunkIdsPlugin");
  530. new NaturalChunkIdsPlugin().apply(compiler);
  531. break;
  532. }
  533. case "named": {
  534. const NamedChunkIdsPlugin = require("./ids/NamedChunkIdsPlugin");
  535. new NamedChunkIdsPlugin().apply(compiler);
  536. break;
  537. }
  538. case "deterministic": {
  539. const DeterministicChunkIdsPlugin = require("./ids/DeterministicChunkIdsPlugin");
  540. new DeterministicChunkIdsPlugin().apply(compiler);
  541. break;
  542. }
  543. case "size": {
  544. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  545. const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");
  546. new OccurrenceChunkIdsPlugin({
  547. prioritiseInitial: true
  548. }).apply(compiler);
  549. break;
  550. }
  551. case "total-size": {
  552. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  553. const OccurrenceChunkIdsPlugin = require("./ids/OccurrenceChunkIdsPlugin");
  554. new OccurrenceChunkIdsPlugin({
  555. prioritiseInitial: false
  556. }).apply(compiler);
  557. break;
  558. }
  559. default:
  560. throw new Error(
  561. `webpack bug: chunkIds: ${chunkIds} is not implemented`
  562. );
  563. }
  564. }
  565. if (options.optimization.nodeEnv) {
  566. const DefinePlugin = require("./DefinePlugin");
  567. new DefinePlugin({
  568. "process.env.NODE_ENV": JSON.stringify(options.optimization.nodeEnv)
  569. }).apply(compiler);
  570. }
  571. if (options.optimization.minimize) {
  572. for (const minimizer of /** @type {(WebpackPluginInstance | WebpackPluginFunction | "...")[]} */ (
  573. options.optimization.minimizer
  574. )) {
  575. if (typeof minimizer === "function") {
  576. /** @type {WebpackPluginFunction} */
  577. (minimizer).call(compiler, compiler);
  578. } else if (minimizer !== "..." && minimizer) {
  579. minimizer.apply(compiler);
  580. }
  581. }
  582. }
  583. if (options.performance) {
  584. const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin");
  585. new SizeLimitsPlugin(options.performance).apply(compiler);
  586. }
  587. new TemplatedPathPlugin().apply(compiler);
  588. new RecordIdsPlugin({
  589. portableIds: options.optimization.portableRecords
  590. }).apply(compiler);
  591. new WarnCaseSensitiveModulesPlugin().apply(compiler);
  592. const AddManagedPathsPlugin = require("./cache/AddManagedPathsPlugin");
  593. new AddManagedPathsPlugin(
  594. /** @type {NonNullable<WebpackOptions["snapshot"]["managedPaths"]>} */
  595. (options.snapshot.managedPaths),
  596. /** @type {NonNullable<WebpackOptions["snapshot"]["managedPaths"]>} */
  597. (options.snapshot.immutablePaths),
  598. /** @type {NonNullable<WebpackOptions["snapshot"]["managedPaths"]>} */
  599. (options.snapshot.unmanagedPaths)
  600. ).apply(compiler);
  601. if (options.cache && typeof options.cache === "object") {
  602. const cacheOptions = options.cache;
  603. switch (cacheOptions.type) {
  604. case "memory": {
  605. if (Number.isFinite(cacheOptions.maxGenerations)) {
  606. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  607. const MemoryWithGcCachePlugin = require("./cache/MemoryWithGcCachePlugin");
  608. new MemoryWithGcCachePlugin({
  609. maxGenerations:
  610. /** @type {number} */
  611. (cacheOptions.maxGenerations)
  612. }).apply(compiler);
  613. } else {
  614. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  615. const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
  616. new MemoryCachePlugin().apply(compiler);
  617. }
  618. if (cacheOptions.cacheUnaffected) {
  619. if (!options.experiments.cacheUnaffected) {
  620. throw new Error(
  621. "'cache.cacheUnaffected: true' is only allowed when 'experiments.cacheUnaffected' is enabled"
  622. );
  623. }
  624. compiler.moduleMemCaches = new Map();
  625. }
  626. break;
  627. }
  628. case "filesystem": {
  629. const AddBuildDependenciesPlugin = require("./cache/AddBuildDependenciesPlugin");
  630. // eslint-disable-next-line guard-for-in
  631. for (const key in cacheOptions.buildDependencies) {
  632. const list = cacheOptions.buildDependencies[key];
  633. new AddBuildDependenciesPlugin(list).apply(compiler);
  634. }
  635. if (!Number.isFinite(cacheOptions.maxMemoryGenerations)) {
  636. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  637. const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
  638. new MemoryCachePlugin().apply(compiler);
  639. } else if (cacheOptions.maxMemoryGenerations !== 0) {
  640. // @ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
  641. const MemoryWithGcCachePlugin = require("./cache/MemoryWithGcCachePlugin");
  642. new MemoryWithGcCachePlugin({
  643. maxGenerations:
  644. /** @type {number} */
  645. (cacheOptions.maxMemoryGenerations)
  646. }).apply(compiler);
  647. }
  648. if (cacheOptions.memoryCacheUnaffected) {
  649. if (!options.experiments.cacheUnaffected) {
  650. throw new Error(
  651. "'cache.memoryCacheUnaffected: true' is only allowed when 'experiments.cacheUnaffected' is enabled"
  652. );
  653. }
  654. compiler.moduleMemCaches = new Map();
  655. }
  656. switch (cacheOptions.store) {
  657. case "pack": {
  658. const IdleFileCachePlugin = require("./cache/IdleFileCachePlugin");
  659. const PackFileCacheStrategy = require("./cache/PackFileCacheStrategy");
  660. new IdleFileCachePlugin(
  661. new PackFileCacheStrategy({
  662. compiler,
  663. fs:
  664. /** @type {IntermediateFileSystem} */
  665. (compiler.intermediateFileSystem),
  666. context: /** @type {string} */ (options.context),
  667. cacheLocation:
  668. /** @type {string} */
  669. (cacheOptions.cacheLocation),
  670. version: /** @type {string} */ (cacheOptions.version),
  671. logger: compiler.getInfrastructureLogger(
  672. "webpack.cache.PackFileCacheStrategy"
  673. ),
  674. snapshot: options.snapshot,
  675. maxAge: /** @type {number} */ (cacheOptions.maxAge),
  676. profile: cacheOptions.profile,
  677. allowCollectingMemory: cacheOptions.allowCollectingMemory,
  678. compression: cacheOptions.compression,
  679. readonly: cacheOptions.readonly
  680. }),
  681. /** @type {number} */
  682. (cacheOptions.idleTimeout),
  683. /** @type {number} */
  684. (cacheOptions.idleTimeoutForInitialStore),
  685. /** @type {number} */
  686. (cacheOptions.idleTimeoutAfterLargeChanges)
  687. ).apply(compiler);
  688. break;
  689. }
  690. default:
  691. throw new Error("Unhandled value for cache.store");
  692. }
  693. break;
  694. }
  695. default:
  696. // @ts-expect-error Property 'type' does not exist on type 'never'. ts(2339)
  697. throw new Error(`Unknown cache type ${cacheOptions.type}`);
  698. }
  699. }
  700. new ResolverCachePlugin().apply(compiler);
  701. if (options.ignoreWarnings && options.ignoreWarnings.length > 0) {
  702. const IgnoreWarningsPlugin = require("./IgnoreWarningsPlugin");
  703. new IgnoreWarningsPlugin(options.ignoreWarnings).apply(compiler);
  704. }
  705. compiler.hooks.afterPlugins.call(compiler);
  706. if (!compiler.inputFileSystem) {
  707. throw new Error("No input filesystem provided");
  708. }
  709. compiler.resolverFactory.hooks.resolveOptions
  710. .for("normal")
  711. .tap(CLASS_NAME, resolveOptions => {
  712. resolveOptions = cleverMerge(options.resolve, resolveOptions);
  713. resolveOptions.fileSystem =
  714. /** @type {InputFileSystem} */
  715. (compiler.inputFileSystem);
  716. return resolveOptions;
  717. });
  718. compiler.resolverFactory.hooks.resolveOptions
  719. .for("context")
  720. .tap(CLASS_NAME, resolveOptions => {
  721. resolveOptions = cleverMerge(options.resolve, resolveOptions);
  722. resolveOptions.fileSystem =
  723. /** @type {InputFileSystem} */
  724. (compiler.inputFileSystem);
  725. resolveOptions.resolveToContext = true;
  726. return resolveOptions;
  727. });
  728. compiler.resolverFactory.hooks.resolveOptions
  729. .for("loader")
  730. .tap(CLASS_NAME, resolveOptions => {
  731. resolveOptions = cleverMerge(options.resolveLoader, resolveOptions);
  732. resolveOptions.fileSystem =
  733. /** @type {InputFileSystem} */
  734. (compiler.inputFileSystem);
  735. return resolveOptions;
  736. });
  737. compiler.hooks.afterResolvers.call(compiler);
  738. return options;
  739. }
  740. }
  741. module.exports = WebpackOptionsApply;