Compilation.js 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const asyncLib = require("neo-async");
  7. const util = require("util");
  8. const { CachedSource } = require("webpack-sources");
  9. const {
  10. Tapable,
  11. SyncHook,
  12. SyncBailHook,
  13. SyncWaterfallHook,
  14. AsyncSeriesHook
  15. } = require("tapable");
  16. const EntryModuleNotFoundError = require("./EntryModuleNotFoundError");
  17. const ModuleNotFoundError = require("./ModuleNotFoundError");
  18. const ModuleDependencyWarning = require("./ModuleDependencyWarning");
  19. const ModuleDependencyError = require("./ModuleDependencyError");
  20. const ChunkGroup = require("./ChunkGroup");
  21. const Chunk = require("./Chunk");
  22. const Entrypoint = require("./Entrypoint");
  23. const MainTemplate = require("./MainTemplate");
  24. const ChunkTemplate = require("./ChunkTemplate");
  25. const HotUpdateChunkTemplate = require("./HotUpdateChunkTemplate");
  26. const ModuleTemplate = require("./ModuleTemplate");
  27. const RuntimeTemplate = require("./RuntimeTemplate");
  28. const ChunkRenderError = require("./ChunkRenderError");
  29. const AsyncDependencyToInitialChunkError = require("./AsyncDependencyToInitialChunkError");
  30. const Stats = require("./Stats");
  31. const Semaphore = require("./util/Semaphore");
  32. const createHash = require("./util/createHash");
  33. const Queue = require("./util/Queue");
  34. const SortableSet = require("./util/SortableSet");
  35. const GraphHelpers = require("./GraphHelpers");
  36. const ModuleDependency = require("./dependencies/ModuleDependency");
  37. const compareLocations = require("./compareLocations");
  38. /** @typedef {import("./Module")} Module */
  39. /** @typedef {import("./Compiler")} Compiler */
  40. /** @typedef {import("webpack-sources").Source} Source */
  41. /** @typedef {import("./WebpackError")} WebpackError */
  42. /** @typedef {import("./DependenciesBlockVariable")} DependenciesBlockVariable */
  43. /** @typedef {import("./dependencies/SingleEntryDependency")} SingleEntryDependency */
  44. /** @typedef {import("./dependencies/MultiEntryDependency")} MultiEntryDependency */
  45. /** @typedef {import("./dependencies/DllEntryDependency")} DllEntryDependency */
  46. /** @typedef {import("./dependencies/DependencyReference")} DependencyReference */
  47. /** @typedef {import("./DependenciesBlock")} DependenciesBlock */
  48. /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
  49. /** @typedef {import("./Dependency")} Dependency */
  50. /** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
  51. /** @typedef {import("./Dependency").DependencyTemplate} DependencyTemplate */
  52. /** @typedef {import("./util/createHash").Hash} Hash */
  53. // TODO use @callback
  54. /** @typedef {{[assetName: string]: Source}} CompilationAssets */
  55. /** @typedef {(err: Error|null, result?: Module) => void } ModuleCallback */
  56. /** @typedef {(err?: Error|null, result?: Module) => void } ModuleChainCallback */
  57. /** @typedef {(module: Module) => void} OnModuleCallback */
  58. /** @typedef {(err?: Error|null) => void} Callback */
  59. /** @typedef {(d: Dependency) => any} DepBlockVarDependenciesCallback */
  60. /** @typedef {new (...args: any[]) => Dependency} DepConstructor */
  61. /** @typedef {{apply: () => void}} Plugin */
  62. /**
  63. * @typedef {Object} ModuleFactoryCreateDataContextInfo
  64. * @property {string} issuer
  65. * @property {string} compiler
  66. */
  67. /**
  68. * @typedef {Object} ModuleFactoryCreateData
  69. * @property {ModuleFactoryCreateDataContextInfo} contextInfo
  70. * @property {any=} resolveOptions
  71. * @property {string} context
  72. * @property {Dependency[]} dependencies
  73. */
  74. /**
  75. * @typedef {Object} ModuleFactory
  76. * @property {(data: ModuleFactoryCreateData, callback: ModuleCallback) => any} create
  77. */
  78. /**
  79. * @typedef {Object} SortedDependency
  80. * @property {ModuleFactory} factory
  81. * @property {Dependency[]} dependencies
  82. */
  83. /**
  84. * @typedef {Object} DependenciesBlockLike
  85. * @property {Dependency[]} dependencies
  86. * @property {AsyncDependenciesBlock[]} blocks
  87. * @property {DependenciesBlockVariable[]} variables
  88. */
  89. /**
  90. * @param {Chunk} a first chunk to sort by id
  91. * @param {Chunk} b second chunk to sort by id
  92. * @returns {-1|0|1} sort value
  93. */
  94. const byId = (a, b) => {
  95. if (typeof a.id !== typeof b.id) {
  96. return typeof a.id < typeof b.id ? -1 : 1;
  97. }
  98. if (a.id < b.id) return -1;
  99. if (a.id > b.id) return 1;
  100. return 0;
  101. };
  102. /**
  103. * @param {Module} a first module to sort by
  104. * @param {Module} b second module to sort by
  105. * @returns {-1|0|1} sort value
  106. */
  107. const byIdOrIdentifier = (a, b) => {
  108. if (typeof a.id !== typeof b.id) {
  109. return typeof a.id < typeof b.id ? -1 : 1;
  110. }
  111. if (a.id < b.id) return -1;
  112. if (a.id > b.id) return 1;
  113. const identA = a.identifier();
  114. const identB = b.identifier();
  115. if (identA < identB) return -1;
  116. if (identA > identB) return 1;
  117. return 0;
  118. };
  119. /**
  120. * @param {Module} a first module to sort by
  121. * @param {Module} b second module to sort by
  122. * @returns {-1|0|1} sort value
  123. */
  124. const byIndexOrIdentifier = (a, b) => {
  125. if (a.index < b.index) return -1;
  126. if (a.index > b.index) return 1;
  127. const identA = a.identifier();
  128. const identB = b.identifier();
  129. if (identA < identB) return -1;
  130. if (identA > identB) return 1;
  131. return 0;
  132. };
  133. /**
  134. * @param {Compilation} a first compilation to sort by
  135. * @param {Compilation} b second compilation to sort by
  136. * @returns {-1|0|1} sort value
  137. */
  138. const byNameOrHash = (a, b) => {
  139. if (a.name < b.name) return -1;
  140. if (a.name > b.name) return 1;
  141. if (a.fullHash < b.fullHash) return -1;
  142. if (a.fullHash > b.fullHash) return 1;
  143. return 0;
  144. };
  145. /**
  146. * @template T
  147. * @param {Set<T>} a first set
  148. * @param {Set<T>} b second set
  149. * @returns {number} cmp
  150. */
  151. const bySetSize = (a, b) => {
  152. return a.size - b.size;
  153. };
  154. /**
  155. * @param {DependenciesBlockVariable[]} variables DepBlock Variables to iterate over
  156. * @param {DepBlockVarDependenciesCallback} fn callback to apply on iterated elements
  157. * @returns {void}
  158. */
  159. const iterationBlockVariable = (variables, fn) => {
  160. for (
  161. let indexVariable = 0;
  162. indexVariable < variables.length;
  163. indexVariable++
  164. ) {
  165. const varDep = variables[indexVariable].dependencies;
  166. for (let indexVDep = 0; indexVDep < varDep.length; indexVDep++) {
  167. fn(varDep[indexVDep]);
  168. }
  169. }
  170. };
  171. /**
  172. * @template T
  173. * @param {T[]} arr array of elements to iterate over
  174. * @param {function(T): void} fn callback applied to each element
  175. * @returns {void}
  176. */
  177. const iterationOfArrayCallback = (arr, fn) => {
  178. for (let index = 0; index < arr.length; index++) {
  179. fn(arr[index]);
  180. }
  181. };
  182. /**
  183. * @template T
  184. * @param {Set<T>} set set to add items to
  185. * @param {Set<T>} otherSet set to add items from
  186. * @returns {void}
  187. */
  188. const addAllToSet = (set, otherSet) => {
  189. for (const item of otherSet) {
  190. set.add(item);
  191. }
  192. };
  193. class Compilation extends Tapable {
  194. /**
  195. * Creates an instance of Compilation.
  196. * @param {Compiler} compiler the compiler which created the compilation
  197. */
  198. constructor(compiler) {
  199. super();
  200. this.hooks = {
  201. /** @type {SyncHook<Module>} */
  202. buildModule: new SyncHook(["module"]),
  203. /** @type {SyncHook<Module>} */
  204. rebuildModule: new SyncHook(["module"]),
  205. /** @type {SyncHook<Module, Error>} */
  206. failedModule: new SyncHook(["module", "error"]),
  207. /** @type {SyncHook<Module>} */
  208. succeedModule: new SyncHook(["module"]),
  209. /** @type {SyncHook<Dependency, string>} */
  210. addEntry: new SyncHook(["entry", "name"]),
  211. /** @type {SyncHook<Dependency, string, Error>} */
  212. failedEntry: new SyncHook(["entry", "name", "error"]),
  213. /** @type {SyncHook<Dependency, string, Module>} */
  214. succeedEntry: new SyncHook(["entry", "name", "module"]),
  215. /** @type {SyncWaterfallHook<DependencyReference, Dependency, Module>} */
  216. dependencyReference: new SyncWaterfallHook([
  217. "dependencyReference",
  218. "dependency",
  219. "module"
  220. ]),
  221. /** @type {SyncHook<Module[]>} */
  222. finishModules: new SyncHook(["modules"]),
  223. /** @type {SyncHook<Module>} */
  224. finishRebuildingModule: new SyncHook(["module"]),
  225. /** @type {SyncHook} */
  226. unseal: new SyncHook([]),
  227. /** @type {SyncHook} */
  228. seal: new SyncHook([]),
  229. /** @type {SyncHook} */
  230. beforeChunks: new SyncHook([]),
  231. /** @type {SyncHook<Chunk[]>} */
  232. afterChunks: new SyncHook(["chunks"]),
  233. /** @type {SyncBailHook<Module[]>} */
  234. optimizeDependenciesBasic: new SyncBailHook(["modules"]),
  235. /** @type {SyncBailHook<Module[]>} */
  236. optimizeDependencies: new SyncBailHook(["modules"]),
  237. /** @type {SyncBailHook<Module[]>} */
  238. optimizeDependenciesAdvanced: new SyncBailHook(["modules"]),
  239. /** @type {SyncBailHook<Module[]>} */
  240. afterOptimizeDependencies: new SyncHook(["modules"]),
  241. /** @type {SyncHook} */
  242. optimize: new SyncHook([]),
  243. /** @type {SyncBailHook<Module[]>} */
  244. optimizeModulesBasic: new SyncBailHook(["modules"]),
  245. /** @type {SyncBailHook<Module[]>} */
  246. optimizeModules: new SyncBailHook(["modules"]),
  247. /** @type {SyncBailHook<Module[]>} */
  248. optimizeModulesAdvanced: new SyncBailHook(["modules"]),
  249. /** @type {SyncHook<Module[]>} */
  250. afterOptimizeModules: new SyncHook(["modules"]),
  251. /** @type {SyncBailHook<Chunk[], ChunkGroup[]>} */
  252. optimizeChunksBasic: new SyncBailHook(["chunks", "chunkGroups"]),
  253. /** @type {SyncBailHook<Chunk[], ChunkGroup[]>} */
  254. optimizeChunks: new SyncBailHook(["chunks", "chunkGroups"]),
  255. /** @type {SyncBailHook<Chunk[], ChunkGroup[]>} */
  256. optimizeChunksAdvanced: new SyncBailHook(["chunks", "chunkGroups"]),
  257. /** @type {SyncHook<Chunk[], ChunkGroup[]>} */
  258. afterOptimizeChunks: new SyncHook(["chunks", "chunkGroups"]),
  259. /** @type {AsyncSeriesHook<Chunk[], Module[]>} */
  260. optimizeTree: new AsyncSeriesHook(["chunks", "modules"]),
  261. /** @type {SyncHook<Chunk[], Module[]>} */
  262. afterOptimizeTree: new SyncHook(["chunks", "modules"]),
  263. /** @type {SyncBailHook<Chunk[], Module[]>} */
  264. optimizeChunkModulesBasic: new SyncBailHook(["chunks", "modules"]),
  265. /** @type {SyncBailHook<Chunk[], Module[]>} */
  266. optimizeChunkModules: new SyncBailHook(["chunks", "modules"]),
  267. /** @type {SyncBailHook<Chunk[], Module[]>} */
  268. optimizeChunkModulesAdvanced: new SyncBailHook(["chunks", "modules"]),
  269. /** @type {SyncHook<Chunk[], Module[]>} */
  270. afterOptimizeChunkModules: new SyncHook(["chunks", "modules"]),
  271. /** @type {SyncBailHook} */
  272. shouldRecord: new SyncBailHook([]),
  273. /** @type {SyncHook<Module[], any>} */
  274. reviveModules: new SyncHook(["modules", "records"]),
  275. /** @type {SyncHook<Module[]>} */
  276. optimizeModuleOrder: new SyncHook(["modules"]),
  277. /** @type {SyncHook<Module[]>} */
  278. advancedOptimizeModuleOrder: new SyncHook(["modules"]),
  279. /** @type {SyncHook<Module[]>} */
  280. beforeModuleIds: new SyncHook(["modules"]),
  281. /** @type {SyncHook<Module[]>} */
  282. moduleIds: new SyncHook(["modules"]),
  283. /** @type {SyncHook<Module[]>} */
  284. optimizeModuleIds: new SyncHook(["modules"]),
  285. /** @type {SyncHook<Module[]>} */
  286. afterOptimizeModuleIds: new SyncHook(["modules"]),
  287. /** @type {SyncHook<Chunk[], any>} */
  288. reviveChunks: new SyncHook(["chunks", "records"]),
  289. /** @type {SyncHook<Chunk[]>} */
  290. optimizeChunkOrder: new SyncHook(["chunks"]),
  291. /** @type {SyncHook<Chunk[]>} */
  292. beforeChunkIds: new SyncHook(["chunks"]),
  293. /** @type {SyncHook<Chunk[]>} */
  294. optimizeChunkIds: new SyncHook(["chunks"]),
  295. /** @type {SyncHook<Chunk[]>} */
  296. afterOptimizeChunkIds: new SyncHook(["chunks"]),
  297. /** @type {SyncHook<Module[], any>} */
  298. recordModules: new SyncHook(["modules", "records"]),
  299. /** @type {SyncHook<Chunk[], any>} */
  300. recordChunks: new SyncHook(["chunks", "records"]),
  301. /** @type {SyncHook} */
  302. beforeHash: new SyncHook([]),
  303. /** @type {SyncHook<Chunk>} */
  304. contentHash: new SyncHook(["chunk"]),
  305. /** @type {SyncHook} */
  306. afterHash: new SyncHook([]),
  307. /** @type {SyncHook<any>} */
  308. recordHash: new SyncHook(["records"]),
  309. /** @type {SyncHook<Compilation, any>} */
  310. record: new SyncHook(["compilation", "records"]),
  311. /** @type {SyncHook} */
  312. beforeModuleAssets: new SyncHook([]),
  313. /** @type {SyncBailHook} */
  314. shouldGenerateChunkAssets: new SyncBailHook([]),
  315. /** @type {SyncHook} */
  316. beforeChunkAssets: new SyncHook([]),
  317. /** @type {SyncHook<Chunk[]>} */
  318. additionalChunkAssets: new SyncHook(["chunks"]),
  319. /** @type {AsyncSeriesHook} */
  320. additionalAssets: new AsyncSeriesHook([]),
  321. /** @type {AsyncSeriesHook<Chunk[]>} */
  322. optimizeChunkAssets: new AsyncSeriesHook(["chunks"]),
  323. /** @type {SyncHook<Chunk[]>} */
  324. afterOptimizeChunkAssets: new SyncHook(["chunks"]),
  325. /** @type {AsyncSeriesHook<CompilationAssets>} */
  326. optimizeAssets: new AsyncSeriesHook(["assets"]),
  327. /** @type {SyncHook<CompilationAssets>} */
  328. afterOptimizeAssets: new SyncHook(["assets"]),
  329. /** @type {SyncBailHook} */
  330. needAdditionalSeal: new SyncBailHook([]),
  331. /** @type {AsyncSeriesHook} */
  332. afterSeal: new AsyncSeriesHook([]),
  333. /** @type {SyncHook<Chunk, Hash>} */
  334. chunkHash: new SyncHook(["chunk", "chunkHash"]),
  335. /** @type {SyncHook<Module, string>} */
  336. moduleAsset: new SyncHook(["module", "filename"]),
  337. /** @type {SyncHook<Chunk, string>} */
  338. chunkAsset: new SyncHook(["chunk", "filename"]),
  339. /** @type {SyncWaterfallHook<string, TODO>} */
  340. assetPath: new SyncWaterfallHook(["filename", "data"]), // TODO MainTemplate
  341. /** @type {SyncBailHook} */
  342. needAdditionalPass: new SyncBailHook([]),
  343. /** @type {SyncHook<Compiler, string, number>} */
  344. childCompiler: new SyncHook([
  345. "childCompiler",
  346. "compilerName",
  347. "compilerIndex"
  348. ]),
  349. // TODO the following hooks are weirdly located here
  350. // TODO move them for webpack 5
  351. /** @type {SyncHook<object, Module>} */
  352. normalModuleLoader: new SyncHook(["loaderContext", "module"]),
  353. /** @type {SyncBailHook<Chunk[]>} */
  354. optimizeExtractedChunksBasic: new SyncBailHook(["chunks"]),
  355. /** @type {SyncBailHook<Chunk[]>} */
  356. optimizeExtractedChunks: new SyncBailHook(["chunks"]),
  357. /** @type {SyncBailHook<Chunk[]>} */
  358. optimizeExtractedChunksAdvanced: new SyncBailHook(["chunks"]),
  359. /** @type {SyncHook<Chunk[]>} */
  360. afterOptimizeExtractedChunks: new SyncHook(["chunks"])
  361. };
  362. this._pluginCompat.tap("Compilation", options => {
  363. switch (options.name) {
  364. case "optimize-tree":
  365. case "additional-assets":
  366. case "optimize-chunk-assets":
  367. case "optimize-assets":
  368. case "after-seal":
  369. options.async = true;
  370. break;
  371. }
  372. });
  373. /** @type {string=} */
  374. this.name = undefined;
  375. /** @type {Compiler} */
  376. this.compiler = compiler;
  377. this.resolverFactory = compiler.resolverFactory;
  378. this.inputFileSystem = compiler.inputFileSystem;
  379. this.requestShortener = compiler.requestShortener;
  380. const options = compiler.options;
  381. this.options = options;
  382. this.outputOptions = options && options.output;
  383. /** @type {boolean=} */
  384. this.bail = options && options.bail;
  385. this.profile = options && options.profile;
  386. this.performance = options && options.performance;
  387. this.mainTemplate = new MainTemplate(this.outputOptions);
  388. this.chunkTemplate = new ChunkTemplate(this.outputOptions);
  389. this.hotUpdateChunkTemplate = new HotUpdateChunkTemplate(
  390. this.outputOptions
  391. );
  392. this.runtimeTemplate = new RuntimeTemplate(
  393. this.outputOptions,
  394. this.requestShortener
  395. );
  396. this.moduleTemplates = {
  397. javascript: new ModuleTemplate(this.runtimeTemplate, "javascript"),
  398. webassembly: new ModuleTemplate(this.runtimeTemplate, "webassembly")
  399. };
  400. this.semaphore = new Semaphore(options.parallelism || 100);
  401. this.entries = [];
  402. /** @private @type {{name: string, request: string, module: Module}[]} */
  403. this._preparedEntrypoints = [];
  404. this.entrypoints = new Map();
  405. /** @type {Chunk[]} */
  406. this.chunks = [];
  407. /** @type {ChunkGroup[]} */
  408. this.chunkGroups = [];
  409. /** @type {Map<string, ChunkGroup>} */
  410. this.namedChunkGroups = new Map();
  411. /** @type {Map<string, Chunk>} */
  412. this.namedChunks = new Map();
  413. /** @type {Module[]} */
  414. this.modules = [];
  415. /** @private @type {Map<string, Module>} */
  416. this._modules = new Map();
  417. this.cache = null;
  418. this.records = null;
  419. /** @type {string[]} */
  420. this.additionalChunkAssets = [];
  421. /** @type {CompilationAssets} */
  422. this.assets = {};
  423. /** @type {WebpackError[]} */
  424. this.errors = [];
  425. /** @type {WebpackError[]} */
  426. this.warnings = [];
  427. /** @type {Compilation[]} */
  428. this.children = [];
  429. /** @type {Map<DepConstructor, ModuleFactory>} */
  430. this.dependencyFactories = new Map();
  431. /** @type {Map<DepConstructor, DependencyTemplate>} */
  432. this.dependencyTemplates = new Map();
  433. // TODO refactor this in webpack 5 to a custom DependencyTemplates class with a hash property
  434. // @ts-ignore
  435. this.dependencyTemplates.set("hash", "");
  436. this.childrenCounters = {};
  437. /** @type {Set<number|string>} */
  438. this.usedChunkIds = null;
  439. /** @type {Set<number>} */
  440. this.usedModuleIds = null;
  441. /** @type {Map<string, number>=} */
  442. this.fileTimestamps = undefined;
  443. /** @type {Map<string, number>=} */
  444. this.contextTimestamps = undefined;
  445. /** @type {Set<string>=} */
  446. this.compilationDependencies = undefined;
  447. /** @private @type {Map<Module, Callback[]>} */
  448. this._buildingModules = new Map();
  449. /** @private @type {Map<Module, Callback[]>} */
  450. this._rebuildingModules = new Map();
  451. }
  452. getStats() {
  453. return new Stats(this);
  454. }
  455. /**
  456. * @typedef {Object} AddModuleResult
  457. * @property {Module} module the added or existing module
  458. * @property {boolean} issuer was this the first request for this module
  459. * @property {boolean} build should the module be build
  460. * @property {boolean} dependencies should dependencies be walked
  461. */
  462. /**
  463. * @param {Module} module module to be added that was created
  464. * @param {any=} cacheGroup cacheGroup it is apart of
  465. * @returns {AddModuleResult} returns meta about whether or not the module had built
  466. * had an issuer, or any dependnecies
  467. */
  468. addModule(module, cacheGroup) {
  469. const identifier = module.identifier();
  470. const alreadyAddedModule = this._modules.get(identifier);
  471. if (alreadyAddedModule) {
  472. return {
  473. module: alreadyAddedModule,
  474. issuer: false,
  475. build: false,
  476. dependencies: false
  477. };
  478. }
  479. const cacheName = (cacheGroup || "m") + identifier;
  480. if (this.cache && this.cache[cacheName]) {
  481. const cacheModule = this.cache[cacheName];
  482. if (typeof cacheModule.updateCacheModule === "function") {
  483. cacheModule.updateCacheModule(module);
  484. }
  485. let rebuild = true;
  486. if (this.fileTimestamps && this.contextTimestamps) {
  487. rebuild = cacheModule.needRebuild(
  488. this.fileTimestamps,
  489. this.contextTimestamps
  490. );
  491. }
  492. if (!rebuild) {
  493. cacheModule.disconnect();
  494. this._modules.set(identifier, cacheModule);
  495. this.modules.push(cacheModule);
  496. for (const err of cacheModule.errors) {
  497. this.errors.push(err);
  498. }
  499. for (const err of cacheModule.warnings) {
  500. this.warnings.push(err);
  501. }
  502. return {
  503. module: cacheModule,
  504. issuer: true,
  505. build: false,
  506. dependencies: true
  507. };
  508. }
  509. cacheModule.unbuild();
  510. module = cacheModule;
  511. }
  512. this._modules.set(identifier, module);
  513. if (this.cache) {
  514. this.cache[cacheName] = module;
  515. }
  516. this.modules.push(module);
  517. return {
  518. module: module,
  519. issuer: true,
  520. build: true,
  521. dependencies: true
  522. };
  523. }
  524. /**
  525. * Fetches a module from a compilation by its identifier
  526. * @param {Module} module the module provided
  527. * @returns {Module} the module requested
  528. */
  529. getModule(module) {
  530. const identifier = module.identifier();
  531. return this._modules.get(identifier);
  532. }
  533. /**
  534. * Attempts to search for a module by its identifier
  535. * @param {string} identifier identifier (usually path) for module
  536. * @returns {Module|undefined} attempt to search for module and return it, else undefined
  537. */
  538. findModule(identifier) {
  539. return this._modules.get(identifier);
  540. }
  541. /**
  542. * @param {Module} module module with its callback list
  543. * @param {Callback} callback the callback function
  544. * @returns {void}
  545. */
  546. waitForBuildingFinished(module, callback) {
  547. let callbackList = this._buildingModules.get(module);
  548. if (callbackList) {
  549. callbackList.push(() => callback());
  550. } else {
  551. process.nextTick(callback);
  552. }
  553. }
  554. /**
  555. * Builds the module object
  556. *
  557. * @param {Module} module module to be built
  558. * @param {boolean} optional optional flag
  559. * @param {Module=} origin origin module this module build was requested from
  560. * @param {Dependency[]=} dependencies optional dependencies from the module to be built
  561. * @param {TODO} thisCallback the callback
  562. * @returns {TODO} returns the callback function with results
  563. */
  564. buildModule(module, optional, origin, dependencies, thisCallback) {
  565. let callbackList = this._buildingModules.get(module);
  566. if (callbackList) {
  567. callbackList.push(thisCallback);
  568. return;
  569. }
  570. this._buildingModules.set(module, (callbackList = [thisCallback]));
  571. const callback = err => {
  572. this._buildingModules.delete(module);
  573. for (const cb of callbackList) {
  574. cb(err);
  575. }
  576. };
  577. this.hooks.buildModule.call(module);
  578. module.build(
  579. this.options,
  580. this,
  581. this.resolverFactory.get("normal", module.resolveOptions),
  582. this.inputFileSystem,
  583. error => {
  584. const errors = module.errors;
  585. for (let indexError = 0; indexError < errors.length; indexError++) {
  586. const err = errors[indexError];
  587. err.origin = origin;
  588. err.dependencies = dependencies;
  589. if (optional) {
  590. this.warnings.push(err);
  591. } else {
  592. this.errors.push(err);
  593. }
  594. }
  595. const warnings = module.warnings;
  596. for (
  597. let indexWarning = 0;
  598. indexWarning < warnings.length;
  599. indexWarning++
  600. ) {
  601. const war = warnings[indexWarning];
  602. war.origin = origin;
  603. war.dependencies = dependencies;
  604. this.warnings.push(war);
  605. }
  606. const originalMap = module.dependencies.reduce((map, v, i) => {
  607. map.set(v, i);
  608. return map;
  609. }, new Map());
  610. module.dependencies.sort((a, b) => {
  611. const cmp = compareLocations(a.loc, b.loc);
  612. if (cmp) return cmp;
  613. return originalMap.get(a) - originalMap.get(b);
  614. });
  615. if (error) {
  616. this.hooks.failedModule.call(module, error);
  617. return callback(error);
  618. }
  619. this.hooks.succeedModule.call(module);
  620. return callback();
  621. }
  622. );
  623. }
  624. /**
  625. * @param {Module} module to be processed for deps
  626. * @param {ModuleCallback} callback callback to be triggered
  627. * @returns {void}
  628. */
  629. processModuleDependencies(module, callback) {
  630. const dependencies = new Map();
  631. const addDependency = dep => {
  632. const resourceIdent = dep.getResourceIdentifier();
  633. if (resourceIdent) {
  634. const factory = this.dependencyFactories.get(dep.constructor);
  635. if (factory === undefined) {
  636. throw new Error(
  637. `No module factory available for dependency type: ${
  638. dep.constructor.name
  639. }`
  640. );
  641. }
  642. let innerMap = dependencies.get(factory);
  643. if (innerMap === undefined) {
  644. dependencies.set(factory, (innerMap = new Map()));
  645. }
  646. let list = innerMap.get(resourceIdent);
  647. if (list === undefined) innerMap.set(resourceIdent, (list = []));
  648. list.push(dep);
  649. }
  650. };
  651. const addDependenciesBlock = block => {
  652. if (block.dependencies) {
  653. iterationOfArrayCallback(block.dependencies, addDependency);
  654. }
  655. if (block.blocks) {
  656. iterationOfArrayCallback(block.blocks, addDependenciesBlock);
  657. }
  658. if (block.variables) {
  659. iterationBlockVariable(block.variables, addDependency);
  660. }
  661. };
  662. try {
  663. addDependenciesBlock(module);
  664. } catch (e) {
  665. callback(e);
  666. }
  667. const sortedDependencies = [];
  668. for (const pair1 of dependencies) {
  669. for (const pair2 of pair1[1]) {
  670. sortedDependencies.push({
  671. factory: pair1[0],
  672. dependencies: pair2[1]
  673. });
  674. }
  675. }
  676. this.addModuleDependencies(
  677. module,
  678. sortedDependencies,
  679. this.bail,
  680. null,
  681. true,
  682. callback
  683. );
  684. }
  685. /**
  686. * @param {Module} module module to add deps to
  687. * @param {SortedDependency[]} dependencies set of sorted dependencies to iterate through
  688. * @param {(boolean|null)=} bail whether to bail or not
  689. * @param {TODO} cacheGroup optional cacheGroup
  690. * @param {boolean} recursive whether it is recursive traversal
  691. * @param {function} callback callback for when dependencies are finished being added
  692. * @returns {void}
  693. */
  694. addModuleDependencies(
  695. module,
  696. dependencies,
  697. bail,
  698. cacheGroup,
  699. recursive,
  700. callback
  701. ) {
  702. const start = this.profile && Date.now();
  703. const currentProfile = this.profile && {};
  704. asyncLib.forEach(
  705. dependencies,
  706. (item, callback) => {
  707. const dependencies = item.dependencies;
  708. const errorAndCallback = err => {
  709. err.origin = module;
  710. err.dependencies = dependencies;
  711. this.errors.push(err);
  712. if (bail) {
  713. callback(err);
  714. } else {
  715. callback();
  716. }
  717. };
  718. const warningAndCallback = err => {
  719. err.origin = module;
  720. this.warnings.push(err);
  721. callback();
  722. };
  723. const semaphore = this.semaphore;
  724. semaphore.acquire(() => {
  725. const factory = item.factory;
  726. factory.create(
  727. {
  728. contextInfo: {
  729. issuer: module.nameForCondition && module.nameForCondition(),
  730. compiler: this.compiler.name
  731. },
  732. resolveOptions: module.resolveOptions,
  733. context: module.context,
  734. dependencies: dependencies
  735. },
  736. (err, dependentModule) => {
  737. let afterFactory;
  738. const isOptional = () => {
  739. return dependencies.every(d => d.optional);
  740. };
  741. const errorOrWarningAndCallback = err => {
  742. if (isOptional()) {
  743. return warningAndCallback(err);
  744. } else {
  745. return errorAndCallback(err);
  746. }
  747. };
  748. if (err) {
  749. semaphore.release();
  750. return errorOrWarningAndCallback(
  751. new ModuleNotFoundError(module, err)
  752. );
  753. }
  754. if (!dependentModule) {
  755. semaphore.release();
  756. return process.nextTick(callback);
  757. }
  758. if (currentProfile) {
  759. afterFactory = Date.now();
  760. currentProfile.factory = afterFactory - start;
  761. }
  762. const iterationDependencies = depend => {
  763. for (let index = 0; index < depend.length; index++) {
  764. const dep = depend[index];
  765. dep.module = dependentModule;
  766. dependentModule.addReason(module, dep);
  767. }
  768. };
  769. const addModuleResult = this.addModule(
  770. dependentModule,
  771. cacheGroup
  772. );
  773. dependentModule = addModuleResult.module;
  774. iterationDependencies(dependencies);
  775. const afterBuild = () => {
  776. if (currentProfile) {
  777. const afterBuilding = Date.now();
  778. currentProfile.building = afterBuilding - afterFactory;
  779. }
  780. if (recursive && addModuleResult.dependencies) {
  781. this.processModuleDependencies(dependentModule, callback);
  782. } else {
  783. return callback();
  784. }
  785. };
  786. if (addModuleResult.issuer) {
  787. if (currentProfile) {
  788. dependentModule.profile = currentProfile;
  789. }
  790. dependentModule.issuer = module;
  791. } else {
  792. if (this.profile) {
  793. if (module.profile) {
  794. const time = Date.now() - start;
  795. if (
  796. !module.profile.dependencies ||
  797. time > module.profile.dependencies
  798. ) {
  799. module.profile.dependencies = time;
  800. }
  801. }
  802. }
  803. }
  804. if (addModuleResult.build) {
  805. this.buildModule(
  806. dependentModule,
  807. isOptional(),
  808. module,
  809. dependencies,
  810. err => {
  811. if (err) {
  812. semaphore.release();
  813. return errorOrWarningAndCallback(err);
  814. }
  815. if (currentProfile) {
  816. const afterBuilding = Date.now();
  817. currentProfile.building = afterBuilding - afterFactory;
  818. }
  819. semaphore.release();
  820. afterBuild();
  821. }
  822. );
  823. } else {
  824. semaphore.release();
  825. this.waitForBuildingFinished(dependentModule, afterBuild);
  826. }
  827. }
  828. );
  829. });
  830. },
  831. err => {
  832. // In V8, the Error objects keep a reference to the functions on the stack. These warnings &
  833. // errors are created inside closures that keep a reference to the Compilation, so errors are
  834. // leaking the Compilation object.
  835. if (err) {
  836. // eslint-disable-next-line no-self-assign
  837. err.stack = err.stack;
  838. return callback(err);
  839. }
  840. return process.nextTick(callback);
  841. }
  842. );
  843. }
  844. /**
  845. *
  846. * @param {string} context context string path
  847. * @param {Dependency} dependency dependency used to create Module chain
  848. * @param {OnModuleCallback} onModule function invoked on modules creation
  849. * @param {ModuleChainCallback} callback callback for when module chain is complete
  850. * @returns {void} will throw if dependency instance is not a valid Dependency
  851. */
  852. _addModuleChain(context, dependency, onModule, callback) {
  853. const start = this.profile && Date.now();
  854. const currentProfile = this.profile && {};
  855. const errorAndCallback = this.bail
  856. ? err => {
  857. callback(err);
  858. }
  859. : err => {
  860. err.dependencies = [dependency];
  861. this.errors.push(err);
  862. callback();
  863. };
  864. if (
  865. typeof dependency !== "object" ||
  866. dependency === null ||
  867. !dependency.constructor
  868. ) {
  869. throw new Error("Parameter 'dependency' must be a Dependency");
  870. }
  871. const Dep = /** @type {DepConstructor} */ (dependency.constructor);
  872. const moduleFactory = this.dependencyFactories.get(Dep);
  873. if (!moduleFactory) {
  874. throw new Error(
  875. `No dependency factory available for this dependency type: ${
  876. dependency.constructor.name
  877. }`
  878. );
  879. }
  880. this.semaphore.acquire(() => {
  881. moduleFactory.create(
  882. {
  883. contextInfo: {
  884. issuer: "",
  885. compiler: this.compiler.name
  886. },
  887. context: context,
  888. dependencies: [dependency]
  889. },
  890. (err, module) => {
  891. if (err) {
  892. this.semaphore.release();
  893. return errorAndCallback(new EntryModuleNotFoundError(err));
  894. }
  895. let afterFactory;
  896. if (currentProfile) {
  897. afterFactory = Date.now();
  898. currentProfile.factory = afterFactory - start;
  899. }
  900. const addModuleResult = this.addModule(module);
  901. module = addModuleResult.module;
  902. onModule(module);
  903. dependency.module = module;
  904. module.addReason(null, dependency);
  905. const afterBuild = () => {
  906. if (currentProfile) {
  907. const afterBuilding = Date.now();
  908. currentProfile.building = afterBuilding - afterFactory;
  909. }
  910. if (addModuleResult.dependencies) {
  911. this.processModuleDependencies(module, err => {
  912. if (err) return callback(err);
  913. callback(null, module);
  914. });
  915. } else {
  916. return callback(null, module);
  917. }
  918. };
  919. if (addModuleResult.issuer) {
  920. if (currentProfile) {
  921. module.profile = currentProfile;
  922. }
  923. }
  924. if (addModuleResult.build) {
  925. this.buildModule(module, false, null, null, err => {
  926. if (err) {
  927. this.semaphore.release();
  928. return errorAndCallback(err);
  929. }
  930. if (currentProfile) {
  931. const afterBuilding = Date.now();
  932. currentProfile.building = afterBuilding - afterFactory;
  933. }
  934. this.semaphore.release();
  935. afterBuild();
  936. });
  937. } else {
  938. this.semaphore.release();
  939. this.waitForBuildingFinished(module, afterBuild);
  940. }
  941. }
  942. );
  943. });
  944. }
  945. /**
  946. *
  947. * @param {string} context context path for entry
  948. * @param {Dependency} entry entry dependency being created
  949. * @param {string} name name of entry
  950. * @param {ModuleCallback} callback callback function
  951. * @returns {void} returns
  952. */
  953. addEntry(context, entry, name, callback) {
  954. this.hooks.addEntry.call(entry, name);
  955. const slot = {
  956. name: name,
  957. // TODO webpack 5 remove `request`
  958. request: null,
  959. module: null
  960. };
  961. if (entry instanceof ModuleDependency) {
  962. slot.request = entry.request;
  963. }
  964. // TODO webpack 5: merge modules instead when multiple entry modules are supported
  965. const idx = this._preparedEntrypoints.findIndex(slot => slot.name === name);
  966. if (idx >= 0) {
  967. // Overwrite existing entrypoint
  968. this._preparedEntrypoints[idx] = slot;
  969. } else {
  970. this._preparedEntrypoints.push(slot);
  971. }
  972. this._addModuleChain(
  973. context,
  974. entry,
  975. module => {
  976. this.entries.push(module);
  977. },
  978. (err, module) => {
  979. if (err) {
  980. this.hooks.failedEntry.call(entry, name, err);
  981. return callback(err);
  982. }
  983. if (module) {
  984. slot.module = module;
  985. } else {
  986. const idx = this._preparedEntrypoints.indexOf(slot);
  987. if (idx >= 0) {
  988. this._preparedEntrypoints.splice(idx, 1);
  989. }
  990. }
  991. this.hooks.succeedEntry.call(entry, name, module);
  992. return callback(null, module);
  993. }
  994. );
  995. }
  996. /**
  997. * @param {string} context context path string
  998. * @param {Dependency} dependency dep used to create module
  999. * @param {ModuleCallback} callback module callback sending module up a level
  1000. * @returns {void}
  1001. */
  1002. prefetch(context, dependency, callback) {
  1003. this._addModuleChain(
  1004. context,
  1005. dependency,
  1006. module => {
  1007. module.prefetched = true;
  1008. },
  1009. callback
  1010. );
  1011. }
  1012. /**
  1013. * @param {Module} module module to be rebuilt
  1014. * @param {Callback} thisCallback callback when module finishes rebuilding
  1015. * @returns {void}
  1016. */
  1017. rebuildModule(module, thisCallback) {
  1018. let callbackList = this._rebuildingModules.get(module);
  1019. if (callbackList) {
  1020. callbackList.push(thisCallback);
  1021. return;
  1022. }
  1023. this._rebuildingModules.set(module, (callbackList = [thisCallback]));
  1024. const callback = err => {
  1025. this._rebuildingModules.delete(module);
  1026. for (const cb of callbackList) {
  1027. cb(err);
  1028. }
  1029. };
  1030. this.hooks.rebuildModule.call(module);
  1031. const oldDependencies = module.dependencies.slice();
  1032. const oldVariables = module.variables.slice();
  1033. const oldBlocks = module.blocks.slice();
  1034. module.unbuild();
  1035. this.buildModule(module, false, module, null, err => {
  1036. if (err) {
  1037. this.hooks.finishRebuildingModule.call(module);
  1038. return callback(err);
  1039. }
  1040. this.processModuleDependencies(module, err => {
  1041. if (err) return callback(err);
  1042. this.removeReasonsOfDependencyBlock(module, {
  1043. dependencies: oldDependencies,
  1044. variables: oldVariables,
  1045. blocks: oldBlocks
  1046. });
  1047. this.hooks.finishRebuildingModule.call(module);
  1048. callback();
  1049. });
  1050. });
  1051. }
  1052. finish() {
  1053. const modules = this.modules;
  1054. this.hooks.finishModules.call(modules);
  1055. for (let index = 0; index < modules.length; index++) {
  1056. const module = modules[index];
  1057. this.reportDependencyErrorsAndWarnings(module, [module]);
  1058. }
  1059. }
  1060. unseal() {
  1061. this.hooks.unseal.call();
  1062. this.chunks.length = 0;
  1063. this.chunkGroups.length = 0;
  1064. this.namedChunks.clear();
  1065. this.namedChunkGroups.clear();
  1066. this.additionalChunkAssets.length = 0;
  1067. this.assets = {};
  1068. for (const module of this.modules) {
  1069. module.unseal();
  1070. }
  1071. }
  1072. /**
  1073. * @param {Callback} callback signals when the seal method is finishes
  1074. * @returns {void}
  1075. */
  1076. seal(callback) {
  1077. this.hooks.seal.call();
  1078. while (
  1079. this.hooks.optimizeDependenciesBasic.call(this.modules) ||
  1080. this.hooks.optimizeDependencies.call(this.modules) ||
  1081. this.hooks.optimizeDependenciesAdvanced.call(this.modules)
  1082. ) {
  1083. /* empty */
  1084. }
  1085. this.hooks.afterOptimizeDependencies.call(this.modules);
  1086. this.hooks.beforeChunks.call();
  1087. for (const preparedEntrypoint of this._preparedEntrypoints) {
  1088. const module = preparedEntrypoint.module;
  1089. const name = preparedEntrypoint.name;
  1090. const chunk = this.addChunk(name);
  1091. const entrypoint = new Entrypoint(name);
  1092. entrypoint.setRuntimeChunk(chunk);
  1093. entrypoint.addOrigin(null, name, preparedEntrypoint.request);
  1094. this.namedChunkGroups.set(name, entrypoint);
  1095. this.entrypoints.set(name, entrypoint);
  1096. this.chunkGroups.push(entrypoint);
  1097. GraphHelpers.connectChunkGroupAndChunk(entrypoint, chunk);
  1098. GraphHelpers.connectChunkAndModule(chunk, module);
  1099. chunk.entryModule = module;
  1100. chunk.name = name;
  1101. this.assignDepth(module);
  1102. }
  1103. this.processDependenciesBlocksForChunkGroups(this.chunkGroups.slice());
  1104. this.sortModules(this.modules);
  1105. this.hooks.afterChunks.call(this.chunks);
  1106. this.hooks.optimize.call();
  1107. while (
  1108. this.hooks.optimizeModulesBasic.call(this.modules) ||
  1109. this.hooks.optimizeModules.call(this.modules) ||
  1110. this.hooks.optimizeModulesAdvanced.call(this.modules)
  1111. ) {
  1112. /* empty */
  1113. }
  1114. this.hooks.afterOptimizeModules.call(this.modules);
  1115. while (
  1116. this.hooks.optimizeChunksBasic.call(this.chunks, this.chunkGroups) ||
  1117. this.hooks.optimizeChunks.call(this.chunks, this.chunkGroups) ||
  1118. this.hooks.optimizeChunksAdvanced.call(this.chunks, this.chunkGroups)
  1119. ) {
  1120. /* empty */
  1121. }
  1122. this.hooks.afterOptimizeChunks.call(this.chunks, this.chunkGroups);
  1123. this.hooks.optimizeTree.callAsync(this.chunks, this.modules, err => {
  1124. if (err) {
  1125. return callback(err);
  1126. }
  1127. this.hooks.afterOptimizeTree.call(this.chunks, this.modules);
  1128. while (
  1129. this.hooks.optimizeChunkModulesBasic.call(this.chunks, this.modules) ||
  1130. this.hooks.optimizeChunkModules.call(this.chunks, this.modules) ||
  1131. this.hooks.optimizeChunkModulesAdvanced.call(this.chunks, this.modules)
  1132. ) {
  1133. /* empty */
  1134. }
  1135. this.hooks.afterOptimizeChunkModules.call(this.chunks, this.modules);
  1136. const shouldRecord = this.hooks.shouldRecord.call() !== false;
  1137. this.hooks.reviveModules.call(this.modules, this.records);
  1138. this.hooks.optimizeModuleOrder.call(this.modules);
  1139. this.hooks.advancedOptimizeModuleOrder.call(this.modules);
  1140. this.hooks.beforeModuleIds.call(this.modules);
  1141. this.hooks.moduleIds.call(this.modules);
  1142. this.applyModuleIds();
  1143. this.hooks.optimizeModuleIds.call(this.modules);
  1144. this.hooks.afterOptimizeModuleIds.call(this.modules);
  1145. this.sortItemsWithModuleIds();
  1146. this.hooks.reviveChunks.call(this.chunks, this.records);
  1147. this.hooks.optimizeChunkOrder.call(this.chunks);
  1148. this.hooks.beforeChunkIds.call(this.chunks);
  1149. this.applyChunkIds();
  1150. this.hooks.optimizeChunkIds.call(this.chunks);
  1151. this.hooks.afterOptimizeChunkIds.call(this.chunks);
  1152. this.sortItemsWithChunkIds();
  1153. if (shouldRecord) {
  1154. this.hooks.recordModules.call(this.modules, this.records);
  1155. this.hooks.recordChunks.call(this.chunks, this.records);
  1156. }
  1157. this.hooks.beforeHash.call();
  1158. this.createHash();
  1159. this.hooks.afterHash.call();
  1160. if (shouldRecord) {
  1161. this.hooks.recordHash.call(this.records);
  1162. }
  1163. this.hooks.beforeModuleAssets.call();
  1164. this.createModuleAssets();
  1165. if (this.hooks.shouldGenerateChunkAssets.call() !== false) {
  1166. this.hooks.beforeChunkAssets.call();
  1167. this.createChunkAssets();
  1168. }
  1169. this.hooks.additionalChunkAssets.call(this.chunks);
  1170. this.summarizeDependencies();
  1171. if (shouldRecord) {
  1172. this.hooks.record.call(this, this.records);
  1173. }
  1174. this.hooks.additionalAssets.callAsync(err => {
  1175. if (err) {
  1176. return callback(err);
  1177. }
  1178. this.hooks.optimizeChunkAssets.callAsync(this.chunks, err => {
  1179. if (err) {
  1180. return callback(err);
  1181. }
  1182. this.hooks.afterOptimizeChunkAssets.call(this.chunks);
  1183. this.hooks.optimizeAssets.callAsync(this.assets, err => {
  1184. if (err) {
  1185. return callback(err);
  1186. }
  1187. this.hooks.afterOptimizeAssets.call(this.assets);
  1188. if (this.hooks.needAdditionalSeal.call()) {
  1189. this.unseal();
  1190. return this.seal(callback);
  1191. }
  1192. return this.hooks.afterSeal.callAsync(callback);
  1193. });
  1194. });
  1195. });
  1196. });
  1197. }
  1198. /**
  1199. * @param {Module[]} modules the modules array on compilation to perform the sort for
  1200. * @returns {void}
  1201. */
  1202. sortModules(modules) {
  1203. // TODO webpack 5: this should only be enabled when `moduleIds: "natural"`
  1204. // TODO move it into a plugin (NaturalModuleIdsPlugin) and use this in WebpackOptionsApply
  1205. // TODO remove this method
  1206. modules.sort(byIndexOrIdentifier);
  1207. }
  1208. /**
  1209. * @param {Module} module moulde to report from
  1210. * @param {DependenciesBlock[]} blocks blocks to report from
  1211. * @returns {void}
  1212. */
  1213. reportDependencyErrorsAndWarnings(module, blocks) {
  1214. for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
  1215. const block = blocks[indexBlock];
  1216. const dependencies = block.dependencies;
  1217. for (let indexDep = 0; indexDep < dependencies.length; indexDep++) {
  1218. const d = dependencies[indexDep];
  1219. const warnings = d.getWarnings();
  1220. if (warnings) {
  1221. for (let indexWar = 0; indexWar < warnings.length; indexWar++) {
  1222. const w = warnings[indexWar];
  1223. const warning = new ModuleDependencyWarning(module, w, d.loc);
  1224. this.warnings.push(warning);
  1225. }
  1226. }
  1227. const errors = d.getErrors();
  1228. if (errors) {
  1229. for (let indexErr = 0; indexErr < errors.length; indexErr++) {
  1230. const e = errors[indexErr];
  1231. const error = new ModuleDependencyError(module, e, d.loc);
  1232. this.errors.push(error);
  1233. }
  1234. }
  1235. }
  1236. this.reportDependencyErrorsAndWarnings(module, block.blocks);
  1237. }
  1238. }
  1239. /**
  1240. * @param {TODO} groupOptions options for the chunk group
  1241. * @param {Module} module the module the references the chunk group
  1242. * @param {DependencyLocation} loc the location from with the chunk group is referenced (inside of module)
  1243. * @param {string} request the request from which the the chunk group is referenced
  1244. * @returns {ChunkGroup} the new or existing chunk group
  1245. */
  1246. addChunkInGroup(groupOptions, module, loc, request) {
  1247. if (typeof groupOptions === "string") {
  1248. groupOptions = { name: groupOptions };
  1249. }
  1250. const name = groupOptions.name;
  1251. if (name) {
  1252. const chunkGroup = this.namedChunkGroups.get(name);
  1253. if (chunkGroup !== undefined) {
  1254. chunkGroup.addOptions(groupOptions);
  1255. if (module) {
  1256. chunkGroup.addOrigin(module, loc, request);
  1257. }
  1258. return chunkGroup;
  1259. }
  1260. }
  1261. const chunkGroup = new ChunkGroup(groupOptions);
  1262. if (module) chunkGroup.addOrigin(module, loc, request);
  1263. const chunk = this.addChunk(name);
  1264. GraphHelpers.connectChunkGroupAndChunk(chunkGroup, chunk);
  1265. this.chunkGroups.push(chunkGroup);
  1266. if (name) {
  1267. this.namedChunkGroups.set(name, chunkGroup);
  1268. }
  1269. return chunkGroup;
  1270. }
  1271. /**
  1272. * This method first looks to see if a name is provided for a new chunk,
  1273. * and first looks to see if any named chunks already exist and reuse that chunk instead.
  1274. *
  1275. * @param {string=} name optional chunk name to be provided
  1276. * @returns {Chunk} create a chunk (invoked during seal event)
  1277. */
  1278. addChunk(name) {
  1279. if (name) {
  1280. const chunk = this.namedChunks.get(name);
  1281. if (chunk !== undefined) {
  1282. return chunk;
  1283. }
  1284. }
  1285. const chunk = new Chunk(name);
  1286. this.chunks.push(chunk);
  1287. if (name) {
  1288. this.namedChunks.set(name, chunk);
  1289. }
  1290. return chunk;
  1291. }
  1292. /**
  1293. * @param {Module} module module to assign depth
  1294. * @returns {void}
  1295. */
  1296. assignDepth(module) {
  1297. const queue = new Set([module]);
  1298. let depth;
  1299. module.depth = 0;
  1300. /**
  1301. * @param {Module} module module for processeing
  1302. * @returns {void}
  1303. */
  1304. const enqueueJob = module => {
  1305. const d = module.depth;
  1306. if (typeof d === "number" && d <= depth) return;
  1307. queue.add(module);
  1308. module.depth = depth;
  1309. };
  1310. /**
  1311. * @param {Dependency} dependency dependency to assign depth to
  1312. * @returns {void}
  1313. */
  1314. const assignDepthToDependency = dependency => {
  1315. if (dependency.module) {
  1316. enqueueJob(dependency.module);
  1317. }
  1318. };
  1319. /**
  1320. * @param {DependenciesBlock} block block to assign depth to
  1321. * @returns {void}
  1322. */
  1323. const assignDepthToDependencyBlock = block => {
  1324. if (block.variables) {
  1325. iterationBlockVariable(block.variables, assignDepthToDependency);
  1326. }
  1327. if (block.dependencies) {
  1328. iterationOfArrayCallback(block.dependencies, assignDepthToDependency);
  1329. }
  1330. if (block.blocks) {
  1331. iterationOfArrayCallback(block.blocks, assignDepthToDependencyBlock);
  1332. }
  1333. };
  1334. for (module of queue) {
  1335. queue.delete(module);
  1336. depth = module.depth;
  1337. depth++;
  1338. assignDepthToDependencyBlock(module);
  1339. }
  1340. }
  1341. /**
  1342. * @param {Module} module the module containing the dependency
  1343. * @param {Dependency} dependency the dependency
  1344. * @returns {DependencyReference} a reference for the dependency
  1345. */
  1346. getDependencyReference(module, dependency) {
  1347. // TODO remove dep.getReference existence check in webpack 5
  1348. if (typeof dependency.getReference !== "function") return null;
  1349. const ref = dependency.getReference();
  1350. if (!ref) return null;
  1351. return this.hooks.dependencyReference.call(ref, dependency, module);
  1352. }
  1353. /**
  1354. * This method creates the Chunk graph from the Module graph
  1355. * @private
  1356. * @param {TODO[]} inputChunkGroups chunk groups which are processed
  1357. * @returns {void}
  1358. */
  1359. processDependenciesBlocksForChunkGroups(inputChunkGroups) {
  1360. // Process is splitting into two parts:
  1361. // Part one traverse the module graph and builds a very basic chunks graph
  1362. // in chunkDependencies.
  1363. // Part two traverse every possible way through the basic chunk graph and
  1364. // tracks the available modules. While traversing it connects chunks with
  1365. // eachother and Blocks with Chunks. It stops traversing when all modules
  1366. // for a chunk are already available. So it doesn't connect unneeded chunks.
  1367. /** @type {Map<ChunkGroup, {block: AsyncDependenciesBlock, chunkGroup: ChunkGroup, couldBeFiltered: boolean}[]>} */
  1368. const chunkDependencies = new Map();
  1369. const allCreatedChunkGroups = new Set();
  1370. // PREPARE
  1371. /** @type {Map<DependenciesBlock, { modules: Module[], blocks: AsyncDependenciesBlock[]}>} */
  1372. const blockInfoMap = new Map();
  1373. /**
  1374. * @param {Dependency} d dependency to iterate over
  1375. * @returns {void}
  1376. */
  1377. const iteratorDependency = d => {
  1378. // We skip Dependencies without Reference
  1379. const ref = this.getDependencyReference(currentModule, d);
  1380. if (!ref) {
  1381. return;
  1382. }
  1383. // We skip Dependencies without Module pointer
  1384. const refModule = ref.module;
  1385. if (!refModule) {
  1386. return;
  1387. }
  1388. // We skip weak Dependencies
  1389. if (ref.weak) {
  1390. return;
  1391. }
  1392. blockInfoModules.add(refModule);
  1393. };
  1394. /**
  1395. * @param {AsyncDependenciesBlock} b blocks to prepare
  1396. * @returns {void}
  1397. */
  1398. const iteratorBlockPrepare = b => {
  1399. blockInfoBlocks.push(b);
  1400. blockQueue.push(b);
  1401. };
  1402. /** @type {Module} */
  1403. let currentModule;
  1404. /** @type {DependenciesBlock} */
  1405. let block;
  1406. /** @type {DependenciesBlock[]} */
  1407. let blockQueue;
  1408. /** @type {Set<Module>} */
  1409. let blockInfoModules;
  1410. /** @type {AsyncDependenciesBlock[]} */
  1411. let blockInfoBlocks;
  1412. for (const module of this.modules) {
  1413. blockQueue = [module];
  1414. currentModule = module;
  1415. while (blockQueue.length > 0) {
  1416. block = blockQueue.pop();
  1417. blockInfoModules = new Set();
  1418. blockInfoBlocks = [];
  1419. if (block.variables) {
  1420. iterationBlockVariable(block.variables, iteratorDependency);
  1421. }
  1422. if (block.dependencies) {
  1423. iterationOfArrayCallback(block.dependencies, iteratorDependency);
  1424. }
  1425. if (block.blocks) {
  1426. iterationOfArrayCallback(block.blocks, iteratorBlockPrepare);
  1427. }
  1428. const blockInfo = {
  1429. modules: Array.from(blockInfoModules),
  1430. blocks: blockInfoBlocks
  1431. };
  1432. blockInfoMap.set(block, blockInfo);
  1433. }
  1434. }
  1435. // PART ONE
  1436. /** @type {Map<ChunkGroup, { index: number, index2: number }>} */
  1437. const chunkGroupCounters = new Map();
  1438. for (const chunkGroup of inputChunkGroups) {
  1439. chunkGroupCounters.set(chunkGroup, { index: 0, index2: 0 });
  1440. }
  1441. let nextFreeModuleIndex = 0;
  1442. let nextFreeModuleIndex2 = 0;
  1443. /** @type {Map<DependenciesBlock, ChunkGroup>} */
  1444. const blockChunkGroups = new Map();
  1445. /** @type {Set<DependenciesBlock>} */
  1446. const blocksWithNestedBlocks = new Set();
  1447. const ADD_AND_ENTER_MODULE = 0;
  1448. const ENTER_MODULE = 1;
  1449. const PROCESS_BLOCK = 2;
  1450. const LEAVE_MODULE = 3;
  1451. /**
  1452. * @typedef {Object} QueueItem
  1453. * @property {number} action
  1454. * @property {DependenciesBlock} block
  1455. * @property {Module} module
  1456. * @property {Chunk} chunk
  1457. * @property {ChunkGroup} chunkGroup
  1458. */
  1459. /**
  1460. * @param {ChunkGroup} chunkGroup chunk group
  1461. * @returns {QueueItem} queue item
  1462. */
  1463. const chunkGroupToQueueItem = chunkGroup => ({
  1464. action: ENTER_MODULE,
  1465. block: chunkGroup.chunks[0].entryModule,
  1466. module: chunkGroup.chunks[0].entryModule,
  1467. chunk: chunkGroup.chunks[0],
  1468. chunkGroup
  1469. });
  1470. // Start with the provided modules/chunks
  1471. /** @type {QueueItem[]} */
  1472. let queue = inputChunkGroups.map(chunkGroupToQueueItem).reverse();
  1473. /** @type {QueueItem[]} */
  1474. let queueDelayed = [];
  1475. /** @type {Module} */
  1476. let module;
  1477. /** @type {Chunk} */
  1478. let chunk;
  1479. /** @type {ChunkGroup} */
  1480. let chunkGroup;
  1481. // For each async Block in graph
  1482. /**
  1483. * @param {AsyncDependenciesBlock} b iterating over each Async DepBlock
  1484. * @returns {void}
  1485. */
  1486. const iteratorBlock = b => {
  1487. // 1. We create a chunk for this Block
  1488. // but only once (blockChunkGroups map)
  1489. let c = blockChunkGroups.get(b);
  1490. if (c === undefined) {
  1491. c = this.namedChunkGroups.get(b.chunkName);
  1492. if (c && c.isInitial()) {
  1493. this.errors.push(
  1494. new AsyncDependencyToInitialChunkError(b.chunkName, module, b.loc)
  1495. );
  1496. c = chunkGroup;
  1497. } else {
  1498. c = this.addChunkInGroup(
  1499. b.groupOptions || b.chunkName,
  1500. module,
  1501. b.loc,
  1502. b.request
  1503. );
  1504. chunkGroupCounters.set(c, { index: 0, index2: 0 });
  1505. blockChunkGroups.set(b, c);
  1506. allCreatedChunkGroups.add(c);
  1507. }
  1508. } else {
  1509. // TODO webpack 5 remove addOptions check
  1510. if (c.addOptions) c.addOptions(b.groupOptions);
  1511. c.addOrigin(module, b.loc, b.request);
  1512. }
  1513. // 2. We store the Block+Chunk mapping as dependency for the chunk
  1514. let deps = chunkDependencies.get(chunkGroup);
  1515. if (!deps) chunkDependencies.set(chunkGroup, (deps = []));
  1516. deps.push({
  1517. block: b,
  1518. chunkGroup: c,
  1519. couldBeFiltered: true
  1520. });
  1521. // 3. We enqueue the DependenciesBlock for traversal
  1522. queueDelayed.push({
  1523. action: PROCESS_BLOCK,
  1524. block: b,
  1525. module: module,
  1526. chunk: c.chunks[0],
  1527. chunkGroup: c
  1528. });
  1529. };
  1530. // Iterative traversal of the Module graph
  1531. // Recursive would be simpler to write but could result in Stack Overflows
  1532. while (queue.length) {
  1533. while (queue.length) {
  1534. const queueItem = queue.pop();
  1535. module = queueItem.module;
  1536. block = queueItem.block;
  1537. chunk = queueItem.chunk;
  1538. chunkGroup = queueItem.chunkGroup;
  1539. switch (queueItem.action) {
  1540. case ADD_AND_ENTER_MODULE: {
  1541. // We connect Module and Chunk when not already done
  1542. if (chunk.addModule(module)) {
  1543. module.addChunk(chunk);
  1544. } else {
  1545. // already connected, skip it
  1546. break;
  1547. }
  1548. }
  1549. // fallthrough
  1550. case ENTER_MODULE: {
  1551. if (chunkGroup !== undefined) {
  1552. const index = chunkGroup.getModuleIndex(module);
  1553. if (index === undefined) {
  1554. chunkGroup.setModuleIndex(
  1555. module,
  1556. chunkGroupCounters.get(chunkGroup).index++
  1557. );
  1558. }
  1559. }
  1560. if (module.index === null) {
  1561. module.index = nextFreeModuleIndex++;
  1562. }
  1563. queue.push({
  1564. action: LEAVE_MODULE,
  1565. block,
  1566. module,
  1567. chunk,
  1568. chunkGroup
  1569. });
  1570. }
  1571. // fallthrough
  1572. case PROCESS_BLOCK: {
  1573. // get prepared block info
  1574. const blockInfo = blockInfoMap.get(block);
  1575. // Traverse all referenced modules
  1576. for (let i = blockInfo.modules.length - 1; i >= 0; i--) {
  1577. const refModule = blockInfo.modules[i];
  1578. if (chunk.containsModule(refModule)) {
  1579. // skip early if already connected
  1580. continue;
  1581. }
  1582. // enqueue the add and enter to enter in the correct order
  1583. // this is relevant with circular dependencies
  1584. queue.push({
  1585. action: ADD_AND_ENTER_MODULE,
  1586. block: refModule,
  1587. module: refModule,
  1588. chunk,
  1589. chunkGroup
  1590. });
  1591. }
  1592. // Traverse all Blocks
  1593. iterationOfArrayCallback(blockInfo.blocks, iteratorBlock);
  1594. if (blockInfo.blocks.length > 0 && module !== block) {
  1595. blocksWithNestedBlocks.add(block);
  1596. }
  1597. break;
  1598. }
  1599. case LEAVE_MODULE: {
  1600. if (chunkGroup !== undefined) {
  1601. const index = chunkGroup.getModuleIndex2(module);
  1602. if (index === undefined) {
  1603. chunkGroup.setModuleIndex2(
  1604. module,
  1605. chunkGroupCounters.get(chunkGroup).index2++
  1606. );
  1607. }
  1608. }
  1609. if (module.index2 === null) {
  1610. module.index2 = nextFreeModuleIndex2++;
  1611. }
  1612. break;
  1613. }
  1614. }
  1615. }
  1616. const tempQueue = queue;
  1617. queue = queueDelayed.reverse();
  1618. queueDelayed = tempQueue;
  1619. }
  1620. // PART TWO
  1621. /** @type {Set<Module>} */
  1622. let newAvailableModules;
  1623. /**
  1624. * @typedef {Object} ChunkGroupInfo
  1625. * @property {Set<Module>} minAvailableModules current minimal set of modules available at this point
  1626. * @property {Set<Module>[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules
  1627. */
  1628. /** @type {Map<ChunkGroup, ChunkGroupInfo>} */
  1629. const chunkGroupInfoMap = new Map();
  1630. /** @type {Queue<ChunkGroup>} */
  1631. const queue2 = new Queue(inputChunkGroups);
  1632. for (const chunkGroup of inputChunkGroups) {
  1633. chunkGroupInfoMap.set(chunkGroup, {
  1634. minAvailableModules: undefined,
  1635. availableModulesToBeMerged: [new Set()]
  1636. });
  1637. }
  1638. /**
  1639. * Helper function to check if all modules of a chunk are available
  1640. *
  1641. * @param {ChunkGroup} chunkGroup the chunkGroup to scan
  1642. * @param {Set<Module>} availableModules the comparitor set
  1643. * @returns {boolean} return true if all modules of a chunk are available
  1644. */
  1645. const areModulesAvailable = (chunkGroup, availableModules) => {
  1646. for (const chunk of chunkGroup.chunks) {
  1647. for (const module of chunk.modulesIterable) {
  1648. if (!availableModules.has(module)) return false;
  1649. }
  1650. }
  1651. return true;
  1652. };
  1653. // For each edge in the basic chunk graph
  1654. /**
  1655. * @param {TODO} dep the dependency used for filtering
  1656. * @returns {boolean} used to filter "edges" (aka Dependencies) that were pointing
  1657. * to modules that are already available. Also filters circular dependencies in the chunks graph
  1658. */
  1659. const filterFn = dep => {
  1660. const depChunkGroup = dep.chunkGroup;
  1661. if (!dep.couldBeFiltered) return true;
  1662. if (blocksWithNestedBlocks.has(dep.block)) return true;
  1663. if (areModulesAvailable(depChunkGroup, newAvailableModules)) {
  1664. return false; // break all modules are already available
  1665. }
  1666. dep.couldBeFiltered = false;
  1667. return true;
  1668. };
  1669. // Iterative traversing of the basic chunk graph
  1670. while (queue2.length) {
  1671. chunkGroup = queue2.dequeue();
  1672. const info = chunkGroupInfoMap.get(chunkGroup);
  1673. const availableModulesToBeMerged = info.availableModulesToBeMerged;
  1674. let minAvailableModules = info.minAvailableModules;
  1675. // 1. Get minimal available modules
  1676. // It doesn't make sense to traverse a chunk again with more available modules.
  1677. // This step calculates the minimal available modules and skips traversal when
  1678. // the list didn't shrink.
  1679. availableModulesToBeMerged.sort(bySetSize);
  1680. let changed = false;
  1681. for (const availableModules of availableModulesToBeMerged) {
  1682. if (minAvailableModules === undefined) {
  1683. minAvailableModules = new Set(availableModules);
  1684. info.minAvailableModules = minAvailableModules;
  1685. changed = true;
  1686. } else {
  1687. for (const m of minAvailableModules) {
  1688. if (!availableModules.has(m)) {
  1689. minAvailableModules.delete(m);
  1690. changed = true;
  1691. }
  1692. }
  1693. }
  1694. }
  1695. availableModulesToBeMerged.length = 0;
  1696. if (!changed) continue;
  1697. // 2. Get the edges at this point of the graph
  1698. const deps = chunkDependencies.get(chunkGroup);
  1699. if (!deps) continue;
  1700. if (deps.length === 0) continue;
  1701. // 3. Create a new Set of available modules at this points
  1702. newAvailableModules = new Set(minAvailableModules);
  1703. for (const chunk of chunkGroup.chunks) {
  1704. for (const m of chunk.modulesIterable) {
  1705. newAvailableModules.add(m);
  1706. }
  1707. }
  1708. // 4. Foreach remaining edge
  1709. const nextChunkGroups = new Set();
  1710. for (let i = 0; i < deps.length; i++) {
  1711. const dep = deps[i];
  1712. // Filter inline, rather than creating a new array from `.filter()`
  1713. if (!filterFn(dep)) {
  1714. continue;
  1715. }
  1716. const depChunkGroup = dep.chunkGroup;
  1717. const depBlock = dep.block;
  1718. // 5. Connect block with chunk
  1719. GraphHelpers.connectDependenciesBlockAndChunkGroup(
  1720. depBlock,
  1721. depChunkGroup
  1722. );
  1723. // 6. Connect chunk with parent
  1724. GraphHelpers.connectChunkGroupParentAndChild(chunkGroup, depChunkGroup);
  1725. nextChunkGroups.add(depChunkGroup);
  1726. }
  1727. // 7. Enqueue further traversal
  1728. for (const nextChunkGroup of nextChunkGroups) {
  1729. let nextInfo = chunkGroupInfoMap.get(nextChunkGroup);
  1730. if (nextInfo === undefined) {
  1731. nextInfo = {
  1732. minAvailableModules: undefined,
  1733. availableModulesToBeMerged: []
  1734. };
  1735. chunkGroupInfoMap.set(nextChunkGroup, nextInfo);
  1736. }
  1737. nextInfo.availableModulesToBeMerged.push(newAvailableModules);
  1738. // As queue deduplicates enqueued items this makes sure that a ChunkGroup
  1739. // is not enqueued twice
  1740. queue2.enqueue(nextChunkGroup);
  1741. }
  1742. }
  1743. // Remove all unconnected chunk groups
  1744. for (const chunkGroup of allCreatedChunkGroups) {
  1745. if (chunkGroup.getNumberOfParents() === 0) {
  1746. for (const chunk of chunkGroup.chunks) {
  1747. const idx = this.chunks.indexOf(chunk);
  1748. if (idx >= 0) this.chunks.splice(idx, 1);
  1749. chunk.remove("unconnected");
  1750. }
  1751. chunkGroup.remove("unconnected");
  1752. }
  1753. }
  1754. }
  1755. /**
  1756. *
  1757. * @param {Module} module module relationship for removal
  1758. * @param {DependenciesBlockLike} block //TODO: good description
  1759. * @returns {void}
  1760. */
  1761. removeReasonsOfDependencyBlock(module, block) {
  1762. const iteratorDependency = d => {
  1763. if (!d.module) {
  1764. return;
  1765. }
  1766. if (d.module.removeReason(module, d)) {
  1767. for (const chunk of d.module.chunksIterable) {
  1768. this.patchChunksAfterReasonRemoval(d.module, chunk);
  1769. }
  1770. }
  1771. };
  1772. if (block.blocks) {
  1773. iterationOfArrayCallback(block.blocks, block =>
  1774. this.removeReasonsOfDependencyBlock(module, block)
  1775. );
  1776. }
  1777. if (block.dependencies) {
  1778. iterationOfArrayCallback(block.dependencies, iteratorDependency);
  1779. }
  1780. if (block.variables) {
  1781. iterationBlockVariable(block.variables, iteratorDependency);
  1782. }
  1783. }
  1784. /**
  1785. * @param {Module} module module to patch tie
  1786. * @param {Chunk} chunk chunk to patch tie
  1787. * @returns {void}
  1788. */
  1789. patchChunksAfterReasonRemoval(module, chunk) {
  1790. if (!module.hasReasons()) {
  1791. this.removeReasonsOfDependencyBlock(module, module);
  1792. }
  1793. if (!module.hasReasonForChunk(chunk)) {
  1794. if (module.removeChunk(chunk)) {
  1795. this.removeChunkFromDependencies(module, chunk);
  1796. }
  1797. }
  1798. }
  1799. /**
  1800. *
  1801. * @param {DependenciesBlock} block block tie for Chunk
  1802. * @param {Chunk} chunk chunk to remove from dep
  1803. * @returns {void}
  1804. */
  1805. removeChunkFromDependencies(block, chunk) {
  1806. const iteratorDependency = d => {
  1807. if (!d.module) {
  1808. return;
  1809. }
  1810. this.patchChunksAfterReasonRemoval(d.module, chunk);
  1811. };
  1812. const blocks = block.blocks;
  1813. for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
  1814. const asyncBlock = blocks[indexBlock];
  1815. // Grab all chunks from the first Block's AsyncDepBlock
  1816. const chunks = asyncBlock.chunkGroup.chunks;
  1817. // For each chunk in chunkGroup
  1818. for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  1819. const iteratedChunk = chunks[indexChunk];
  1820. asyncBlock.chunkGroup.removeChunk(iteratedChunk);
  1821. asyncBlock.chunkGroup.removeParent(iteratedChunk);
  1822. // Recurse
  1823. this.removeChunkFromDependencies(block, iteratedChunk);
  1824. }
  1825. }
  1826. if (block.dependencies) {
  1827. iterationOfArrayCallback(block.dependencies, iteratorDependency);
  1828. }
  1829. if (block.variables) {
  1830. iterationBlockVariable(block.variables, iteratorDependency);
  1831. }
  1832. }
  1833. applyModuleIds() {
  1834. const unusedIds = [];
  1835. let nextFreeModuleId = 0;
  1836. const usedIds = new Set();
  1837. if (this.usedModuleIds) {
  1838. for (const id of this.usedModuleIds) {
  1839. usedIds.add(id);
  1840. }
  1841. }
  1842. const modules1 = this.modules;
  1843. for (let indexModule1 = 0; indexModule1 < modules1.length; indexModule1++) {
  1844. const module1 = modules1[indexModule1];
  1845. if (module1.id !== null) {
  1846. usedIds.add(module1.id);
  1847. }
  1848. }
  1849. if (usedIds.size > 0) {
  1850. let usedIdMax = -1;
  1851. for (const usedIdKey of usedIds) {
  1852. if (typeof usedIdKey !== "number") {
  1853. continue;
  1854. }
  1855. usedIdMax = Math.max(usedIdMax, usedIdKey);
  1856. }
  1857. let lengthFreeModules = (nextFreeModuleId = usedIdMax + 1);
  1858. while (lengthFreeModules--) {
  1859. if (!usedIds.has(lengthFreeModules)) {
  1860. unusedIds.push(lengthFreeModules);
  1861. }
  1862. }
  1863. }
  1864. const modules2 = this.modules;
  1865. for (let indexModule2 = 0; indexModule2 < modules2.length; indexModule2++) {
  1866. const module2 = modules2[indexModule2];
  1867. if (module2.id === null) {
  1868. if (unusedIds.length > 0) {
  1869. module2.id = unusedIds.pop();
  1870. } else {
  1871. module2.id = nextFreeModuleId++;
  1872. }
  1873. }
  1874. }
  1875. }
  1876. applyChunkIds() {
  1877. /** @type {Set<number>} */
  1878. const usedIds = new Set();
  1879. // Get used ids from usedChunkIds property (i. e. from records)
  1880. if (this.usedChunkIds) {
  1881. for (const id of this.usedChunkIds) {
  1882. if (typeof id !== "number") {
  1883. continue;
  1884. }
  1885. usedIds.add(id);
  1886. }
  1887. }
  1888. // Get used ids from existing chunks
  1889. const chunks = this.chunks;
  1890. for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  1891. const chunk = chunks[indexChunk];
  1892. const usedIdValue = chunk.id;
  1893. if (typeof usedIdValue !== "number") {
  1894. continue;
  1895. }
  1896. usedIds.add(usedIdValue);
  1897. }
  1898. // Calculate maximum assigned chunk id
  1899. let nextFreeChunkId = -1;
  1900. for (const id of usedIds) {
  1901. nextFreeChunkId = Math.max(nextFreeChunkId, id);
  1902. }
  1903. nextFreeChunkId++;
  1904. // Determine free chunk ids from 0 to maximum
  1905. /** @type {number[]} */
  1906. const unusedIds = [];
  1907. if (nextFreeChunkId > 0) {
  1908. let index = nextFreeChunkId;
  1909. while (index--) {
  1910. if (!usedIds.has(index)) {
  1911. unusedIds.push(index);
  1912. }
  1913. }
  1914. }
  1915. // Assign ids to chunk which has no id
  1916. for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  1917. const chunk = chunks[indexChunk];
  1918. if (chunk.id === null) {
  1919. if (unusedIds.length > 0) {
  1920. chunk.id = unusedIds.pop();
  1921. } else {
  1922. chunk.id = nextFreeChunkId++;
  1923. }
  1924. }
  1925. if (!chunk.ids) {
  1926. chunk.ids = [chunk.id];
  1927. }
  1928. }
  1929. }
  1930. sortItemsWithModuleIds() {
  1931. this.modules.sort(byIdOrIdentifier);
  1932. const modules = this.modules;
  1933. for (let indexModule = 0; indexModule < modules.length; indexModule++) {
  1934. modules[indexModule].sortItems(false);
  1935. }
  1936. const chunks = this.chunks;
  1937. for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  1938. chunks[indexChunk].sortItems();
  1939. }
  1940. chunks.sort((a, b) => a.compareTo(b));
  1941. }
  1942. sortItemsWithChunkIds() {
  1943. for (const chunkGroup of this.chunkGroups) {
  1944. chunkGroup.sortItems();
  1945. }
  1946. this.chunks.sort(byId);
  1947. for (
  1948. let indexModule = 0;
  1949. indexModule < this.modules.length;
  1950. indexModule++
  1951. ) {
  1952. this.modules[indexModule].sortItems(true);
  1953. }
  1954. const chunks = this.chunks;
  1955. for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  1956. chunks[indexChunk].sortItems();
  1957. }
  1958. /**
  1959. * Used to sort errors and warnings in compilation. this.warnings, and
  1960. * this.errors contribute to the compilation hash and therefore should be
  1961. * updated whenever other references (having a chunk id) are sorted. This preserves the hash
  1962. * integrity
  1963. *
  1964. * @param {WebpackError} a first WebpackError instance (including subclasses)
  1965. * @param {WebpackError} b second WebpackError instance (including subclasses)
  1966. * @returns {-1|0|1} sort order index
  1967. */
  1968. const byMessage = (a, b) => {
  1969. const ma = `${a.message}`;
  1970. const mb = `${b.message}`;
  1971. if (ma < mb) return -1;
  1972. if (mb < ma) return 1;
  1973. return 0;
  1974. };
  1975. this.errors.sort(byMessage);
  1976. this.warnings.sort(byMessage);
  1977. this.children.sort(byNameOrHash);
  1978. }
  1979. summarizeDependencies() {
  1980. this.fileDependencies = new SortableSet(this.compilationDependencies);
  1981. this.contextDependencies = new SortableSet();
  1982. this.missingDependencies = new SortableSet();
  1983. for (
  1984. let indexChildren = 0;
  1985. indexChildren < this.children.length;
  1986. indexChildren++
  1987. ) {
  1988. const child = this.children[indexChildren];
  1989. addAllToSet(this.fileDependencies, child.fileDependencies);
  1990. addAllToSet(this.contextDependencies, child.contextDependencies);
  1991. addAllToSet(this.missingDependencies, child.missingDependencies);
  1992. }
  1993. for (
  1994. let indexModule = 0;
  1995. indexModule < this.modules.length;
  1996. indexModule++
  1997. ) {
  1998. const module = this.modules[indexModule];
  1999. if (module.buildInfo.fileDependencies) {
  2000. addAllToSet(this.fileDependencies, module.buildInfo.fileDependencies);
  2001. }
  2002. if (module.buildInfo.contextDependencies) {
  2003. addAllToSet(
  2004. this.contextDependencies,
  2005. module.buildInfo.contextDependencies
  2006. );
  2007. }
  2008. }
  2009. for (const error of this.errors) {
  2010. if (
  2011. typeof error.missing === "object" &&
  2012. error.missing &&
  2013. error.missing[Symbol.iterator]
  2014. ) {
  2015. addAllToSet(this.missingDependencies, error.missing);
  2016. }
  2017. }
  2018. this.fileDependencies.sort();
  2019. this.contextDependencies.sort();
  2020. this.missingDependencies.sort();
  2021. }
  2022. createHash() {
  2023. const outputOptions = this.outputOptions;
  2024. const hashFunction = outputOptions.hashFunction;
  2025. const hashDigest = outputOptions.hashDigest;
  2026. const hashDigestLength = outputOptions.hashDigestLength;
  2027. const hash = createHash(hashFunction);
  2028. if (outputOptions.hashSalt) {
  2029. hash.update(outputOptions.hashSalt);
  2030. }
  2031. this.mainTemplate.updateHash(hash);
  2032. this.chunkTemplate.updateHash(hash);
  2033. for (const key of Object.keys(this.moduleTemplates).sort()) {
  2034. this.moduleTemplates[key].updateHash(hash);
  2035. }
  2036. for (const child of this.children) {
  2037. hash.update(child.hash);
  2038. }
  2039. for (const warning of this.warnings) {
  2040. hash.update(`${warning.message}`);
  2041. }
  2042. for (const error of this.errors) {
  2043. hash.update(`${error.message}`);
  2044. }
  2045. const modules = this.modules;
  2046. for (let i = 0; i < modules.length; i++) {
  2047. const module = modules[i];
  2048. const moduleHash = createHash(hashFunction);
  2049. module.updateHash(moduleHash);
  2050. module.hash = moduleHash.digest(hashDigest);
  2051. module.renderedHash = module.hash.substr(0, hashDigestLength);
  2052. }
  2053. // clone needed as sort below is inplace mutation
  2054. const chunks = this.chunks.slice();
  2055. /**
  2056. * sort here will bring all "falsy" values to the beginning
  2057. * this is needed as the "hasRuntime()" chunks are dependent on the
  2058. * hashes of the non-runtime chunks.
  2059. */
  2060. chunks.sort((a, b) => {
  2061. const aEntry = a.hasRuntime();
  2062. const bEntry = b.hasRuntime();
  2063. if (aEntry && !bEntry) return 1;
  2064. if (!aEntry && bEntry) return -1;
  2065. return byId(a, b);
  2066. });
  2067. for (let i = 0; i < chunks.length; i++) {
  2068. const chunk = chunks[i];
  2069. const chunkHash = createHash(hashFunction);
  2070. try {
  2071. if (outputOptions.hashSalt) {
  2072. chunkHash.update(outputOptions.hashSalt);
  2073. }
  2074. chunk.updateHash(chunkHash);
  2075. const template = chunk.hasRuntime()
  2076. ? this.mainTemplate
  2077. : this.chunkTemplate;
  2078. template.updateHashForChunk(
  2079. chunkHash,
  2080. chunk,
  2081. this.moduleTemplates.javascript,
  2082. this.dependencyTemplates
  2083. );
  2084. this.hooks.chunkHash.call(chunk, chunkHash);
  2085. chunk.hash = chunkHash.digest(hashDigest);
  2086. hash.update(chunk.hash);
  2087. chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
  2088. this.hooks.contentHash.call(chunk);
  2089. } catch (err) {
  2090. this.errors.push(new ChunkRenderError(chunk, "", err));
  2091. }
  2092. }
  2093. this.fullHash = hash.digest(hashDigest);
  2094. this.hash = this.fullHash.substr(0, hashDigestLength);
  2095. }
  2096. /**
  2097. * @param {string} update extra information
  2098. * @returns {void}
  2099. */
  2100. modifyHash(update) {
  2101. const outputOptions = this.outputOptions;
  2102. const hashFunction = outputOptions.hashFunction;
  2103. const hashDigest = outputOptions.hashDigest;
  2104. const hashDigestLength = outputOptions.hashDigestLength;
  2105. const hash = createHash(hashFunction);
  2106. hash.update(this.fullHash);
  2107. hash.update(update);
  2108. this.fullHash = hash.digest(hashDigest);
  2109. this.hash = this.fullHash.substr(0, hashDigestLength);
  2110. }
  2111. createModuleAssets() {
  2112. for (let i = 0; i < this.modules.length; i++) {
  2113. const module = this.modules[i];
  2114. if (module.buildInfo.assets) {
  2115. for (const assetName of Object.keys(module.buildInfo.assets)) {
  2116. const fileName = this.getPath(assetName);
  2117. this.assets[fileName] = module.buildInfo.assets[assetName];
  2118. this.hooks.moduleAsset.call(module, fileName);
  2119. }
  2120. }
  2121. }
  2122. }
  2123. createChunkAssets() {
  2124. const outputOptions = this.outputOptions;
  2125. const cachedSourceMap = new Map();
  2126. /** @type {Map<string, {hash: string, source: Source, chunk: Chunk}>} */
  2127. const alreadyWrittenFiles = new Map();
  2128. for (let i = 0; i < this.chunks.length; i++) {
  2129. const chunk = this.chunks[i];
  2130. chunk.files = [];
  2131. let source;
  2132. let file;
  2133. let filenameTemplate;
  2134. try {
  2135. const template = chunk.hasRuntime()
  2136. ? this.mainTemplate
  2137. : this.chunkTemplate;
  2138. const manifest = template.getRenderManifest({
  2139. chunk,
  2140. hash: this.hash,
  2141. fullHash: this.fullHash,
  2142. outputOptions,
  2143. moduleTemplates: this.moduleTemplates,
  2144. dependencyTemplates: this.dependencyTemplates
  2145. }); // [{ render(), filenameTemplate, pathOptions, identifier, hash }]
  2146. for (const fileManifest of manifest) {
  2147. const cacheName = fileManifest.identifier;
  2148. const usedHash = fileManifest.hash;
  2149. filenameTemplate = fileManifest.filenameTemplate;
  2150. file = this.getPath(filenameTemplate, fileManifest.pathOptions);
  2151. // check if the same filename was already written by another chunk
  2152. const alreadyWritten = alreadyWrittenFiles.get(file);
  2153. if (alreadyWritten !== undefined) {
  2154. if (alreadyWritten.hash === usedHash) {
  2155. if (this.cache) {
  2156. this.cache[cacheName] = {
  2157. hash: usedHash,
  2158. source: alreadyWritten.source
  2159. };
  2160. }
  2161. chunk.files.push(file);
  2162. this.hooks.chunkAsset.call(chunk, file);
  2163. continue;
  2164. } else {
  2165. throw new Error(
  2166. `Conflict: Multiple chunks emit assets to the same filename ${file}` +
  2167. ` (chunks ${alreadyWritten.chunk.id} and ${chunk.id})`
  2168. );
  2169. }
  2170. }
  2171. if (
  2172. this.cache &&
  2173. this.cache[cacheName] &&
  2174. this.cache[cacheName].hash === usedHash
  2175. ) {
  2176. source = this.cache[cacheName].source;
  2177. } else {
  2178. source = fileManifest.render();
  2179. // Ensure that source is a cached source to avoid additional cost because of repeated access
  2180. if (!(source instanceof CachedSource)) {
  2181. const cacheEntry = cachedSourceMap.get(source);
  2182. if (cacheEntry) {
  2183. source = cacheEntry;
  2184. } else {
  2185. const cachedSource = new CachedSource(source);
  2186. cachedSourceMap.set(source, cachedSource);
  2187. source = cachedSource;
  2188. }
  2189. }
  2190. if (this.cache) {
  2191. this.cache[cacheName] = {
  2192. hash: usedHash,
  2193. source
  2194. };
  2195. }
  2196. }
  2197. if (this.assets[file] && this.assets[file] !== source) {
  2198. throw new Error(
  2199. `Conflict: Multiple assets emit to the same filename ${file}`
  2200. );
  2201. }
  2202. this.assets[file] = source;
  2203. chunk.files.push(file);
  2204. this.hooks.chunkAsset.call(chunk, file);
  2205. alreadyWrittenFiles.set(file, {
  2206. hash: usedHash,
  2207. source,
  2208. chunk
  2209. });
  2210. }
  2211. } catch (err) {
  2212. this.errors.push(
  2213. new ChunkRenderError(chunk, file || filenameTemplate, err)
  2214. );
  2215. }
  2216. }
  2217. }
  2218. /**
  2219. * @param {string} filename used to get asset path with hash
  2220. * @param {TODO=} data // TODO: figure out this param type
  2221. * @returns {string} interpolated path
  2222. */
  2223. getPath(filename, data) {
  2224. data = data || {};
  2225. data.hash = data.hash || this.hash;
  2226. return this.mainTemplate.getAssetPath(filename, data);
  2227. }
  2228. /**
  2229. * This function allows you to run another instance of webpack inside of webpack however as
  2230. * a child with different settings and configurations (if desired) applied. It copies all hooks, plugins
  2231. * from parent (or top level compiler) and creates a child Compilation
  2232. *
  2233. * @param {string} name name of the child compiler
  2234. * @param {TODO} outputOptions // Need to convert config schema to types for this
  2235. * @param {Plugin[]} plugins webpack plugins that will be applied
  2236. * @returns {Compiler} creates a child Compiler instance
  2237. */
  2238. createChildCompiler(name, outputOptions, plugins) {
  2239. const idx = this.childrenCounters[name] || 0;
  2240. this.childrenCounters[name] = idx + 1;
  2241. return this.compiler.createChildCompiler(
  2242. this,
  2243. name,
  2244. idx,
  2245. outputOptions,
  2246. plugins
  2247. );
  2248. }
  2249. checkConstraints() {
  2250. /** @type {Set<number|string>} */
  2251. const usedIds = new Set();
  2252. const modules = this.modules;
  2253. for (let indexModule = 0; indexModule < modules.length; indexModule++) {
  2254. const moduleId = modules[indexModule].id;
  2255. if (moduleId === null) continue;
  2256. if (usedIds.has(moduleId)) {
  2257. throw new Error(`checkConstraints: duplicate module id ${moduleId}`);
  2258. }
  2259. usedIds.add(moduleId);
  2260. }
  2261. const chunks = this.chunks;
  2262. for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  2263. const chunk = chunks[indexChunk];
  2264. if (chunks.indexOf(chunk) !== indexChunk) {
  2265. throw new Error(
  2266. `checkConstraints: duplicate chunk in compilation ${chunk.debugId}`
  2267. );
  2268. }
  2269. }
  2270. for (const chunkGroup of this.chunkGroups) {
  2271. chunkGroup.checkConstraints();
  2272. }
  2273. }
  2274. }
  2275. // TODO remove in webpack 5
  2276. Compilation.prototype.applyPlugins = util.deprecate(
  2277. /**
  2278. * @deprecated
  2279. * @param {string} name Name
  2280. * @param {any[]} args Other arguments
  2281. * @returns {void}
  2282. * @this {Compilation}
  2283. */
  2284. function(name, ...args) {
  2285. this.hooks[
  2286. name.replace(/[- ]([a-z])/g, match => match[1].toUpperCase())
  2287. ].call(...args);
  2288. },
  2289. "Compilation.applyPlugins is deprecated. Use new API on `.hooks` instead"
  2290. );
  2291. // TODO remove in webpack 5
  2292. Object.defineProperty(Compilation.prototype, "moduleTemplate", {
  2293. configurable: false,
  2294. get: util.deprecate(
  2295. /**
  2296. * @deprecated
  2297. * @this {Compilation}
  2298. * @returns {TODO} module template
  2299. */
  2300. function() {
  2301. return this.moduleTemplates.javascript;
  2302. },
  2303. "Compilation.moduleTemplate: Use Compilation.moduleTemplates.javascript instead"
  2304. ),
  2305. set: util.deprecate(
  2306. /**
  2307. * @deprecated
  2308. * @param {ModuleTemplate} value Template value
  2309. * @this {Compilation}
  2310. * @returns {void}
  2311. */
  2312. function(value) {
  2313. this.moduleTemplates.javascript = value;
  2314. },
  2315. "Compilation.moduleTemplate: Use Compilation.moduleTemplates.javascript instead."
  2316. )
  2317. });
  2318. module.exports = Compilation;