defaults.js 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const fs = require("fs");
  7. const path = require("path");
  8. const {
  9. JAVASCRIPT_MODULE_TYPE_AUTO,
  10. JAVASCRIPT_MODULE_TYPE_ESM,
  11. JAVASCRIPT_MODULE_TYPE_DYNAMIC,
  12. JSON_MODULE_TYPE,
  13. WEBASSEMBLY_MODULE_TYPE_ASYNC,
  14. WEBASSEMBLY_MODULE_TYPE_SYNC,
  15. ASSET_MODULE_TYPE,
  16. ASSET_MODULE_TYPE_INLINE,
  17. ASSET_MODULE_TYPE_RESOURCE,
  18. CSS_MODULE_TYPE_AUTO,
  19. CSS_MODULE_TYPE,
  20. CSS_MODULE_TYPE_MODULE,
  21. CSS_MODULE_TYPE_GLOBAL
  22. } = require("../ModuleTypeConstants");
  23. const Template = require("../Template");
  24. const { cleverMerge } = require("../util/cleverMerge");
  25. const {
  26. getTargetsProperties,
  27. getTargetProperties,
  28. getDefaultTarget
  29. } = require("./target");
  30. /** @typedef {import("../../declarations/WebpackOptions").CacheOptions} CacheOptions */
  31. /** @typedef {import("../../declarations/WebpackOptions").CacheOptionsNormalized} CacheOptionsNormalized */
  32. /** @typedef {import("../../declarations/WebpackOptions").Context} Context */
  33. /** @typedef {import("../../declarations/WebpackOptions").CssGeneratorOptions} CssGeneratorOptions */
  34. /** @typedef {import("../../declarations/WebpackOptions").CssParserOptions} CssParserOptions */
  35. /** @typedef {import("../../declarations/WebpackOptions").EntryDescription} EntryDescription */
  36. /** @typedef {import("../../declarations/WebpackOptions").EntryNormalized} Entry */
  37. /** @typedef {import("../../declarations/WebpackOptions").EntryStaticNormalized} EntryStaticNormalized */
  38. /** @typedef {import("../../declarations/WebpackOptions").Environment} Environment */
  39. /** @typedef {import("../../declarations/WebpackOptions").Experiments} Experiments */
  40. /** @typedef {import("../../declarations/WebpackOptions").ExperimentsNormalized} ExperimentsNormalized */
  41. /** @typedef {import("../../declarations/WebpackOptions").ExternalsPresets} ExternalsPresets */
  42. /** @typedef {import("../../declarations/WebpackOptions").ExternalsType} ExternalsType */
  43. /** @typedef {import("../../declarations/WebpackOptions").FileCacheOptions} FileCacheOptions */
  44. /** @typedef {import("../../declarations/WebpackOptions").GeneratorOptionsByModuleTypeKnown} GeneratorOptionsByModuleTypeKnown */
  45. /** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */
  46. /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
  47. /** @typedef {import("../../declarations/WebpackOptions").JsonGeneratorOptions} JsonGeneratorOptions */
  48. /** @typedef {import("../../declarations/WebpackOptions").Library} Library */
  49. /** @typedef {import("../../declarations/WebpackOptions").LibraryName} LibraryName */
  50. /** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
  51. /** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
  52. /** @typedef {import("../../declarations/WebpackOptions").Loader} Loader */
  53. /** @typedef {import("../../declarations/WebpackOptions").Mode} Mode */
  54. /** @typedef {import("../../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
  55. /** @typedef {import("../../declarations/WebpackOptions").Node} WebpackNode */
  56. /** @typedef {import("../../declarations/WebpackOptions").Optimization} Optimization */
  57. /** @typedef {import("../../declarations/WebpackOptions").OptimizationSplitChunksOptions} OptimizationSplitChunksOptions */
  58. /** @typedef {import("../../declarations/WebpackOptions").OutputNormalized} Output */
  59. /** @typedef {import("../../declarations/WebpackOptions").ParserOptionsByModuleTypeKnown} ParserOptionsByModuleTypeKnown */
  60. /** @typedef {import("../../declarations/WebpackOptions").Performance} Performance */
  61. /** @typedef {import("../../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
  62. /** @typedef {import("../../declarations/WebpackOptions").RuleSetRules} RuleSetRules */
  63. /** @typedef {import("../../declarations/WebpackOptions").SnapshotOptions} SnapshotOptions */
  64. /** @typedef {import("../../declarations/WebpackOptions").Target} Target */
  65. /** @typedef {import("../../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
  66. /** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptionsNormalized */
  67. /** @typedef {import("../Compiler")} Compiler */
  68. /** @typedef {import("../Module")} Module */
  69. /** @typedef {import("./target").PlatformTargetProperties} PlatformTargetProperties */
  70. /** @typedef {import("./target").TargetProperties} TargetProperties */
  71. /**
  72. * @typedef {object} ResolvedOptions
  73. * @property {PlatformTargetProperties | false} platform - platform target properties
  74. */
  75. const NODE_MODULES_REGEXP = /[\\/]node_modules[\\/]/i;
  76. const DEFAULT_CACHE_NAME = "default";
  77. const DEFAULTS = {
  78. // TODO webpack 6 - use xxhash64
  79. HASH_FUNCTION: "md4"
  80. };
  81. /**
  82. * Sets a constant default value when undefined
  83. * @template T
  84. * @template {keyof T} P
  85. * @param {T} obj an object
  86. * @param {P} prop a property of this object
  87. * @param {T[P]} value a default value of the property
  88. * @returns {void}
  89. */
  90. const D = (obj, prop, value) => {
  91. if (obj[prop] === undefined) {
  92. obj[prop] = value;
  93. }
  94. };
  95. /**
  96. * Sets a dynamic default value when undefined, by calling the factory function
  97. * @template T
  98. * @template {keyof T} P
  99. * @param {T} obj an object
  100. * @param {P} prop a property of this object
  101. * @param {() => T[P]} factory a default value factory for the property
  102. * @returns {void}
  103. */
  104. const F = (obj, prop, factory) => {
  105. if (obj[prop] === undefined) {
  106. obj[prop] = factory();
  107. }
  108. };
  109. /**
  110. * Sets a dynamic default value when undefined, by calling the factory function.
  111. * factory must return an array or undefined
  112. * When the current value is already an array an contains "..." it's replaced with
  113. * the result of the factory function
  114. * @template T
  115. * @template {keyof T} P
  116. * @param {T} obj an object
  117. * @param {P} prop a property of this object
  118. * @param {() => T[P]} factory a default value factory for the property
  119. * @returns {void}
  120. */
  121. const A = (obj, prop, factory) => {
  122. const value = obj[prop];
  123. if (value === undefined) {
  124. obj[prop] = factory();
  125. } else if (Array.isArray(value)) {
  126. /** @type {EXPECTED_ANY[] | undefined} */
  127. let newArray;
  128. for (let i = 0; i < value.length; i++) {
  129. const item = value[i];
  130. if (item === "...") {
  131. if (newArray === undefined) {
  132. newArray = value.slice(0, i);
  133. obj[prop] = /** @type {T[P]} */ (/** @type {unknown} */ (newArray));
  134. }
  135. const items = /** @type {EXPECTED_ANY[]} */ (
  136. /** @type {unknown} */ (factory())
  137. );
  138. if (items !== undefined) {
  139. for (const item of items) {
  140. newArray.push(item);
  141. }
  142. }
  143. } else if (newArray !== undefined) {
  144. newArray.push(item);
  145. }
  146. }
  147. }
  148. };
  149. /**
  150. * @param {WebpackOptionsNormalized} options options to be modified
  151. * @returns {void}
  152. */
  153. const applyWebpackOptionsBaseDefaults = options => {
  154. F(options, "context", () => process.cwd());
  155. applyInfrastructureLoggingDefaults(options.infrastructureLogging);
  156. };
  157. /**
  158. * @param {WebpackOptionsNormalized} options options to be modified
  159. * @param {number} [compilerIndex] index of compiler
  160. * @returns {ResolvedOptions} Resolved options after apply defaults
  161. */
  162. const applyWebpackOptionsDefaults = (options, compilerIndex) => {
  163. F(options, "context", () => process.cwd());
  164. F(options, "target", () =>
  165. getDefaultTarget(/** @type {string} */ (options.context))
  166. );
  167. const { mode, name, target } = options;
  168. const targetProperties =
  169. target === false
  170. ? /** @type {false} */ (false)
  171. : typeof target === "string"
  172. ? getTargetProperties(target, /** @type {Context} */ (options.context))
  173. : getTargetsProperties(
  174. /** @type {string[]} */ (target),
  175. /** @type {Context} */ (options.context)
  176. );
  177. const development = mode === "development";
  178. const production = mode === "production" || !mode;
  179. if (typeof options.entry !== "function") {
  180. for (const key of Object.keys(options.entry)) {
  181. F(
  182. options.entry[key],
  183. "import",
  184. () => /** @type {[string]} */ (["./src"])
  185. );
  186. }
  187. }
  188. F(options, "devtool", () => (development ? "eval" : false));
  189. D(options, "watch", false);
  190. D(options, "profile", false);
  191. D(options, "parallelism", 100);
  192. D(options, "recordsInputPath", false);
  193. D(options, "recordsOutputPath", false);
  194. applyExperimentsDefaults(options.experiments, {
  195. production,
  196. development,
  197. targetProperties
  198. });
  199. const futureDefaults =
  200. /** @type {NonNullable<ExperimentsNormalized["futureDefaults"]>} */
  201. (options.experiments.futureDefaults);
  202. F(options, "cache", () =>
  203. development ? { type: /** @type {"memory"} */ ("memory") } : false
  204. );
  205. applyCacheDefaults(options.cache, {
  206. name: name || DEFAULT_CACHE_NAME,
  207. mode: mode || "production",
  208. development,
  209. cacheUnaffected: options.experiments.cacheUnaffected,
  210. futureDefaults,
  211. compilerIndex
  212. });
  213. const cache = Boolean(options.cache);
  214. applySnapshotDefaults(options.snapshot, {
  215. production,
  216. futureDefaults
  217. });
  218. applyOutputDefaults(options.output, {
  219. context: /** @type {Context} */ (options.context),
  220. targetProperties,
  221. isAffectedByBrowserslist:
  222. target === undefined ||
  223. (typeof target === "string" && target.startsWith("browserslist")) ||
  224. (Array.isArray(target) &&
  225. target.some(target => target.startsWith("browserslist"))),
  226. outputModule:
  227. /** @type {NonNullable<ExperimentsNormalized["outputModule"]>} */
  228. (options.experiments.outputModule),
  229. development,
  230. entry: options.entry,
  231. futureDefaults,
  232. asyncWebAssembly:
  233. /** @type {NonNullable<ExperimentsNormalized["asyncWebAssembly"]>} */
  234. (options.experiments.asyncWebAssembly)
  235. });
  236. applyModuleDefaults(options.module, {
  237. cache,
  238. syncWebAssembly:
  239. /** @type {NonNullable<ExperimentsNormalized["syncWebAssembly"]>} */
  240. (options.experiments.syncWebAssembly),
  241. asyncWebAssembly:
  242. /** @type {NonNullable<ExperimentsNormalized["asyncWebAssembly"]>} */
  243. (options.experiments.asyncWebAssembly),
  244. css:
  245. /** @type {NonNullable<ExperimentsNormalized["css"]>} */
  246. (options.experiments.css),
  247. futureDefaults,
  248. isNode: targetProperties && targetProperties.node === true,
  249. uniqueName: /** @type {string} */ (options.output.uniqueName),
  250. targetProperties,
  251. mode: options.mode
  252. });
  253. applyExternalsPresetsDefaults(options.externalsPresets, {
  254. targetProperties,
  255. buildHttp: Boolean(options.experiments.buildHttp)
  256. });
  257. applyLoaderDefaults(
  258. /** @type {NonNullable<WebpackOptionsNormalized["loader"]>} */ (
  259. options.loader
  260. ),
  261. { targetProperties, environment: options.output.environment }
  262. );
  263. F(options, "externalsType", () => {
  264. const validExternalTypes = require("../../schemas/WebpackOptions.json")
  265. .definitions.ExternalsType.enum;
  266. return options.output.library &&
  267. validExternalTypes.includes(options.output.library.type)
  268. ? /** @type {ExternalsType} */ (options.output.library.type)
  269. : options.output.module
  270. ? "module-import"
  271. : "var";
  272. });
  273. applyNodeDefaults(options.node, {
  274. futureDefaults:
  275. /** @type {NonNullable<WebpackOptionsNormalized["experiments"]["futureDefaults"]>} */
  276. (options.experiments.futureDefaults),
  277. outputModule:
  278. /** @type {NonNullable<WebpackOptionsNormalized["output"]["module"]>} */
  279. (options.output.module),
  280. targetProperties
  281. });
  282. F(options, "performance", () =>
  283. production &&
  284. targetProperties &&
  285. (targetProperties.browser || targetProperties.browser === null)
  286. ? {}
  287. : false
  288. );
  289. applyPerformanceDefaults(
  290. /** @type {NonNullable<WebpackOptionsNormalized["performance"]>} */
  291. (options.performance),
  292. {
  293. production
  294. }
  295. );
  296. applyOptimizationDefaults(options.optimization, {
  297. development,
  298. production,
  299. css:
  300. /** @type {NonNullable<ExperimentsNormalized["css"]>} */
  301. (options.experiments.css),
  302. records: Boolean(options.recordsInputPath || options.recordsOutputPath)
  303. });
  304. options.resolve = cleverMerge(
  305. getResolveDefaults({
  306. cache,
  307. context: /** @type {Context} */ (options.context),
  308. targetProperties,
  309. mode: /** @type {Mode} */ (options.mode),
  310. css:
  311. /** @type {NonNullable<ExperimentsNormalized["css"]>} */
  312. (options.experiments.css)
  313. }),
  314. options.resolve
  315. );
  316. options.resolveLoader = cleverMerge(
  317. getResolveLoaderDefaults({ cache }),
  318. options.resolveLoader
  319. );
  320. return {
  321. platform:
  322. targetProperties === false
  323. ? targetProperties
  324. : {
  325. web: targetProperties.web,
  326. browser: targetProperties.browser,
  327. webworker: targetProperties.webworker,
  328. node: targetProperties.node,
  329. nwjs: targetProperties.nwjs,
  330. electron: targetProperties.electron
  331. }
  332. };
  333. };
  334. /**
  335. * @param {ExperimentsNormalized} experiments options
  336. * @param {object} options options
  337. * @param {boolean} options.production is production
  338. * @param {boolean} options.development is development mode
  339. * @param {TargetProperties | false} options.targetProperties target properties
  340. * @returns {void}
  341. */
  342. const applyExperimentsDefaults = (
  343. experiments,
  344. { production, development, targetProperties }
  345. ) => {
  346. D(experiments, "futureDefaults", false);
  347. D(experiments, "backCompat", !experiments.futureDefaults);
  348. D(experiments, "syncWebAssembly", false);
  349. D(experiments, "asyncWebAssembly", experiments.futureDefaults);
  350. D(experiments, "outputModule", false);
  351. D(experiments, "layers", false);
  352. D(experiments, "lazyCompilation", undefined);
  353. D(experiments, "buildHttp", undefined);
  354. D(experiments, "cacheUnaffected", experiments.futureDefaults);
  355. F(experiments, "css", () => (experiments.futureDefaults ? true : undefined));
  356. // TODO webpack 6: remove this. topLevelAwait should be enabled by default
  357. let shouldEnableTopLevelAwait = true;
  358. if (typeof experiments.topLevelAwait === "boolean") {
  359. shouldEnableTopLevelAwait = experiments.topLevelAwait;
  360. }
  361. D(experiments, "topLevelAwait", shouldEnableTopLevelAwait);
  362. if (typeof experiments.buildHttp === "object") {
  363. D(experiments.buildHttp, "frozen", production);
  364. D(experiments.buildHttp, "upgrade", false);
  365. }
  366. };
  367. /**
  368. * @param {CacheOptionsNormalized} cache options
  369. * @param {object} options options
  370. * @param {string} options.name name
  371. * @param {Mode} options.mode mode
  372. * @param {boolean} options.futureDefaults is future defaults enabled
  373. * @param {boolean} options.development is development mode
  374. * @param {number} [options.compilerIndex] index of compiler
  375. * @param {Experiments["cacheUnaffected"]} options.cacheUnaffected the cacheUnaffected experiment is enabled
  376. * @returns {void}
  377. */
  378. const applyCacheDefaults = (
  379. cache,
  380. { name, mode, development, cacheUnaffected, compilerIndex, futureDefaults }
  381. ) => {
  382. if (cache === false) return;
  383. switch (cache.type) {
  384. case "filesystem":
  385. F(cache, "name", () =>
  386. compilerIndex !== undefined
  387. ? `${`${name}-${mode}`}__compiler${compilerIndex + 1}__`
  388. : `${name}-${mode}`
  389. );
  390. D(cache, "version", "");
  391. F(cache, "cacheDirectory", () => {
  392. const cwd = process.cwd();
  393. /** @type {string | undefined} */
  394. let dir = cwd;
  395. for (;;) {
  396. try {
  397. if (fs.statSync(path.join(dir, "package.json")).isFile()) break;
  398. // eslint-disable-next-line no-empty
  399. } catch (_err) {}
  400. const parent = path.dirname(dir);
  401. if (dir === parent) {
  402. dir = undefined;
  403. break;
  404. }
  405. dir = parent;
  406. }
  407. if (!dir) {
  408. return path.resolve(cwd, ".cache/webpack");
  409. } else if (process.versions.pnp === "1") {
  410. return path.resolve(dir, ".pnp/.cache/webpack");
  411. } else if (process.versions.pnp === "3") {
  412. return path.resolve(dir, ".yarn/.cache/webpack");
  413. }
  414. return path.resolve(dir, "node_modules/.cache/webpack");
  415. });
  416. F(cache, "cacheLocation", () =>
  417. path.resolve(
  418. /** @type {NonNullable<FileCacheOptions["cacheDirectory"]>} */
  419. (cache.cacheDirectory),
  420. /** @type {NonNullable<FileCacheOptions["name"]>} */ (cache.name)
  421. )
  422. );
  423. D(cache, "hashAlgorithm", futureDefaults ? "xxhash64" : "md4");
  424. D(cache, "store", "pack");
  425. D(cache, "compression", false);
  426. D(cache, "profile", false);
  427. D(cache, "idleTimeout", 60000);
  428. D(cache, "idleTimeoutForInitialStore", 5000);
  429. D(cache, "idleTimeoutAfterLargeChanges", 1000);
  430. D(cache, "maxMemoryGenerations", development ? 5 : Infinity);
  431. D(cache, "maxAge", 1000 * 60 * 60 * 24 * 60); // 1 month
  432. D(cache, "allowCollectingMemory", development);
  433. D(cache, "memoryCacheUnaffected", development && cacheUnaffected);
  434. D(cache, "readonly", false);
  435. D(
  436. /** @type {NonNullable<FileCacheOptions["buildDependencies"]>} */
  437. (cache.buildDependencies),
  438. "defaultWebpack",
  439. [path.resolve(__dirname, "..") + path.sep]
  440. );
  441. break;
  442. case "memory":
  443. D(cache, "maxGenerations", Infinity);
  444. D(cache, "cacheUnaffected", development && cacheUnaffected);
  445. break;
  446. }
  447. };
  448. /**
  449. * @param {SnapshotOptions} snapshot options
  450. * @param {object} options options
  451. * @param {boolean} options.production is production
  452. * @param {boolean} options.futureDefaults is future defaults enabled
  453. * @returns {void}
  454. */
  455. const applySnapshotDefaults = (snapshot, { production, futureDefaults }) => {
  456. if (futureDefaults) {
  457. F(snapshot, "managedPaths", () =>
  458. process.versions.pnp === "3"
  459. ? [
  460. /^(.+?(?:[\\/]\.yarn[\\/]unplugged[\\/][^\\/]+)?[\\/]node_modules[\\/])/
  461. ]
  462. : [/^(.+?[\\/]node_modules[\\/])/]
  463. );
  464. F(snapshot, "immutablePaths", () =>
  465. process.versions.pnp === "3"
  466. ? [/^(.+?[\\/]cache[\\/][^\\/]+\.zip[\\/]node_modules[\\/])/]
  467. : []
  468. );
  469. } else {
  470. A(snapshot, "managedPaths", () => {
  471. if (process.versions.pnp === "3") {
  472. const match =
  473. /^(.+?)[\\/]cache[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
  474. require.resolve("watchpack")
  475. );
  476. if (match) {
  477. return [path.resolve(match[1], "unplugged")];
  478. }
  479. } else {
  480. const match = /^(.+?[\\/]node_modules[\\/])/.exec(
  481. require.resolve("watchpack")
  482. );
  483. if (match) {
  484. return [match[1]];
  485. }
  486. }
  487. return [];
  488. });
  489. A(snapshot, "immutablePaths", () => {
  490. if (process.versions.pnp === "1") {
  491. const match =
  492. /^(.+?[\\/]v4)[\\/]npm-watchpack-[^\\/]+-[\da-f]{40}[\\/]node_modules[\\/]/.exec(
  493. require.resolve("watchpack")
  494. );
  495. if (match) {
  496. return [match[1]];
  497. }
  498. } else if (process.versions.pnp === "3") {
  499. const match =
  500. /^(.+?)[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
  501. require.resolve("watchpack")
  502. );
  503. if (match) {
  504. return [match[1]];
  505. }
  506. }
  507. return [];
  508. });
  509. }
  510. F(snapshot, "unmanagedPaths", () => []);
  511. F(snapshot, "resolveBuildDependencies", () => ({
  512. timestamp: true,
  513. hash: true
  514. }));
  515. F(snapshot, "buildDependencies", () => ({ timestamp: true, hash: true }));
  516. F(snapshot, "module", () =>
  517. production ? { timestamp: true, hash: true } : { timestamp: true }
  518. );
  519. F(snapshot, "resolve", () =>
  520. production ? { timestamp: true, hash: true } : { timestamp: true }
  521. );
  522. };
  523. /**
  524. * @param {JavascriptParserOptions} parserOptions parser options
  525. * @param {object} options options
  526. * @param {boolean} options.futureDefaults is future defaults enabled
  527. * @param {boolean} options.isNode is node target platform
  528. * @returns {void}
  529. */
  530. const applyJavascriptParserOptionsDefaults = (
  531. parserOptions,
  532. { futureDefaults, isNode }
  533. ) => {
  534. D(parserOptions, "unknownContextRequest", ".");
  535. D(parserOptions, "unknownContextRegExp", false);
  536. D(parserOptions, "unknownContextRecursive", true);
  537. D(parserOptions, "unknownContextCritical", true);
  538. D(parserOptions, "exprContextRequest", ".");
  539. D(parserOptions, "exprContextRegExp", false);
  540. D(parserOptions, "exprContextRecursive", true);
  541. D(parserOptions, "exprContextCritical", true);
  542. D(parserOptions, "wrappedContextRegExp", /.*/);
  543. D(parserOptions, "wrappedContextRecursive", true);
  544. D(parserOptions, "wrappedContextCritical", false);
  545. D(parserOptions, "strictThisContextOnImports", false);
  546. D(parserOptions, "importMeta", true);
  547. D(parserOptions, "dynamicImportMode", "lazy");
  548. D(parserOptions, "dynamicImportPrefetch", false);
  549. D(parserOptions, "dynamicImportPreload", false);
  550. D(parserOptions, "dynamicImportFetchPriority", false);
  551. D(parserOptions, "createRequire", isNode);
  552. if (futureDefaults) D(parserOptions, "exportsPresence", "error");
  553. };
  554. /**
  555. * @param {JsonGeneratorOptions} generatorOptions generator options
  556. * @returns {void}
  557. */
  558. const applyJsonGeneratorOptionsDefaults = generatorOptions => {
  559. D(generatorOptions, "JSONParse", true);
  560. };
  561. /**
  562. * @param {CssGeneratorOptions} generatorOptions generator options
  563. * @param {object} options options
  564. * @param {TargetProperties | false} options.targetProperties target properties
  565. * @returns {void}
  566. */
  567. const applyCssGeneratorOptionsDefaults = (
  568. generatorOptions,
  569. { targetProperties }
  570. ) => {
  571. D(
  572. generatorOptions,
  573. "exportsOnly",
  574. !targetProperties || targetProperties.document === false
  575. );
  576. D(generatorOptions, "esModule", true);
  577. };
  578. /**
  579. * @param {ModuleOptions} module options
  580. * @param {object} options options
  581. * @param {boolean} options.cache is caching enabled
  582. * @param {boolean} options.syncWebAssembly is syncWebAssembly enabled
  583. * @param {boolean} options.asyncWebAssembly is asyncWebAssembly enabled
  584. * @param {boolean} options.css is css enabled
  585. * @param {boolean} options.futureDefaults is future defaults enabled
  586. * @param {string} options.uniqueName the unique name
  587. * @param {boolean} options.isNode is node target platform
  588. * @param {TargetProperties | false} options.targetProperties target properties
  589. * @param {Mode | undefined} options.mode mode
  590. * @returns {void}
  591. */
  592. const applyModuleDefaults = (
  593. module,
  594. {
  595. cache,
  596. syncWebAssembly,
  597. asyncWebAssembly,
  598. css,
  599. futureDefaults,
  600. isNode,
  601. uniqueName,
  602. targetProperties,
  603. mode
  604. }
  605. ) => {
  606. if (cache) {
  607. D(
  608. module,
  609. "unsafeCache",
  610. /**
  611. * @param {Module} module module
  612. * @returns {boolean | null | string} true, if we want to cache the module
  613. */
  614. module => {
  615. const name = module.nameForCondition();
  616. return name && NODE_MODULES_REGEXP.test(name);
  617. }
  618. );
  619. } else {
  620. D(module, "unsafeCache", false);
  621. }
  622. F(module.parser, ASSET_MODULE_TYPE, () => ({}));
  623. F(
  624. /** @type {NonNullable<ParserOptionsByModuleTypeKnown[ASSET_MODULE_TYPE]>} */
  625. (module.parser[ASSET_MODULE_TYPE]),
  626. "dataUrlCondition",
  627. () => ({})
  628. );
  629. if (
  630. typeof (
  631. /** @type {NonNullable<ParserOptionsByModuleTypeKnown[ASSET_MODULE_TYPE]>} */
  632. (module.parser[ASSET_MODULE_TYPE]).dataUrlCondition
  633. ) === "object"
  634. ) {
  635. D(
  636. /** @type {NonNullable<ParserOptionsByModuleTypeKnown[ASSET_MODULE_TYPE]>} */
  637. (module.parser[ASSET_MODULE_TYPE]).dataUrlCondition,
  638. "maxSize",
  639. 8096
  640. );
  641. }
  642. F(module.parser, "javascript", () => ({}));
  643. F(module.parser, JSON_MODULE_TYPE, () => ({}));
  644. D(
  645. module.parser[JSON_MODULE_TYPE],
  646. "exportsDepth",
  647. mode === "development" ? 1 : Infinity
  648. );
  649. applyJavascriptParserOptionsDefaults(
  650. /** @type {NonNullable<ParserOptionsByModuleTypeKnown["javascript"]>} */
  651. (module.parser.javascript),
  652. {
  653. futureDefaults,
  654. isNode
  655. }
  656. );
  657. F(module.generator, "json", () => ({}));
  658. applyJsonGeneratorOptionsDefaults(
  659. /** @type {NonNullable<GeneratorOptionsByModuleTypeKnown["json"]>} */
  660. (module.generator.json)
  661. );
  662. if (css) {
  663. F(module.parser, CSS_MODULE_TYPE, () => ({}));
  664. D(
  665. /** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
  666. (module.parser[CSS_MODULE_TYPE]),
  667. "import",
  668. true
  669. );
  670. D(
  671. /** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
  672. (module.parser[CSS_MODULE_TYPE]),
  673. "url",
  674. true
  675. );
  676. D(
  677. /** @type {NonNullable<ParserOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
  678. (module.parser[CSS_MODULE_TYPE]),
  679. "namedExports",
  680. true
  681. );
  682. F(module.generator, CSS_MODULE_TYPE, () => ({}));
  683. applyCssGeneratorOptionsDefaults(
  684. /** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE]>} */
  685. (module.generator[CSS_MODULE_TYPE]),
  686. { targetProperties }
  687. );
  688. const localIdentName =
  689. uniqueName.length > 0 ? "[uniqueName]-[id]-[local]" : "[id]-[local]";
  690. F(module.generator, CSS_MODULE_TYPE_AUTO, () => ({}));
  691. D(
  692. /** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]>} */
  693. (module.generator[CSS_MODULE_TYPE_AUTO]),
  694. "localIdentName",
  695. localIdentName
  696. );
  697. D(
  698. /** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_AUTO]>} */
  699. (module.generator[CSS_MODULE_TYPE_AUTO]),
  700. "exportsConvention",
  701. "as-is"
  702. );
  703. F(module.generator, CSS_MODULE_TYPE_MODULE, () => ({}));
  704. D(
  705. /** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]>} */
  706. (module.generator[CSS_MODULE_TYPE_MODULE]),
  707. "localIdentName",
  708. localIdentName
  709. );
  710. D(
  711. /** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_MODULE]>} */
  712. (module.generator[CSS_MODULE_TYPE_MODULE]),
  713. "exportsConvention",
  714. "as-is"
  715. );
  716. F(module.generator, CSS_MODULE_TYPE_GLOBAL, () => ({}));
  717. D(
  718. /** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
  719. (module.generator[CSS_MODULE_TYPE_GLOBAL]),
  720. "localIdentName",
  721. localIdentName
  722. );
  723. D(
  724. /** @type {NonNullable<GeneratorOptionsByModuleTypeKnown[CSS_MODULE_TYPE_GLOBAL]>} */
  725. (module.generator[CSS_MODULE_TYPE_GLOBAL]),
  726. "exportsConvention",
  727. "as-is"
  728. );
  729. }
  730. A(module, "defaultRules", () => {
  731. const esm = {
  732. type: JAVASCRIPT_MODULE_TYPE_ESM,
  733. resolve: {
  734. byDependency: {
  735. esm: {
  736. fullySpecified: true
  737. }
  738. }
  739. }
  740. };
  741. const commonjs = {
  742. type: JAVASCRIPT_MODULE_TYPE_DYNAMIC
  743. };
  744. /** @type {RuleSetRules} */
  745. const rules = [
  746. {
  747. mimetype: "application/node",
  748. type: JAVASCRIPT_MODULE_TYPE_AUTO
  749. },
  750. {
  751. test: /\.json$/i,
  752. type: JSON_MODULE_TYPE
  753. },
  754. {
  755. mimetype: "application/json",
  756. type: JSON_MODULE_TYPE
  757. },
  758. {
  759. test: /\.mjs$/i,
  760. ...esm
  761. },
  762. {
  763. test: /\.js$/i,
  764. descriptionData: {
  765. type: "module"
  766. },
  767. ...esm
  768. },
  769. {
  770. test: /\.cjs$/i,
  771. ...commonjs
  772. },
  773. {
  774. test: /\.js$/i,
  775. descriptionData: {
  776. type: "commonjs"
  777. },
  778. ...commonjs
  779. },
  780. {
  781. mimetype: {
  782. or: ["text/javascript", "application/javascript"]
  783. },
  784. ...esm
  785. }
  786. ];
  787. if (asyncWebAssembly) {
  788. const wasm = {
  789. type: WEBASSEMBLY_MODULE_TYPE_ASYNC,
  790. rules: [
  791. {
  792. descriptionData: {
  793. type: "module"
  794. },
  795. resolve: {
  796. fullySpecified: true
  797. }
  798. }
  799. ]
  800. };
  801. rules.push({
  802. test: /\.wasm$/i,
  803. ...wasm
  804. });
  805. rules.push({
  806. mimetype: "application/wasm",
  807. ...wasm
  808. });
  809. } else if (syncWebAssembly) {
  810. const wasm = {
  811. type: WEBASSEMBLY_MODULE_TYPE_SYNC,
  812. rules: [
  813. {
  814. descriptionData: {
  815. type: "module"
  816. },
  817. resolve: {
  818. fullySpecified: true
  819. }
  820. }
  821. ]
  822. };
  823. rules.push({
  824. test: /\.wasm$/i,
  825. ...wasm
  826. });
  827. rules.push({
  828. mimetype: "application/wasm",
  829. ...wasm
  830. });
  831. }
  832. if (css) {
  833. const resolve = {
  834. fullySpecified: true,
  835. preferRelative: true
  836. };
  837. rules.push({
  838. test: /\.css$/i,
  839. type: CSS_MODULE_TYPE_AUTO,
  840. resolve
  841. });
  842. rules.push({
  843. mimetype: "text/css+module",
  844. type: CSS_MODULE_TYPE_MODULE,
  845. resolve
  846. });
  847. rules.push({
  848. mimetype: "text/css",
  849. type: CSS_MODULE_TYPE,
  850. resolve
  851. });
  852. }
  853. rules.push(
  854. {
  855. dependency: "url",
  856. oneOf: [
  857. {
  858. scheme: /^data$/,
  859. type: ASSET_MODULE_TYPE_INLINE
  860. },
  861. {
  862. type: ASSET_MODULE_TYPE_RESOURCE
  863. }
  864. ]
  865. },
  866. {
  867. assert: { type: JSON_MODULE_TYPE },
  868. type: JSON_MODULE_TYPE
  869. },
  870. {
  871. with: { type: JSON_MODULE_TYPE },
  872. type: JSON_MODULE_TYPE
  873. }
  874. );
  875. return rules;
  876. });
  877. };
  878. /**
  879. * @param {Output} output options
  880. * @param {object} options options
  881. * @param {string} options.context context
  882. * @param {TargetProperties | false} options.targetProperties target properties
  883. * @param {boolean} options.isAffectedByBrowserslist is affected by browserslist
  884. * @param {boolean} options.outputModule is outputModule experiment enabled
  885. * @param {boolean} options.development is development mode
  886. * @param {Entry} options.entry entry option
  887. * @param {boolean} options.futureDefaults is future defaults enabled
  888. * @param {boolean} options.asyncWebAssembly is asyncWebAssembly enabled
  889. * @returns {void}
  890. */
  891. const applyOutputDefaults = (
  892. output,
  893. {
  894. context,
  895. targetProperties: tp,
  896. isAffectedByBrowserslist,
  897. outputModule,
  898. development,
  899. entry,
  900. futureDefaults,
  901. asyncWebAssembly
  902. }
  903. ) => {
  904. /**
  905. * @param {Library=} library the library option
  906. * @returns {string} a readable library name
  907. */
  908. const getLibraryName = library => {
  909. const libraryName =
  910. typeof library === "object" &&
  911. library &&
  912. !Array.isArray(library) &&
  913. "type" in library
  914. ? library.name
  915. : /** @type {LibraryName} */ (library);
  916. if (Array.isArray(libraryName)) {
  917. return libraryName.join(".");
  918. } else if (typeof libraryName === "object") {
  919. return getLibraryName(libraryName.root);
  920. } else if (typeof libraryName === "string") {
  921. return libraryName;
  922. }
  923. return "";
  924. };
  925. F(output, "uniqueName", () => {
  926. const libraryName = getLibraryName(output.library).replace(
  927. /^\[(\\*[\w:]+\\*)\](\.)|(\.)\[(\\*[\w:]+\\*)\](?=\.|$)|\[(\\*[\w:]+\\*)\]/g,
  928. (m, a, d1, d2, b, c) => {
  929. const content = a || b || c;
  930. return content.startsWith("\\") && content.endsWith("\\")
  931. ? `${d2 || ""}[${content.slice(1, -1)}]${d1 || ""}`
  932. : "";
  933. }
  934. );
  935. if (libraryName) return libraryName;
  936. const pkgPath = path.resolve(context, "package.json");
  937. try {
  938. const packageInfo = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
  939. return packageInfo.name || "";
  940. } catch (err) {
  941. if (/** @type {Error & { code: string }} */ (err).code !== "ENOENT") {
  942. /** @type {Error & { code: string }} */
  943. (err).message +=
  944. `\nwhile determining default 'output.uniqueName' from 'name' in ${pkgPath}`;
  945. throw err;
  946. }
  947. return "";
  948. }
  949. });
  950. F(output, "module", () => Boolean(outputModule));
  951. const environment = /** @type {Environment} */ (output.environment);
  952. /**
  953. * @param {boolean | undefined} v value
  954. * @returns {boolean} true, when v is truthy or undefined
  955. */
  956. const optimistic = v => v || v === undefined;
  957. /**
  958. * @param {boolean | undefined} v value
  959. * @param {boolean | undefined} c condition
  960. * @returns {boolean | undefined} true, when v is truthy or undefined, or c is truthy
  961. */
  962. const conditionallyOptimistic = (v, c) => (v === undefined && c) || v;
  963. F(
  964. environment,
  965. "globalThis",
  966. () => /** @type {boolean | undefined} */ (tp && tp.globalThis)
  967. );
  968. F(
  969. environment,
  970. "bigIntLiteral",
  971. () =>
  972. tp && optimistic(/** @type {boolean | undefined} */ (tp.bigIntLiteral))
  973. );
  974. F(
  975. environment,
  976. "const",
  977. () => tp && optimistic(/** @type {boolean | undefined} */ (tp.const))
  978. );
  979. F(
  980. environment,
  981. "arrowFunction",
  982. () =>
  983. tp && optimistic(/** @type {boolean | undefined} */ (tp.arrowFunction))
  984. );
  985. F(
  986. environment,
  987. "asyncFunction",
  988. () =>
  989. tp && optimistic(/** @type {boolean | undefined} */ (tp.asyncFunction))
  990. );
  991. F(
  992. environment,
  993. "forOf",
  994. () => tp && optimistic(/** @type {boolean | undefined} */ (tp.forOf))
  995. );
  996. F(
  997. environment,
  998. "destructuring",
  999. () =>
  1000. tp && optimistic(/** @type {boolean | undefined} */ (tp.destructuring))
  1001. );
  1002. F(
  1003. environment,
  1004. "optionalChaining",
  1005. () =>
  1006. tp && optimistic(/** @type {boolean | undefined} */ (tp.optionalChaining))
  1007. );
  1008. F(
  1009. environment,
  1010. "nodePrefixForCoreModules",
  1011. () =>
  1012. tp &&
  1013. optimistic(
  1014. /** @type {boolean | undefined} */ (tp.nodePrefixForCoreModules)
  1015. )
  1016. );
  1017. F(
  1018. environment,
  1019. "templateLiteral",
  1020. () =>
  1021. tp && optimistic(/** @type {boolean | undefined} */ (tp.templateLiteral))
  1022. );
  1023. F(environment, "dynamicImport", () =>
  1024. conditionallyOptimistic(
  1025. /** @type {boolean | undefined} */ (tp && tp.dynamicImport),
  1026. output.module
  1027. )
  1028. );
  1029. F(environment, "dynamicImportInWorker", () =>
  1030. conditionallyOptimistic(
  1031. /** @type {boolean | undefined} */ (tp && tp.dynamicImportInWorker),
  1032. output.module
  1033. )
  1034. );
  1035. F(environment, "module", () =>
  1036. conditionallyOptimistic(
  1037. /** @type {boolean | undefined} */ (tp && tp.module),
  1038. output.module
  1039. )
  1040. );
  1041. F(
  1042. environment,
  1043. "document",
  1044. () => tp && optimistic(/** @type {boolean | undefined} */ (tp.document))
  1045. );
  1046. D(output, "filename", output.module ? "[name].mjs" : "[name].js");
  1047. F(output, "iife", () => !output.module);
  1048. D(output, "importFunctionName", "import");
  1049. D(output, "importMetaName", "import.meta");
  1050. F(output, "chunkFilename", () => {
  1051. const filename =
  1052. /** @type {NonNullable<Output["chunkFilename"]>} */
  1053. (output.filename);
  1054. if (typeof filename !== "function") {
  1055. const hasName = filename.includes("[name]");
  1056. const hasId = filename.includes("[id]");
  1057. const hasChunkHash = filename.includes("[chunkhash]");
  1058. const hasContentHash = filename.includes("[contenthash]");
  1059. // Anything changing depending on chunk is fine
  1060. if (hasChunkHash || hasContentHash || hasName || hasId) return filename;
  1061. // Otherwise prefix "[id]." in front of the basename to make it changing
  1062. return filename.replace(/(^|\/)([^/]*(?:\?|$))/, "$1[id].$2");
  1063. }
  1064. return output.module ? "[id].mjs" : "[id].js";
  1065. });
  1066. F(output, "cssFilename", () => {
  1067. const filename =
  1068. /** @type {NonNullable<Output["cssFilename"]>} */
  1069. (output.filename);
  1070. if (typeof filename !== "function") {
  1071. return filename.replace(/\.[mc]?js(\?|$)/, ".css$1");
  1072. }
  1073. return "[id].css";
  1074. });
  1075. F(output, "cssChunkFilename", () => {
  1076. const chunkFilename =
  1077. /** @type {NonNullable<Output["cssChunkFilename"]>} */
  1078. (output.chunkFilename);
  1079. if (typeof chunkFilename !== "function") {
  1080. return chunkFilename.replace(/\.[mc]?js(\?|$)/, ".css$1");
  1081. }
  1082. return "[id].css";
  1083. });
  1084. D(output, "assetModuleFilename", "[hash][ext][query]");
  1085. D(output, "webassemblyModuleFilename", "[hash].module.wasm");
  1086. D(output, "compareBeforeEmit", true);
  1087. D(output, "charset", !futureDefaults);
  1088. const uniqueNameId = Template.toIdentifier(
  1089. /** @type {NonNullable<Output["uniqueName"]>} */ (output.uniqueName)
  1090. );
  1091. F(output, "hotUpdateGlobal", () => `webpackHotUpdate${uniqueNameId}`);
  1092. F(output, "chunkLoadingGlobal", () => `webpackChunk${uniqueNameId}`);
  1093. F(output, "globalObject", () => {
  1094. if (tp) {
  1095. if (tp.global) return "global";
  1096. if (tp.globalThis) return "globalThis";
  1097. }
  1098. return "self";
  1099. });
  1100. F(output, "chunkFormat", () => {
  1101. if (tp) {
  1102. const helpMessage = isAffectedByBrowserslist
  1103. ? "Make sure that your 'browserslist' includes only platforms that support these features or select an appropriate 'target' to allow selecting a chunk format by default. Alternatively specify the 'output.chunkFormat' directly."
  1104. : "Select an appropriate 'target' to allow selecting one by default, or specify the 'output.chunkFormat' directly.";
  1105. if (output.module) {
  1106. if (environment.dynamicImport) return "module";
  1107. if (tp.document) return "array-push";
  1108. throw new Error(
  1109. "For the selected environment is no default ESM chunk format available:\n" +
  1110. "ESM exports can be chosen when 'import()' is available.\n" +
  1111. `JSONP Array push can be chosen when 'document' is available.\n${
  1112. helpMessage
  1113. }`
  1114. );
  1115. } else {
  1116. if (tp.document) return "array-push";
  1117. if (tp.require) return "commonjs";
  1118. if (tp.nodeBuiltins) return "commonjs";
  1119. if (tp.importScripts) return "array-push";
  1120. throw new Error(
  1121. "For the selected environment is no default script chunk format available:\n" +
  1122. "JSONP Array push can be chosen when 'document' or 'importScripts' is available.\n" +
  1123. `CommonJs exports can be chosen when 'require' or node builtins are available.\n${
  1124. helpMessage
  1125. }`
  1126. );
  1127. }
  1128. }
  1129. throw new Error(
  1130. "Chunk format can't be selected by default when no target is specified"
  1131. );
  1132. });
  1133. D(output, "asyncChunks", true);
  1134. F(output, "chunkLoading", () => {
  1135. if (tp) {
  1136. switch (output.chunkFormat) {
  1137. case "array-push":
  1138. if (tp.document) return "jsonp";
  1139. if (tp.importScripts) return "import-scripts";
  1140. break;
  1141. case "commonjs":
  1142. if (tp.require) return "require";
  1143. if (tp.nodeBuiltins) return "async-node";
  1144. break;
  1145. case "module":
  1146. if (environment.dynamicImport) return "import";
  1147. break;
  1148. }
  1149. if (
  1150. (tp.require === null ||
  1151. tp.nodeBuiltins === null ||
  1152. tp.document === null ||
  1153. tp.importScripts === null) &&
  1154. output.module &&
  1155. environment.dynamicImport
  1156. ) {
  1157. return "universal";
  1158. }
  1159. }
  1160. return false;
  1161. });
  1162. F(output, "workerChunkLoading", () => {
  1163. if (tp) {
  1164. switch (output.chunkFormat) {
  1165. case "array-push":
  1166. if (tp.importScriptsInWorker) return "import-scripts";
  1167. break;
  1168. case "commonjs":
  1169. if (tp.require) return "require";
  1170. if (tp.nodeBuiltins) return "async-node";
  1171. break;
  1172. case "module":
  1173. if (environment.dynamicImportInWorker) return "import";
  1174. break;
  1175. }
  1176. if (
  1177. (tp.require === null ||
  1178. tp.nodeBuiltins === null ||
  1179. tp.importScriptsInWorker === null) &&
  1180. output.module &&
  1181. environment.dynamicImport
  1182. ) {
  1183. return "universal";
  1184. }
  1185. }
  1186. return false;
  1187. });
  1188. F(output, "wasmLoading", () => {
  1189. if (tp) {
  1190. if (tp.fetchWasm) return "fetch";
  1191. if (tp.nodeBuiltins) return "async-node";
  1192. if (
  1193. (tp.nodeBuiltins === null || tp.fetchWasm === null) &&
  1194. asyncWebAssembly &&
  1195. output.module &&
  1196. environment.dynamicImport
  1197. ) {
  1198. return "universal";
  1199. }
  1200. }
  1201. return false;
  1202. });
  1203. F(output, "workerWasmLoading", () => output.wasmLoading);
  1204. F(output, "devtoolNamespace", () => output.uniqueName);
  1205. if (output.library) {
  1206. F(output.library, "type", () => (output.module ? "module" : "var"));
  1207. }
  1208. F(output, "path", () => path.join(process.cwd(), "dist"));
  1209. F(output, "pathinfo", () => development);
  1210. D(output, "sourceMapFilename", "[file].map[query]");
  1211. D(
  1212. output,
  1213. "hotUpdateChunkFilename",
  1214. `[id].[fullhash].hot-update.${output.module ? "mjs" : "js"}`
  1215. );
  1216. D(output, "hotUpdateMainFilename", "[runtime].[fullhash].hot-update.json");
  1217. D(output, "crossOriginLoading", false);
  1218. F(output, "scriptType", () => (output.module ? "module" : false));
  1219. D(
  1220. output,
  1221. "publicPath",
  1222. (tp && (tp.document || tp.importScripts)) || output.scriptType === "module"
  1223. ? "auto"
  1224. : ""
  1225. );
  1226. D(output, "workerPublicPath", "");
  1227. D(output, "chunkLoadTimeout", 120000);
  1228. F(output, "hashFunction", () => {
  1229. if (futureDefaults) {
  1230. DEFAULTS.HASH_FUNCTION = "xxhash64";
  1231. return "xxhash64";
  1232. }
  1233. return "md4";
  1234. });
  1235. D(output, "hashDigest", "hex");
  1236. D(output, "hashDigestLength", futureDefaults ? 16 : 20);
  1237. D(output, "strictModuleErrorHandling", false);
  1238. D(output, "strictModuleExceptionHandling", false);
  1239. const { trustedTypes } = output;
  1240. if (trustedTypes) {
  1241. F(
  1242. trustedTypes,
  1243. "policyName",
  1244. () =>
  1245. /** @type {NonNullable<Output["uniqueName"]>} */
  1246. (output.uniqueName).replace(/[^a-zA-Z0-9\-#=_/@.%]+/g, "_") || "webpack"
  1247. );
  1248. D(trustedTypes, "onPolicyCreationFailure", "stop");
  1249. }
  1250. /**
  1251. * @param {(entryDescription: EntryDescription) => void} fn iterator
  1252. * @returns {void}
  1253. */
  1254. const forEachEntry = fn => {
  1255. for (const name of Object.keys(entry)) {
  1256. fn(/** @type {{[k: string] : EntryDescription}} */ (entry)[name]);
  1257. }
  1258. };
  1259. A(output, "enabledLibraryTypes", () => {
  1260. /** @type {LibraryType[]} */
  1261. const enabledLibraryTypes = [];
  1262. if (output.library) {
  1263. enabledLibraryTypes.push(output.library.type);
  1264. }
  1265. forEachEntry(desc => {
  1266. if (desc.library) {
  1267. enabledLibraryTypes.push(desc.library.type);
  1268. }
  1269. });
  1270. return enabledLibraryTypes;
  1271. });
  1272. A(output, "enabledChunkLoadingTypes", () => {
  1273. const enabledChunkLoadingTypes = new Set();
  1274. if (output.chunkLoading) {
  1275. enabledChunkLoadingTypes.add(output.chunkLoading);
  1276. }
  1277. if (output.workerChunkLoading) {
  1278. enabledChunkLoadingTypes.add(output.workerChunkLoading);
  1279. }
  1280. forEachEntry(desc => {
  1281. if (desc.chunkLoading) {
  1282. enabledChunkLoadingTypes.add(desc.chunkLoading);
  1283. }
  1284. });
  1285. return Array.from(enabledChunkLoadingTypes);
  1286. });
  1287. A(output, "enabledWasmLoadingTypes", () => {
  1288. const enabledWasmLoadingTypes = new Set();
  1289. if (output.wasmLoading) {
  1290. enabledWasmLoadingTypes.add(output.wasmLoading);
  1291. }
  1292. if (output.workerWasmLoading) {
  1293. enabledWasmLoadingTypes.add(output.workerWasmLoading);
  1294. }
  1295. forEachEntry(desc => {
  1296. if (desc.wasmLoading) {
  1297. enabledWasmLoadingTypes.add(desc.wasmLoading);
  1298. }
  1299. });
  1300. return Array.from(enabledWasmLoadingTypes);
  1301. });
  1302. };
  1303. /**
  1304. * @param {ExternalsPresets} externalsPresets options
  1305. * @param {object} options options
  1306. * @param {TargetProperties | false} options.targetProperties target properties
  1307. * @param {boolean} options.buildHttp buildHttp experiment enabled
  1308. * @returns {void}
  1309. */
  1310. const applyExternalsPresetsDefaults = (
  1311. externalsPresets,
  1312. { targetProperties, buildHttp }
  1313. ) => {
  1314. D(
  1315. externalsPresets,
  1316. "web",
  1317. /** @type {boolean | undefined} */
  1318. (!buildHttp && targetProperties && targetProperties.web)
  1319. );
  1320. D(
  1321. externalsPresets,
  1322. "node",
  1323. /** @type {boolean | undefined} */
  1324. (targetProperties && targetProperties.node)
  1325. );
  1326. D(
  1327. externalsPresets,
  1328. "nwjs",
  1329. /** @type {boolean | undefined} */
  1330. (targetProperties && targetProperties.nwjs)
  1331. );
  1332. D(
  1333. externalsPresets,
  1334. "electron",
  1335. /** @type {boolean | undefined} */
  1336. (targetProperties && targetProperties.electron)
  1337. );
  1338. D(
  1339. externalsPresets,
  1340. "electronMain",
  1341. /** @type {boolean | undefined} */
  1342. (
  1343. targetProperties &&
  1344. targetProperties.electron &&
  1345. targetProperties.electronMain
  1346. )
  1347. );
  1348. D(
  1349. externalsPresets,
  1350. "electronPreload",
  1351. /** @type {boolean | undefined} */
  1352. (
  1353. targetProperties &&
  1354. targetProperties.electron &&
  1355. targetProperties.electronPreload
  1356. )
  1357. );
  1358. D(
  1359. externalsPresets,
  1360. "electronRenderer",
  1361. /** @type {boolean | undefined} */
  1362. (
  1363. targetProperties &&
  1364. targetProperties.electron &&
  1365. targetProperties.electronRenderer
  1366. )
  1367. );
  1368. };
  1369. /**
  1370. * @param {Loader} loader options
  1371. * @param {object} options options
  1372. * @param {TargetProperties | false} options.targetProperties target properties
  1373. * @param {Environment} options.environment environment
  1374. * @returns {void}
  1375. */
  1376. const applyLoaderDefaults = (loader, { targetProperties, environment }) => {
  1377. F(loader, "target", () => {
  1378. if (targetProperties) {
  1379. if (targetProperties.electron) {
  1380. if (targetProperties.electronMain) return "electron-main";
  1381. if (targetProperties.electronPreload) return "electron-preload";
  1382. if (targetProperties.electronRenderer) return "electron-renderer";
  1383. return "electron";
  1384. }
  1385. if (targetProperties.nwjs) return "nwjs";
  1386. if (targetProperties.node) return "node";
  1387. if (targetProperties.web) return "web";
  1388. }
  1389. });
  1390. D(loader, "environment", environment);
  1391. };
  1392. /**
  1393. * @param {WebpackNode} node options
  1394. * @param {object} options options
  1395. * @param {TargetProperties | false} options.targetProperties target properties
  1396. * @param {boolean} options.futureDefaults is future defaults enabled
  1397. * @param {boolean} options.outputModule is output type is module
  1398. * @returns {void}
  1399. */
  1400. const applyNodeDefaults = (
  1401. node,
  1402. { futureDefaults, outputModule, targetProperties }
  1403. ) => {
  1404. if (node === false) return;
  1405. F(node, "global", () => {
  1406. if (targetProperties && targetProperties.global) return false;
  1407. // TODO webpack 6 should always default to false
  1408. return futureDefaults ? "warn" : true;
  1409. });
  1410. const handlerForNames = () => {
  1411. if (targetProperties && targetProperties.node)
  1412. return outputModule ? "node-module" : "eval-only";
  1413. // TODO webpack 6 should always default to false
  1414. return futureDefaults ? "warn-mock" : "mock";
  1415. };
  1416. F(node, "__filename", handlerForNames);
  1417. F(node, "__dirname", handlerForNames);
  1418. };
  1419. /**
  1420. * @param {Performance} performance options
  1421. * @param {object} options options
  1422. * @param {boolean} options.production is production
  1423. * @returns {void}
  1424. */
  1425. const applyPerformanceDefaults = (performance, { production }) => {
  1426. if (performance === false) return;
  1427. D(performance, "maxAssetSize", 250000);
  1428. D(performance, "maxEntrypointSize", 250000);
  1429. F(performance, "hints", () => (production ? "warning" : false));
  1430. };
  1431. /**
  1432. * @param {Optimization} optimization options
  1433. * @param {object} options options
  1434. * @param {boolean} options.production is production
  1435. * @param {boolean} options.development is development
  1436. * @param {boolean} options.css is css enabled
  1437. * @param {boolean} options.records using records
  1438. * @returns {void}
  1439. */
  1440. const applyOptimizationDefaults = (
  1441. optimization,
  1442. { production, development, css, records }
  1443. ) => {
  1444. D(optimization, "removeAvailableModules", false);
  1445. D(optimization, "removeEmptyChunks", true);
  1446. D(optimization, "mergeDuplicateChunks", true);
  1447. D(optimization, "flagIncludedChunks", production);
  1448. F(optimization, "moduleIds", () => {
  1449. if (production) return "deterministic";
  1450. if (development) return "named";
  1451. return "natural";
  1452. });
  1453. F(optimization, "chunkIds", () => {
  1454. if (production) return "deterministic";
  1455. if (development) return "named";
  1456. return "natural";
  1457. });
  1458. F(optimization, "sideEffects", () => (production ? true : "flag"));
  1459. D(optimization, "providedExports", true);
  1460. D(optimization, "usedExports", production);
  1461. D(optimization, "innerGraph", production);
  1462. D(optimization, "mangleExports", production);
  1463. D(optimization, "concatenateModules", production);
  1464. D(optimization, "avoidEntryIife", production);
  1465. D(optimization, "runtimeChunk", false);
  1466. D(optimization, "emitOnErrors", !production);
  1467. D(optimization, "checkWasmTypes", production);
  1468. D(optimization, "mangleWasmImports", false);
  1469. D(optimization, "portableRecords", records);
  1470. D(optimization, "realContentHash", production);
  1471. D(optimization, "minimize", production);
  1472. A(optimization, "minimizer", () => [
  1473. {
  1474. apply: compiler => {
  1475. // Lazy load the Terser plugin
  1476. const TerserPlugin = require("terser-webpack-plugin");
  1477. new TerserPlugin({
  1478. terserOptions: {
  1479. compress: {
  1480. passes: 2
  1481. }
  1482. }
  1483. }).apply(/** @type {TODO} */ (compiler));
  1484. }
  1485. }
  1486. ]);
  1487. F(optimization, "nodeEnv", () => {
  1488. if (production) return "production";
  1489. if (development) return "development";
  1490. return false;
  1491. });
  1492. const { splitChunks } = optimization;
  1493. if (splitChunks) {
  1494. A(splitChunks, "defaultSizeTypes", () =>
  1495. css ? ["javascript", "css", "unknown"] : ["javascript", "unknown"]
  1496. );
  1497. D(splitChunks, "hidePathInfo", production);
  1498. D(splitChunks, "chunks", "async");
  1499. D(splitChunks, "usedExports", optimization.usedExports === true);
  1500. D(splitChunks, "minChunks", 1);
  1501. F(splitChunks, "minSize", () => (production ? 20000 : 10000));
  1502. F(splitChunks, "minRemainingSize", () => (development ? 0 : undefined));
  1503. F(splitChunks, "enforceSizeThreshold", () => (production ? 50000 : 30000));
  1504. F(splitChunks, "maxAsyncRequests", () => (production ? 30 : Infinity));
  1505. F(splitChunks, "maxInitialRequests", () => (production ? 30 : Infinity));
  1506. D(splitChunks, "automaticNameDelimiter", "-");
  1507. const cacheGroups =
  1508. /** @type {NonNullable<OptimizationSplitChunksOptions["cacheGroups"]>} */
  1509. (splitChunks.cacheGroups);
  1510. F(cacheGroups, "default", () => ({
  1511. idHint: "",
  1512. reuseExistingChunk: true,
  1513. minChunks: 2,
  1514. priority: -20
  1515. }));
  1516. F(cacheGroups, "defaultVendors", () => ({
  1517. idHint: "vendors",
  1518. reuseExistingChunk: true,
  1519. test: NODE_MODULES_REGEXP,
  1520. priority: -10
  1521. }));
  1522. }
  1523. };
  1524. /**
  1525. * @param {object} options options
  1526. * @param {boolean} options.cache is cache enable
  1527. * @param {string} options.context build context
  1528. * @param {TargetProperties | false} options.targetProperties target properties
  1529. * @param {Mode} options.mode mode
  1530. * @param {boolean} options.css is css enabled
  1531. * @returns {ResolveOptions} resolve options
  1532. */
  1533. const getResolveDefaults = ({
  1534. cache,
  1535. context,
  1536. targetProperties,
  1537. mode,
  1538. css
  1539. }) => {
  1540. /** @type {string[]} */
  1541. const conditions = ["webpack"];
  1542. conditions.push(mode === "development" ? "development" : "production");
  1543. if (targetProperties) {
  1544. if (targetProperties.webworker) conditions.push("worker");
  1545. if (targetProperties.node) conditions.push("node");
  1546. if (targetProperties.web) conditions.push("browser");
  1547. if (targetProperties.electron) conditions.push("electron");
  1548. if (targetProperties.nwjs) conditions.push("nwjs");
  1549. }
  1550. const jsExtensions = [".js", ".json", ".wasm"];
  1551. const tp = targetProperties;
  1552. const browserField =
  1553. tp && tp.web && (!tp.node || (tp.electron && tp.electronRenderer));
  1554. /** @type {() => ResolveOptions} */
  1555. const cjsDeps = () => ({
  1556. aliasFields: browserField ? ["browser"] : [],
  1557. mainFields: browserField ? ["browser", "module", "..."] : ["module", "..."],
  1558. conditionNames: ["require", "module", "..."],
  1559. extensions: [...jsExtensions]
  1560. });
  1561. /** @type {() => ResolveOptions} */
  1562. const esmDeps = () => ({
  1563. aliasFields: browserField ? ["browser"] : [],
  1564. mainFields: browserField ? ["browser", "module", "..."] : ["module", "..."],
  1565. conditionNames: ["import", "module", "..."],
  1566. extensions: [...jsExtensions]
  1567. });
  1568. /** @type {ResolveOptions} */
  1569. const resolveOptions = {
  1570. cache,
  1571. modules: ["node_modules"],
  1572. conditionNames: conditions,
  1573. mainFiles: ["index"],
  1574. extensions: [],
  1575. aliasFields: [],
  1576. exportsFields: ["exports"],
  1577. roots: [context],
  1578. mainFields: ["main"],
  1579. importsFields: ["imports"],
  1580. byDependency: {
  1581. wasm: esmDeps(),
  1582. esm: esmDeps(),
  1583. loaderImport: esmDeps(),
  1584. url: {
  1585. preferRelative: true
  1586. },
  1587. worker: {
  1588. ...esmDeps(),
  1589. preferRelative: true
  1590. },
  1591. commonjs: cjsDeps(),
  1592. amd: cjsDeps(),
  1593. // for backward-compat: loadModule
  1594. loader: cjsDeps(),
  1595. // for backward-compat: Custom Dependency
  1596. unknown: cjsDeps(),
  1597. // for backward-compat: getResolve without dependencyType
  1598. undefined: cjsDeps()
  1599. }
  1600. };
  1601. if (css) {
  1602. const styleConditions = [];
  1603. styleConditions.push("webpack");
  1604. styleConditions.push(mode === "development" ? "development" : "production");
  1605. styleConditions.push("style");
  1606. /** @type {NonNullable<ResolveOptions["byDependency"]>} */
  1607. (resolveOptions.byDependency)["css-import"] = {
  1608. // We avoid using any main files because we have to be consistent with CSS `@import`
  1609. // and CSS `@import` does not handle `main` files in directories,
  1610. // you should always specify the full URL for styles
  1611. mainFiles: [],
  1612. mainFields: ["style", "..."],
  1613. conditionNames: styleConditions,
  1614. extensions: [".css"],
  1615. preferRelative: true
  1616. };
  1617. }
  1618. return resolveOptions;
  1619. };
  1620. /**
  1621. * @param {object} options options
  1622. * @param {boolean} options.cache is cache enable
  1623. * @returns {ResolveOptions} resolve options
  1624. */
  1625. const getResolveLoaderDefaults = ({ cache }) => {
  1626. /** @type {ResolveOptions} */
  1627. const resolveOptions = {
  1628. cache,
  1629. conditionNames: ["loader", "require", "node"],
  1630. exportsFields: ["exports"],
  1631. mainFields: ["loader", "main"],
  1632. extensions: [".js"],
  1633. mainFiles: ["index"]
  1634. };
  1635. return resolveOptions;
  1636. };
  1637. /**
  1638. * @param {InfrastructureLogging} infrastructureLogging options
  1639. * @returns {void}
  1640. */
  1641. const applyInfrastructureLoggingDefaults = infrastructureLogging => {
  1642. F(infrastructureLogging, "stream", () => process.stderr);
  1643. const tty =
  1644. /** @type {EXPECTED_ANY} */ (infrastructureLogging.stream).isTTY &&
  1645. process.env.TERM !== "dumb";
  1646. D(infrastructureLogging, "level", "info");
  1647. D(infrastructureLogging, "debug", false);
  1648. D(infrastructureLogging, "colors", tty);
  1649. D(infrastructureLogging, "appendOnly", !tty);
  1650. };
  1651. module.exports.applyWebpackOptionsBaseDefaults =
  1652. applyWebpackOptionsBaseDefaults;
  1653. module.exports.applyWebpackOptionsDefaults = applyWebpackOptionsDefaults;
  1654. module.exports.DEFAULTS = DEFAULTS;