10
0

WebpackOptionsApply.js 29 KB

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