You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

761 lines
28 KiB

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