Compilation.js 73 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577
  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;