Compilation.js 158 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301
  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 {
  8. HookMap,
  9. SyncHook,
  10. SyncBailHook,
  11. SyncWaterfallHook,
  12. AsyncSeriesHook,
  13. AsyncSeriesBailHook,
  14. AsyncParallelHook
  15. } = require("tapable");
  16. const util = require("util");
  17. const { CachedSource } = require("webpack-sources");
  18. const { MultiItemCache } = require("./CacheFacade");
  19. const Chunk = require("./Chunk");
  20. const ChunkGraph = require("./ChunkGraph");
  21. const ChunkGroup = require("./ChunkGroup");
  22. const ChunkRenderError = require("./ChunkRenderError");
  23. const ChunkTemplate = require("./ChunkTemplate");
  24. const CodeGenerationError = require("./CodeGenerationError");
  25. const CodeGenerationResults = require("./CodeGenerationResults");
  26. const Dependency = require("./Dependency");
  27. const DependencyTemplates = require("./DependencyTemplates");
  28. const Entrypoint = require("./Entrypoint");
  29. const ErrorHelpers = require("./ErrorHelpers");
  30. const FileSystemInfo = require("./FileSystemInfo");
  31. const {
  32. connectChunkGroupAndChunk,
  33. connectChunkGroupParentAndChild
  34. } = require("./GraphHelpers");
  35. const {
  36. makeWebpackError,
  37. tryRunOrWebpackError
  38. } = require("./HookWebpackError");
  39. const MainTemplate = require("./MainTemplate");
  40. const Module = require("./Module");
  41. const ModuleDependencyError = require("./ModuleDependencyError");
  42. const ModuleDependencyWarning = require("./ModuleDependencyWarning");
  43. const ModuleGraph = require("./ModuleGraph");
  44. const ModuleHashingError = require("./ModuleHashingError");
  45. const ModuleNotFoundError = require("./ModuleNotFoundError");
  46. const ModuleProfile = require("./ModuleProfile");
  47. const ModuleRestoreError = require("./ModuleRestoreError");
  48. const ModuleStoreError = require("./ModuleStoreError");
  49. const ModuleTemplate = require("./ModuleTemplate");
  50. const RuntimeGlobals = require("./RuntimeGlobals");
  51. const RuntimeTemplate = require("./RuntimeTemplate");
  52. const Stats = require("./Stats");
  53. const WebpackError = require("./WebpackError");
  54. const buildChunkGraph = require("./buildChunkGraph");
  55. const BuildCycleError = require("./errors/BuildCycleError");
  56. const { Logger, LogType } = require("./logging/Logger");
  57. const StatsFactory = require("./stats/StatsFactory");
  58. const StatsPrinter = require("./stats/StatsPrinter");
  59. const { equals: arrayEquals } = require("./util/ArrayHelpers");
  60. const AsyncQueue = require("./util/AsyncQueue");
  61. const LazySet = require("./util/LazySet");
  62. const { provide } = require("./util/MapHelpers");
  63. const WeakTupleMap = require("./util/WeakTupleMap");
  64. const { cachedCleverMerge } = require("./util/cleverMerge");
  65. const {
  66. compareLocations,
  67. concatComparators,
  68. compareSelect,
  69. compareIds,
  70. compareStringsNumeric,
  71. compareModulesByIdentifier
  72. } = require("./util/comparators");
  73. const createHash = require("./util/createHash");
  74. const {
  75. arrayToSetDeprecation,
  76. soonFrozenObjectDeprecation,
  77. createFakeHook
  78. } = require("./util/deprecation");
  79. const processAsyncTree = require("./util/processAsyncTree");
  80. const { getRuntimeKey } = require("./util/runtime");
  81. const { isSourceEqual } = require("./util/source");
  82. /** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */
  83. /** @typedef {import("webpack-sources").Source} Source */
  84. /** @typedef {import("../declarations/WebpackOptions").EntryDescriptionNormalized} EntryDescription */
  85. /** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
  86. /** @typedef {import("../declarations/WebpackOptions").StatsOptions} StatsOptions */
  87. /** @typedef {import("../declarations/WebpackOptions").WebpackPluginFunction} WebpackPluginFunction */
  88. /** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */
  89. /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
  90. /** @typedef {import("./Cache")} Cache */
  91. /** @typedef {import("./CacheFacade")} CacheFacade */
  92. /** @typedef {import("./ChunkGroup").ChunkGroupOptions} ChunkGroupOptions */
  93. /** @typedef {import("./Compiler")} Compiler */
  94. /** @typedef {import("./Compiler").CompilationParams} CompilationParams */
  95. /** @typedef {import("./DependenciesBlock")} DependenciesBlock */
  96. /** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
  97. /** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */
  98. /** @typedef {import("./DependencyTemplate")} DependencyTemplate */
  99. /** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */
  100. /** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
  101. /** @typedef {import("./ModuleFactory")} ModuleFactory */
  102. /** @typedef {import("./ModuleFactory").ModuleFactoryCreateDataContextInfo} ModuleFactoryCreateDataContextInfo */
  103. /** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
  104. /** @typedef {import("./RequestShortener")} RequestShortener */
  105. /** @typedef {import("./RuntimeModule")} RuntimeModule */
  106. /** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */
  107. /** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions */
  108. /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsAsset} StatsAsset */
  109. /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsError} StatsError */
  110. /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsModule} StatsModule */
  111. /** @typedef {import("./util/Hash")} Hash */
  112. /** @template T @typedef {import("./util/deprecation").FakeHook<T>} FakeHook<T> */
  113. /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
  114. /**
  115. * @callback Callback
  116. * @param {(WebpackError | null)=} err
  117. * @returns {void}
  118. */
  119. /**
  120. * @callback ModuleCallback
  121. * @param {(WebpackError | null)=} err
  122. * @param {Module=} result
  123. * @returns {void}
  124. */
  125. /**
  126. * @callback ModuleFactoryResultCallback
  127. * @param {(WebpackError | null)=} err
  128. * @param {ModuleFactoryResult=} result
  129. * @returns {void}
  130. */
  131. /**
  132. * @callback ModuleOrFactoryResultCallback
  133. * @param {(WebpackError | null)=} err
  134. * @param {Module | ModuleFactoryResult=} result
  135. * @returns {void}
  136. */
  137. /**
  138. * @callback ExecuteModuleCallback
  139. * @param {(WebpackError | null)=} err
  140. * @param {ExecuteModuleResult=} result
  141. * @returns {void}
  142. */
  143. /**
  144. * @callback DepBlockVarDependenciesCallback
  145. * @param {Dependency} dependency
  146. * @returns {any}
  147. */
  148. /** @typedef {new (...args: any[]) => Dependency} DepConstructor */
  149. /** @typedef {Record<string, Source>} CompilationAssets */
  150. /**
  151. * @typedef {Object} AvailableModulesChunkGroupMapping
  152. * @property {ChunkGroup} chunkGroup
  153. * @property {Set<Module>} availableModules
  154. * @property {boolean} needCopy
  155. */
  156. /**
  157. * @typedef {Object} DependenciesBlockLike
  158. * @property {Dependency[]} dependencies
  159. * @property {AsyncDependenciesBlock[]} blocks
  160. */
  161. /**
  162. * @typedef {Object} ChunkPathData
  163. * @property {string|number} id
  164. * @property {string=} name
  165. * @property {string} hash
  166. * @property {function(number): string=} hashWithLength
  167. * @property {(Record<string, string>)=} contentHash
  168. * @property {(Record<string, (length: number) => string>)=} contentHashWithLength
  169. */
  170. /**
  171. * @typedef {Object} ChunkHashContext
  172. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  173. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  174. * @property {ModuleGraph} moduleGraph the module graph
  175. * @property {ChunkGraph} chunkGraph the chunk graph
  176. */
  177. /**
  178. * @typedef {Object} RuntimeRequirementsContext
  179. * @property {ChunkGraph} chunkGraph the chunk graph
  180. * @property {CodeGenerationResults} codeGenerationResults the code generation results
  181. */
  182. /**
  183. * @typedef {Object} ExecuteModuleOptions
  184. * @property {EntryOptions=} entryOptions
  185. */
  186. /**
  187. * @typedef {Object} ExecuteModuleResult
  188. * @property {any} exports
  189. * @property {boolean} cacheable
  190. * @property {Map<string, { source: Source, info: AssetInfo }>} assets
  191. * @property {LazySet<string>} fileDependencies
  192. * @property {LazySet<string>} contextDependencies
  193. * @property {LazySet<string>} missingDependencies
  194. * @property {LazySet<string>} buildDependencies
  195. */
  196. /**
  197. * @typedef {Object} ExecuteModuleArgument
  198. * @property {Module} module
  199. * @property {{ id: string, exports: any, loaded: boolean }=} moduleObject
  200. * @property {any} preparedInfo
  201. * @property {CodeGenerationResult} codeGenerationResult
  202. */
  203. /**
  204. * @typedef {Object} ExecuteModuleContext
  205. * @property {Map<string, { source: Source, info: AssetInfo }>} assets
  206. * @property {Chunk} chunk
  207. * @property {ChunkGraph} chunkGraph
  208. * @property {function(string): any=} __webpack_require__
  209. */
  210. /**
  211. * @typedef {Object} EntryData
  212. * @property {Dependency[]} dependencies dependencies of the entrypoint that should be evaluated at startup
  213. * @property {Dependency[]} includeDependencies dependencies of the entrypoint that should be included but not evaluated
  214. * @property {EntryOptions} options options of the entrypoint
  215. */
  216. /**
  217. * @typedef {Object} LogEntry
  218. * @property {string} type
  219. * @property {any[]} args
  220. * @property {number} time
  221. * @property {string[]=} trace
  222. */
  223. /**
  224. * @typedef {Object} KnownAssetInfo
  225. * @property {boolean=} immutable true, if the asset can be long term cached forever (contains a hash)
  226. * @property {boolean=} minimized whether the asset is minimized
  227. * @property {string | string[]=} fullhash the value(s) of the full hash used for this asset
  228. * @property {string | string[]=} chunkhash the value(s) of the chunk hash used for this asset
  229. * @property {string | string[]=} modulehash the value(s) of the module hash used for this asset
  230. * @property {string | string[]=} contenthash the value(s) of the content hash used for this asset
  231. * @property {string=} sourceFilename when asset was created from a source file (potentially transformed), the original filename relative to compilation context
  232. * @property {number=} size size in bytes, only set after asset has been emitted
  233. * @property {boolean=} development true, when asset is only used for development and doesn't count towards user-facing assets
  234. * @property {boolean=} hotModuleReplacement true, when asset ships data for updating an existing application (HMR)
  235. * @property {boolean=} javascriptModule true, when asset is javascript and an ESM
  236. * @property {Record<string, string | string[]>=} related object of pointers to other assets, keyed by type of relation (only points from parent to child)
  237. */
  238. /** @typedef {KnownAssetInfo & Record<string, any>} AssetInfo */
  239. /**
  240. * @typedef {Object} Asset
  241. * @property {string} name the filename of the asset
  242. * @property {Source} source source of the asset
  243. * @property {AssetInfo} info info about the asset
  244. */
  245. /**
  246. * @typedef {Object} ModulePathData
  247. * @property {string|number} id
  248. * @property {string} hash
  249. * @property {function(number): string=} hashWithLength
  250. */
  251. /**
  252. * @typedef {Object} PathData
  253. * @property {ChunkGraph=} chunkGraph
  254. * @property {string=} hash
  255. * @property {function(number): string=} hashWithLength
  256. * @property {(Chunk|ChunkPathData)=} chunk
  257. * @property {(Module|ModulePathData)=} module
  258. * @property {RuntimeSpec=} runtime
  259. * @property {string=} filename
  260. * @property {string=} basename
  261. * @property {string=} query
  262. * @property {string=} contentHashType
  263. * @property {string=} contentHash
  264. * @property {function(number): string=} contentHashWithLength
  265. * @property {boolean=} noChunkHash
  266. * @property {string=} url
  267. */
  268. /**
  269. * @typedef {Object} KnownNormalizedStatsOptions
  270. * @property {string} context
  271. * @property {RequestShortener} requestShortener
  272. * @property {string} chunksSort
  273. * @property {string} modulesSort
  274. * @property {string} chunkModulesSort
  275. * @property {string} nestedModulesSort
  276. * @property {string} assetsSort
  277. * @property {boolean} ids
  278. * @property {boolean} cachedAssets
  279. * @property {boolean} groupAssetsByEmitStatus
  280. * @property {boolean} groupAssetsByPath
  281. * @property {boolean} groupAssetsByExtension
  282. * @property {number} assetsSpace
  283. * @property {((value: string, asset: StatsAsset) => boolean)[]} excludeAssets
  284. * @property {((name: string, module: StatsModule, type: "module" | "chunk" | "root-of-chunk" | "nested") => boolean)[]} excludeModules
  285. * @property {((warning: StatsError, textValue: string) => boolean)[]} warningsFilter
  286. * @property {boolean} cachedModules
  287. * @property {boolean} orphanModules
  288. * @property {boolean} dependentModules
  289. * @property {boolean} runtimeModules
  290. * @property {boolean} groupModulesByCacheStatus
  291. * @property {boolean} groupModulesByLayer
  292. * @property {boolean} groupModulesByAttributes
  293. * @property {boolean} groupModulesByPath
  294. * @property {boolean} groupModulesByExtension
  295. * @property {boolean} groupModulesByType
  296. * @property {boolean | "auto"} entrypoints
  297. * @property {boolean} chunkGroups
  298. * @property {boolean} chunkGroupAuxiliary
  299. * @property {boolean} chunkGroupChildren
  300. * @property {number} chunkGroupMaxAssets
  301. * @property {number} modulesSpace
  302. * @property {number} chunkModulesSpace
  303. * @property {number} nestedModulesSpace
  304. * @property {false|"none"|"error"|"warn"|"info"|"log"|"verbose"} logging
  305. * @property {((value: string) => boolean)[]} loggingDebug
  306. * @property {boolean} loggingTrace
  307. * @property {any} _env
  308. */
  309. /** @typedef {KnownNormalizedStatsOptions & Omit<StatsOptions, keyof KnownNormalizedStatsOptions> & Record<string, any>} NormalizedStatsOptions */
  310. /**
  311. * @typedef {Object} KnownCreateStatsOptionsContext
  312. * @property {boolean=} forToString
  313. */
  314. /** @typedef {KnownCreateStatsOptionsContext & Record<string, any>} CreateStatsOptionsContext */
  315. /** @type {AssetInfo} */
  316. const EMPTY_ASSET_INFO = Object.freeze({});
  317. const esmDependencyCategory = "esm";
  318. // TODO webpack 6: remove
  319. const deprecatedNormalModuleLoaderHook = util.deprecate(
  320. compilation => {
  321. return require("./NormalModule").getCompilationHooks(compilation).loader;
  322. },
  323. "Compilation.hooks.normalModuleLoader was moved to NormalModule.getCompilationHooks(compilation).loader",
  324. "DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK"
  325. );
  326. // TODO webpack 6: remove
  327. const defineRemovedModuleTemplates = moduleTemplates => {
  328. Object.defineProperties(moduleTemplates, {
  329. asset: {
  330. enumerable: false,
  331. configurable: false,
  332. get: () => {
  333. throw new WebpackError(
  334. "Compilation.moduleTemplates.asset has been removed"
  335. );
  336. }
  337. },
  338. webassembly: {
  339. enumerable: false,
  340. configurable: false,
  341. get: () => {
  342. throw new WebpackError(
  343. "Compilation.moduleTemplates.webassembly has been removed"
  344. );
  345. }
  346. }
  347. });
  348. moduleTemplates = undefined;
  349. };
  350. const byId = compareSelect(
  351. /**
  352. * @param {Chunk} c chunk
  353. * @returns {number | string} id
  354. */ c => c.id,
  355. compareIds
  356. );
  357. const byNameOrHash = concatComparators(
  358. compareSelect(
  359. /**
  360. * @param {Compilation} c compilation
  361. * @returns {string} name
  362. */
  363. c => c.name,
  364. compareIds
  365. ),
  366. compareSelect(
  367. /**
  368. * @param {Compilation} c compilation
  369. * @returns {string} hash
  370. */ c => c.fullHash,
  371. compareIds
  372. )
  373. );
  374. const byMessage = compareSelect(err => `${err.message}`, compareStringsNumeric);
  375. const byModule = compareSelect(
  376. err => (err.module && err.module.identifier()) || "",
  377. compareStringsNumeric
  378. );
  379. const byLocation = compareSelect(err => err.loc, compareLocations);
  380. const compareErrors = concatComparators(byModule, byLocation, byMessage);
  381. /** @type {WeakMap<Dependency, Module & { restoreFromUnsafeCache: Function } | null>} */
  382. const unsafeCacheDependencies = new WeakMap();
  383. /** @type {WeakMap<Module & { restoreFromUnsafeCache: Function }, object>} */
  384. const unsafeCacheData = new WeakMap();
  385. class Compilation {
  386. /**
  387. * Creates an instance of Compilation.
  388. * @param {Compiler} compiler the compiler which created the compilation
  389. * @param {CompilationParams} params the compilation parameters
  390. */
  391. constructor(compiler, params) {
  392. this._backCompat = compiler._backCompat;
  393. const getNormalModuleLoader = () => deprecatedNormalModuleLoaderHook(this);
  394. /** @typedef {{ additionalAssets?: true | Function }} ProcessAssetsAdditionalOptions */
  395. /** @type {AsyncSeriesHook<[CompilationAssets], ProcessAssetsAdditionalOptions>} */
  396. const processAssetsHook = new AsyncSeriesHook(["assets"]);
  397. let savedAssets = new Set();
  398. const popNewAssets = assets => {
  399. let newAssets = undefined;
  400. for (const file of Object.keys(assets)) {
  401. if (savedAssets.has(file)) continue;
  402. if (newAssets === undefined) {
  403. newAssets = Object.create(null);
  404. }
  405. newAssets[file] = assets[file];
  406. savedAssets.add(file);
  407. }
  408. return newAssets;
  409. };
  410. processAssetsHook.intercept({
  411. name: "Compilation",
  412. call: () => {
  413. savedAssets = new Set(Object.keys(this.assets));
  414. },
  415. register: tap => {
  416. const { type, name } = tap;
  417. const { fn, additionalAssets, ...remainingTap } = tap;
  418. const additionalAssetsFn =
  419. additionalAssets === true ? fn : additionalAssets;
  420. const processedAssets = additionalAssetsFn ? new WeakSet() : undefined;
  421. switch (type) {
  422. case "sync":
  423. if (additionalAssetsFn) {
  424. this.hooks.processAdditionalAssets.tap(name, assets => {
  425. if (processedAssets.has(this.assets))
  426. additionalAssetsFn(assets);
  427. });
  428. }
  429. return {
  430. ...remainingTap,
  431. type: "async",
  432. fn: (assets, callback) => {
  433. try {
  434. fn(assets);
  435. } catch (e) {
  436. return callback(e);
  437. }
  438. if (processedAssets !== undefined)
  439. processedAssets.add(this.assets);
  440. const newAssets = popNewAssets(assets);
  441. if (newAssets !== undefined) {
  442. this.hooks.processAdditionalAssets.callAsync(
  443. newAssets,
  444. callback
  445. );
  446. return;
  447. }
  448. callback();
  449. }
  450. };
  451. case "async":
  452. if (additionalAssetsFn) {
  453. this.hooks.processAdditionalAssets.tapAsync(
  454. name,
  455. (assets, callback) => {
  456. if (processedAssets.has(this.assets))
  457. return additionalAssetsFn(assets, callback);
  458. callback();
  459. }
  460. );
  461. }
  462. return {
  463. ...remainingTap,
  464. fn: (assets, callback) => {
  465. fn(assets, err => {
  466. if (err) return callback(err);
  467. if (processedAssets !== undefined)
  468. processedAssets.add(this.assets);
  469. const newAssets = popNewAssets(assets);
  470. if (newAssets !== undefined) {
  471. this.hooks.processAdditionalAssets.callAsync(
  472. newAssets,
  473. callback
  474. );
  475. return;
  476. }
  477. callback();
  478. });
  479. }
  480. };
  481. case "promise":
  482. if (additionalAssetsFn) {
  483. this.hooks.processAdditionalAssets.tapPromise(name, assets => {
  484. if (processedAssets.has(this.assets))
  485. return additionalAssetsFn(assets);
  486. return Promise.resolve();
  487. });
  488. }
  489. return {
  490. ...remainingTap,
  491. fn: assets => {
  492. const p = fn(assets);
  493. if (!p || !p.then) return p;
  494. return p.then(() => {
  495. if (processedAssets !== undefined)
  496. processedAssets.add(this.assets);
  497. const newAssets = popNewAssets(assets);
  498. if (newAssets !== undefined) {
  499. return this.hooks.processAdditionalAssets.promise(
  500. newAssets
  501. );
  502. }
  503. });
  504. }
  505. };
  506. }
  507. }
  508. });
  509. /** @type {SyncHook<[CompilationAssets]>} */
  510. const afterProcessAssetsHook = new SyncHook(["assets"]);
  511. /**
  512. * @template T
  513. * @param {string} name name of the hook
  514. * @param {number} stage new stage
  515. * @param {function(): AsArray<T>} getArgs get old hook function args
  516. * @param {string=} code deprecation code (not deprecated when unset)
  517. * @returns {FakeHook<Pick<AsyncSeriesHook<T>, "tap" | "tapAsync" | "tapPromise" | "name">>} fake hook which redirects
  518. */
  519. const createProcessAssetsHook = (name, stage, getArgs, code) => {
  520. if (!this._backCompat && code) return undefined;
  521. const errorMessage =
  522. reason => `Can't automatically convert plugin using Compilation.hooks.${name} to Compilation.hooks.processAssets because ${reason}.
  523. BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a single Compilation.hooks.processAssets hook.`;
  524. const getOptions = options => {
  525. if (typeof options === "string") options = { name: options };
  526. if (options.stage) {
  527. throw new Error(errorMessage("it's using the 'stage' option"));
  528. }
  529. return { ...options, stage: stage };
  530. };
  531. return createFakeHook(
  532. {
  533. name,
  534. /** @type {AsyncSeriesHook<T>["intercept"]} */
  535. intercept(interceptor) {
  536. throw new Error(errorMessage("it's using 'intercept'"));
  537. },
  538. /** @type {AsyncSeriesHook<T>["tap"]} */
  539. tap: (options, fn) => {
  540. processAssetsHook.tap(getOptions(options), () => fn(...getArgs()));
  541. },
  542. /** @type {AsyncSeriesHook<T>["tapAsync"]} */
  543. tapAsync: (options, fn) => {
  544. processAssetsHook.tapAsync(
  545. getOptions(options),
  546. (assets, callback) =>
  547. /** @type {any} */ (fn)(...getArgs(), callback)
  548. );
  549. },
  550. /** @type {AsyncSeriesHook<T>["tapPromise"]} */
  551. tapPromise: (options, fn) => {
  552. processAssetsHook.tapPromise(getOptions(options), () =>
  553. fn(...getArgs())
  554. );
  555. }
  556. },
  557. `${name} is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option)`,
  558. code
  559. );
  560. };
  561. this.hooks = Object.freeze({
  562. /** @type {SyncHook<[Module]>} */
  563. buildModule: new SyncHook(["module"]),
  564. /** @type {SyncHook<[Module]>} */
  565. rebuildModule: new SyncHook(["module"]),
  566. /** @type {SyncHook<[Module, WebpackError]>} */
  567. failedModule: new SyncHook(["module", "error"]),
  568. /** @type {SyncHook<[Module]>} */
  569. succeedModule: new SyncHook(["module"]),
  570. /** @type {SyncHook<[Module]>} */
  571. stillValidModule: new SyncHook(["module"]),
  572. /** @type {SyncHook<[Dependency, EntryOptions]>} */
  573. addEntry: new SyncHook(["entry", "options"]),
  574. /** @type {SyncHook<[Dependency, EntryOptions, Error]>} */
  575. failedEntry: new SyncHook(["entry", "options", "error"]),
  576. /** @type {SyncHook<[Dependency, EntryOptions, Module]>} */
  577. succeedEntry: new SyncHook(["entry", "options", "module"]),
  578. /** @type {SyncWaterfallHook<[(string[] | ReferencedExport)[], Dependency, RuntimeSpec]>} */
  579. dependencyReferencedExports: new SyncWaterfallHook([
  580. "referencedExports",
  581. "dependency",
  582. "runtime"
  583. ]),
  584. /** @type {SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */
  585. executeModule: new SyncHook(["options", "context"]),
  586. /** @type {AsyncParallelHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */
  587. prepareModuleExecution: new AsyncParallelHook(["options", "context"]),
  588. /** @type {AsyncSeriesHook<[Iterable<Module>]>} */
  589. finishModules: new AsyncSeriesHook(["modules"]),
  590. /** @type {AsyncSeriesHook<[Module]>} */
  591. finishRebuildingModule: new AsyncSeriesHook(["module"]),
  592. /** @type {SyncHook<[]>} */
  593. unseal: new SyncHook([]),
  594. /** @type {SyncHook<[]>} */
  595. seal: new SyncHook([]),
  596. /** @type {SyncHook<[]>} */
  597. beforeChunks: new SyncHook([]),
  598. /** @type {SyncHook<[Iterable<Chunk>]>} */
  599. afterChunks: new SyncHook(["chunks"]),
  600. /** @type {SyncBailHook<[Iterable<Module>]>} */
  601. optimizeDependencies: new SyncBailHook(["modules"]),
  602. /** @type {SyncHook<[Iterable<Module>]>} */
  603. afterOptimizeDependencies: new SyncHook(["modules"]),
  604. /** @type {SyncHook<[]>} */
  605. optimize: new SyncHook([]),
  606. /** @type {SyncBailHook<[Iterable<Module>]>} */
  607. optimizeModules: new SyncBailHook(["modules"]),
  608. /** @type {SyncHook<[Iterable<Module>]>} */
  609. afterOptimizeModules: new SyncHook(["modules"]),
  610. /** @type {SyncBailHook<[Iterable<Chunk>, ChunkGroup[]]>} */
  611. optimizeChunks: new SyncBailHook(["chunks", "chunkGroups"]),
  612. /** @type {SyncHook<[Iterable<Chunk>, ChunkGroup[]]>} */
  613. afterOptimizeChunks: new SyncHook(["chunks", "chunkGroups"]),
  614. /** @type {AsyncSeriesHook<[Iterable<Chunk>, Iterable<Module>]>} */
  615. optimizeTree: new AsyncSeriesHook(["chunks", "modules"]),
  616. /** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
  617. afterOptimizeTree: new SyncHook(["chunks", "modules"]),
  618. /** @type {AsyncSeriesBailHook<[Iterable<Chunk>, Iterable<Module>]>} */
  619. optimizeChunkModules: new AsyncSeriesBailHook(["chunks", "modules"]),
  620. /** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
  621. afterOptimizeChunkModules: new SyncHook(["chunks", "modules"]),
  622. /** @type {SyncBailHook<[], boolean>} */
  623. shouldRecord: new SyncBailHook([]),
  624. /** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */
  625. additionalChunkRuntimeRequirements: new SyncHook([
  626. "chunk",
  627. "runtimeRequirements",
  628. "context"
  629. ]),
  630. /** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext]>>} */
  631. runtimeRequirementInChunk: new HookMap(
  632. () => new SyncBailHook(["chunk", "runtimeRequirements", "context"])
  633. ),
  634. /** @type {SyncHook<[Module, Set<string>, RuntimeRequirementsContext]>} */
  635. additionalModuleRuntimeRequirements: new SyncHook([
  636. "module",
  637. "runtimeRequirements",
  638. "context"
  639. ]),
  640. /** @type {HookMap<SyncBailHook<[Module, Set<string>, RuntimeRequirementsContext]>>} */
  641. runtimeRequirementInModule: new HookMap(
  642. () => new SyncBailHook(["module", "runtimeRequirements", "context"])
  643. ),
  644. /** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */
  645. additionalTreeRuntimeRequirements: new SyncHook([
  646. "chunk",
  647. "runtimeRequirements",
  648. "context"
  649. ]),
  650. /** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext]>>} */
  651. runtimeRequirementInTree: new HookMap(
  652. () => new SyncBailHook(["chunk", "runtimeRequirements", "context"])
  653. ),
  654. /** @type {SyncHook<[RuntimeModule, Chunk]>} */
  655. runtimeModule: new SyncHook(["module", "chunk"]),
  656. /** @type {SyncHook<[Iterable<Module>, any]>} */
  657. reviveModules: new SyncHook(["modules", "records"]),
  658. /** @type {SyncHook<[Iterable<Module>]>} */
  659. beforeModuleIds: new SyncHook(["modules"]),
  660. /** @type {SyncHook<[Iterable<Module>]>} */
  661. moduleIds: new SyncHook(["modules"]),
  662. /** @type {SyncHook<[Iterable<Module>]>} */
  663. optimizeModuleIds: new SyncHook(["modules"]),
  664. /** @type {SyncHook<[Iterable<Module>]>} */
  665. afterOptimizeModuleIds: new SyncHook(["modules"]),
  666. /** @type {SyncHook<[Iterable<Chunk>, any]>} */
  667. reviveChunks: new SyncHook(["chunks", "records"]),
  668. /** @type {SyncHook<[Iterable<Chunk>]>} */
  669. beforeChunkIds: new SyncHook(["chunks"]),
  670. /** @type {SyncHook<[Iterable<Chunk>]>} */
  671. chunkIds: new SyncHook(["chunks"]),
  672. /** @type {SyncHook<[Iterable<Chunk>]>} */
  673. optimizeChunkIds: new SyncHook(["chunks"]),
  674. /** @type {SyncHook<[Iterable<Chunk>]>} */
  675. afterOptimizeChunkIds: new SyncHook(["chunks"]),
  676. /** @type {SyncHook<[Iterable<Module>, any]>} */
  677. recordModules: new SyncHook(["modules", "records"]),
  678. /** @type {SyncHook<[Iterable<Chunk>, any]>} */
  679. recordChunks: new SyncHook(["chunks", "records"]),
  680. /** @type {SyncHook<[Iterable<Module>]>} */
  681. optimizeCodeGeneration: new SyncHook(["modules"]),
  682. /** @type {SyncHook<[]>} */
  683. beforeModuleHash: new SyncHook([]),
  684. /** @type {SyncHook<[]>} */
  685. afterModuleHash: new SyncHook([]),
  686. /** @type {SyncHook<[]>} */
  687. beforeCodeGeneration: new SyncHook([]),
  688. /** @type {SyncHook<[]>} */
  689. afterCodeGeneration: new SyncHook([]),
  690. /** @type {SyncHook<[]>} */
  691. beforeRuntimeRequirements: new SyncHook([]),
  692. /** @type {SyncHook<[]>} */
  693. afterRuntimeRequirements: new SyncHook([]),
  694. /** @type {SyncHook<[]>} */
  695. beforeHash: new SyncHook([]),
  696. /** @type {SyncHook<[Chunk]>} */
  697. contentHash: new SyncHook(["chunk"]),
  698. /** @type {SyncHook<[]>} */
  699. afterHash: new SyncHook([]),
  700. /** @type {SyncHook<[any]>} */
  701. recordHash: new SyncHook(["records"]),
  702. /** @type {SyncHook<[Compilation, any]>} */
  703. record: new SyncHook(["compilation", "records"]),
  704. /** @type {SyncHook<[]>} */
  705. beforeModuleAssets: new SyncHook([]),
  706. /** @type {SyncBailHook<[], boolean>} */
  707. shouldGenerateChunkAssets: new SyncBailHook([]),
  708. /** @type {SyncHook<[]>} */
  709. beforeChunkAssets: new SyncHook([]),
  710. // TODO webpack 6 remove
  711. /** @deprecated */
  712. additionalChunkAssets: createProcessAssetsHook(
  713. "additionalChunkAssets",
  714. Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
  715. () => [this.chunks],
  716. "DEP_WEBPACK_COMPILATION_ADDITIONAL_CHUNK_ASSETS"
  717. ),
  718. // TODO webpack 6 deprecate
  719. /** @deprecated */
  720. additionalAssets: createProcessAssetsHook(
  721. "additionalAssets",
  722. Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
  723. () => []
  724. ),
  725. // TODO webpack 6 remove
  726. /** @deprecated */
  727. optimizeChunkAssets: createProcessAssetsHook(
  728. "optimizeChunkAssets",
  729. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE,
  730. () => [this.chunks],
  731. "DEP_WEBPACK_COMPILATION_OPTIMIZE_CHUNK_ASSETS"
  732. ),
  733. // TODO webpack 6 remove
  734. /** @deprecated */
  735. afterOptimizeChunkAssets: createProcessAssetsHook(
  736. "afterOptimizeChunkAssets",
  737. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE + 1,
  738. () => [this.chunks],
  739. "DEP_WEBPACK_COMPILATION_AFTER_OPTIMIZE_CHUNK_ASSETS"
  740. ),
  741. // TODO webpack 6 deprecate
  742. /** @deprecated */
  743. optimizeAssets: processAssetsHook,
  744. // TODO webpack 6 deprecate
  745. /** @deprecated */
  746. afterOptimizeAssets: afterProcessAssetsHook,
  747. processAssets: processAssetsHook,
  748. afterProcessAssets: afterProcessAssetsHook,
  749. /** @type {AsyncSeriesHook<[CompilationAssets]>} */
  750. processAdditionalAssets: new AsyncSeriesHook(["assets"]),
  751. /** @type {SyncBailHook<[], boolean>} */
  752. needAdditionalSeal: new SyncBailHook([]),
  753. /** @type {AsyncSeriesHook<[]>} */
  754. afterSeal: new AsyncSeriesHook([]),
  755. /** @type {SyncWaterfallHook<[RenderManifestEntry[], RenderManifestOptions]>} */
  756. renderManifest: new SyncWaterfallHook(["result", "options"]),
  757. /** @type {SyncHook<[Hash]>} */
  758. fullHash: new SyncHook(["hash"]),
  759. /** @type {SyncHook<[Chunk, Hash, ChunkHashContext]>} */
  760. chunkHash: new SyncHook(["chunk", "chunkHash", "ChunkHashContext"]),
  761. /** @type {SyncHook<[Module, string]>} */
  762. moduleAsset: new SyncHook(["module", "filename"]),
  763. /** @type {SyncHook<[Chunk, string]>} */
  764. chunkAsset: new SyncHook(["chunk", "filename"]),
  765. /** @type {SyncWaterfallHook<[string, object, AssetInfo]>} */
  766. assetPath: new SyncWaterfallHook(["path", "options", "assetInfo"]),
  767. /** @type {SyncBailHook<[], boolean>} */
  768. needAdditionalPass: new SyncBailHook([]),
  769. /** @type {SyncHook<[Compiler, string, number]>} */
  770. childCompiler: new SyncHook([
  771. "childCompiler",
  772. "compilerName",
  773. "compilerIndex"
  774. ]),
  775. /** @type {SyncBailHook<[string, LogEntry], true>} */
  776. log: new SyncBailHook(["origin", "logEntry"]),
  777. /** @type {SyncWaterfallHook<[WebpackError[]]>} */
  778. processWarnings: new SyncWaterfallHook(["warnings"]),
  779. /** @type {SyncWaterfallHook<[WebpackError[]]>} */
  780. processErrors: new SyncWaterfallHook(["errors"]),
  781. /** @type {HookMap<SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>>} */
  782. statsPreset: new HookMap(() => new SyncHook(["options", "context"])),
  783. /** @type {SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>} */
  784. statsNormalize: new SyncHook(["options", "context"]),
  785. /** @type {SyncHook<[StatsFactory, NormalizedStatsOptions]>} */
  786. statsFactory: new SyncHook(["statsFactory", "options"]),
  787. /** @type {SyncHook<[StatsPrinter, NormalizedStatsOptions]>} */
  788. statsPrinter: new SyncHook(["statsPrinter", "options"]),
  789. get normalModuleLoader() {
  790. return getNormalModuleLoader();
  791. }
  792. });
  793. /** @type {string=} */
  794. this.name = undefined;
  795. this.startTime = undefined;
  796. this.endTime = undefined;
  797. /** @type {Compiler} */
  798. this.compiler = compiler;
  799. this.resolverFactory = compiler.resolverFactory;
  800. this.inputFileSystem = compiler.inputFileSystem;
  801. this.fileSystemInfo = new FileSystemInfo(this.inputFileSystem, {
  802. managedPaths: compiler.managedPaths,
  803. immutablePaths: compiler.immutablePaths,
  804. logger: this.getLogger("webpack.FileSystemInfo"),
  805. hashFunction: compiler.options.output.hashFunction
  806. });
  807. if (compiler.fileTimestamps) {
  808. this.fileSystemInfo.addFileTimestamps(compiler.fileTimestamps, true);
  809. }
  810. if (compiler.contextTimestamps) {
  811. this.fileSystemInfo.addContextTimestamps(
  812. compiler.contextTimestamps,
  813. true
  814. );
  815. }
  816. /** @type {Map<string, string | Set<string>>} */
  817. this.valueCacheVersions = new Map();
  818. this.requestShortener = compiler.requestShortener;
  819. this.compilerPath = compiler.compilerPath;
  820. this.logger = this.getLogger("webpack.Compilation");
  821. const options = compiler.options;
  822. this.options = options;
  823. this.outputOptions = options && options.output;
  824. /** @type {boolean} */
  825. this.bail = (options && options.bail) || false;
  826. /** @type {boolean} */
  827. this.profile = (options && options.profile) || false;
  828. this.params = params;
  829. this.mainTemplate = new MainTemplate(this.outputOptions, this);
  830. this.chunkTemplate = new ChunkTemplate(this.outputOptions, this);
  831. this.runtimeTemplate = new RuntimeTemplate(
  832. this,
  833. this.outputOptions,
  834. this.requestShortener
  835. );
  836. /** @type {{javascript: ModuleTemplate}} */
  837. this.moduleTemplates = {
  838. javascript: new ModuleTemplate(this.runtimeTemplate, this)
  839. };
  840. defineRemovedModuleTemplates(this.moduleTemplates);
  841. /** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
  842. this.moduleMemCaches = undefined;
  843. /** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
  844. this.moduleMemCaches2 = undefined;
  845. this.moduleGraph = new ModuleGraph();
  846. /** @type {ChunkGraph} */
  847. this.chunkGraph = undefined;
  848. /** @type {CodeGenerationResults} */
  849. this.codeGenerationResults = undefined;
  850. /** @type {AsyncQueue<Module, Module, Module>} */
  851. this.processDependenciesQueue = new AsyncQueue({
  852. name: "processDependencies",
  853. parallelism: options.parallelism || 100,
  854. processor: this._processModuleDependencies.bind(this)
  855. });
  856. /** @type {AsyncQueue<Module, string, Module>} */
  857. this.addModuleQueue = new AsyncQueue({
  858. name: "addModule",
  859. parent: this.processDependenciesQueue,
  860. getKey: module => module.identifier(),
  861. processor: this._addModule.bind(this)
  862. });
  863. /** @type {AsyncQueue<FactorizeModuleOptions, string, Module | ModuleFactoryResult>} */
  864. this.factorizeQueue = new AsyncQueue({
  865. name: "factorize",
  866. parent: this.addModuleQueue,
  867. processor: this._factorizeModule.bind(this)
  868. });
  869. /** @type {AsyncQueue<Module, Module, Module>} */
  870. this.buildQueue = new AsyncQueue({
  871. name: "build",
  872. parent: this.factorizeQueue,
  873. processor: this._buildModule.bind(this)
  874. });
  875. /** @type {AsyncQueue<Module, Module, Module>} */
  876. this.rebuildQueue = new AsyncQueue({
  877. name: "rebuild",
  878. parallelism: options.parallelism || 100,
  879. processor: this._rebuildModule.bind(this)
  880. });
  881. /**
  882. * Modules in value are building during the build of Module in key.
  883. * Means value blocking key from finishing.
  884. * Needed to detect build cycles.
  885. * @type {WeakMap<Module, Set<Module>>}
  886. */
  887. this.creatingModuleDuringBuild = new WeakMap();
  888. /** @type {Map<string, EntryData>} */
  889. this.entries = new Map();
  890. /** @type {EntryData} */
  891. this.globalEntry = {
  892. dependencies: [],
  893. includeDependencies: [],
  894. options: {
  895. name: undefined
  896. }
  897. };
  898. /** @type {Map<string, Entrypoint>} */
  899. this.entrypoints = new Map();
  900. /** @type {Entrypoint[]} */
  901. this.asyncEntrypoints = [];
  902. /** @type {Set<Chunk>} */
  903. this.chunks = new Set();
  904. /** @type {ChunkGroup[]} */
  905. this.chunkGroups = [];
  906. /** @type {Map<string, ChunkGroup>} */
  907. this.namedChunkGroups = new Map();
  908. /** @type {Map<string, Chunk>} */
  909. this.namedChunks = new Map();
  910. /** @type {Set<Module>} */
  911. this.modules = new Set();
  912. if (this._backCompat) {
  913. arrayToSetDeprecation(this.chunks, "Compilation.chunks");
  914. arrayToSetDeprecation(this.modules, "Compilation.modules");
  915. }
  916. /** @private @type {Map<string, Module>} */
  917. this._modules = new Map();
  918. this.records = null;
  919. /** @type {string[]} */
  920. this.additionalChunkAssets = [];
  921. /** @type {CompilationAssets} */
  922. this.assets = {};
  923. /** @type {Map<string, AssetInfo>} */
  924. this.assetsInfo = new Map();
  925. /** @type {Map<string, Map<string, Set<string>>>} */
  926. this._assetsRelatedIn = new Map();
  927. /** @type {WebpackError[]} */
  928. this.errors = [];
  929. /** @type {WebpackError[]} */
  930. this.warnings = [];
  931. /** @type {Compilation[]} */
  932. this.children = [];
  933. /** @type {Map<string, LogEntry[]>} */
  934. this.logging = new Map();
  935. /** @type {Map<DepConstructor, ModuleFactory>} */
  936. this.dependencyFactories = new Map();
  937. /** @type {DependencyTemplates} */
  938. this.dependencyTemplates = new DependencyTemplates(
  939. this.outputOptions.hashFunction
  940. );
  941. this.childrenCounters = {};
  942. /** @type {Set<number|string>} */
  943. this.usedChunkIds = null;
  944. /** @type {Set<number>} */
  945. this.usedModuleIds = null;
  946. /** @type {boolean} */
  947. this.needAdditionalPass = false;
  948. /** @type {Set<Module & { restoreFromUnsafeCache: Function }>} */
  949. this._restoredUnsafeCacheModuleEntries = new Set();
  950. /** @type {Map<string, Module & { restoreFromUnsafeCache: Function }>} */
  951. this._restoredUnsafeCacheEntries = new Map();
  952. /** @type {WeakSet<Module>} */
  953. this.builtModules = new WeakSet();
  954. /** @type {WeakSet<Module>} */
  955. this.codeGeneratedModules = new WeakSet();
  956. /** @type {WeakSet<Module>} */
  957. this.buildTimeExecutedModules = new WeakSet();
  958. /** @private @type {Map<Module, Callback[]>} */
  959. this._rebuildingModules = new Map();
  960. /** @type {Set<string>} */
  961. this.emittedAssets = new Set();
  962. /** @type {Set<string>} */
  963. this.comparedForEmitAssets = new Set();
  964. /** @type {LazySet<string>} */
  965. this.fileDependencies = new LazySet();
  966. /** @type {LazySet<string>} */
  967. this.contextDependencies = new LazySet();
  968. /** @type {LazySet<string>} */
  969. this.missingDependencies = new LazySet();
  970. /** @type {LazySet<string>} */
  971. this.buildDependencies = new LazySet();
  972. // TODO webpack 6 remove
  973. this.compilationDependencies = {
  974. add: util.deprecate(
  975. item => this.fileDependencies.add(item),
  976. "Compilation.compilationDependencies is deprecated (used Compilation.fileDependencies instead)",
  977. "DEP_WEBPACK_COMPILATION_COMPILATION_DEPENDENCIES"
  978. )
  979. };
  980. this._modulesCache = this.getCache("Compilation/modules");
  981. this._assetsCache = this.getCache("Compilation/assets");
  982. this._codeGenerationCache = this.getCache("Compilation/codeGeneration");
  983. const unsafeCache = options.module.unsafeCache;
  984. this._unsafeCache = !!unsafeCache;
  985. this._unsafeCachePredicate =
  986. typeof unsafeCache === "function" ? unsafeCache : () => true;
  987. }
  988. getStats() {
  989. return new Stats(this);
  990. }
  991. /**
  992. * @param {StatsOptions | string} optionsOrPreset stats option value
  993. * @param {CreateStatsOptionsContext} context context
  994. * @returns {NormalizedStatsOptions} normalized options
  995. */
  996. createStatsOptions(optionsOrPreset, context = {}) {
  997. if (
  998. typeof optionsOrPreset === "boolean" ||
  999. typeof optionsOrPreset === "string"
  1000. ) {
  1001. optionsOrPreset = { preset: optionsOrPreset };
  1002. }
  1003. if (typeof optionsOrPreset === "object" && optionsOrPreset !== null) {
  1004. // We use this method of shallow cloning this object to include
  1005. // properties in the prototype chain
  1006. /** @type {Partial<NormalizedStatsOptions>} */
  1007. const options = {};
  1008. for (const key in optionsOrPreset) {
  1009. options[key] = optionsOrPreset[key];
  1010. }
  1011. if (options.preset !== undefined) {
  1012. this.hooks.statsPreset.for(options.preset).call(options, context);
  1013. }
  1014. this.hooks.statsNormalize.call(options, context);
  1015. return /** @type {NormalizedStatsOptions} */ (options);
  1016. } else {
  1017. /** @type {Partial<NormalizedStatsOptions>} */
  1018. const options = {};
  1019. this.hooks.statsNormalize.call(options, context);
  1020. return /** @type {NormalizedStatsOptions} */ (options);
  1021. }
  1022. }
  1023. createStatsFactory(options) {
  1024. const statsFactory = new StatsFactory();
  1025. this.hooks.statsFactory.call(statsFactory, options);
  1026. return statsFactory;
  1027. }
  1028. createStatsPrinter(options) {
  1029. const statsPrinter = new StatsPrinter();
  1030. this.hooks.statsPrinter.call(statsPrinter, options);
  1031. return statsPrinter;
  1032. }
  1033. /**
  1034. * @param {string} name cache name
  1035. * @returns {CacheFacade} the cache facade instance
  1036. */
  1037. getCache(name) {
  1038. return this.compiler.getCache(name);
  1039. }
  1040. /**
  1041. * @param {string | (function(): string)} name name of the logger, or function called once to get the logger name
  1042. * @returns {Logger} a logger with that name
  1043. */
  1044. getLogger(name) {
  1045. if (!name) {
  1046. throw new TypeError("Compilation.getLogger(name) called without a name");
  1047. }
  1048. /** @type {LogEntry[] | undefined} */
  1049. let logEntries;
  1050. return new Logger(
  1051. (type, args) => {
  1052. if (typeof name === "function") {
  1053. name = name();
  1054. if (!name) {
  1055. throw new TypeError(
  1056. "Compilation.getLogger(name) called with a function not returning a name"
  1057. );
  1058. }
  1059. }
  1060. let trace;
  1061. switch (type) {
  1062. case LogType.warn:
  1063. case LogType.error:
  1064. case LogType.trace:
  1065. trace = ErrorHelpers.cutOffLoaderExecution(new Error("Trace").stack)
  1066. .split("\n")
  1067. .slice(3);
  1068. break;
  1069. }
  1070. /** @type {LogEntry} */
  1071. const logEntry = {
  1072. time: Date.now(),
  1073. type,
  1074. args,
  1075. trace
  1076. };
  1077. if (this.hooks.log.call(name, logEntry) === undefined) {
  1078. if (logEntry.type === LogType.profileEnd) {
  1079. // eslint-disable-next-line node/no-unsupported-features/node-builtins
  1080. if (typeof console.profileEnd === "function") {
  1081. // eslint-disable-next-line node/no-unsupported-features/node-builtins
  1082. console.profileEnd(`[${name}] ${logEntry.args[0]}`);
  1083. }
  1084. }
  1085. if (logEntries === undefined) {
  1086. logEntries = this.logging.get(name);
  1087. if (logEntries === undefined) {
  1088. logEntries = [];
  1089. this.logging.set(name, logEntries);
  1090. }
  1091. }
  1092. logEntries.push(logEntry);
  1093. if (logEntry.type === LogType.profile) {
  1094. // eslint-disable-next-line node/no-unsupported-features/node-builtins
  1095. if (typeof console.profile === "function") {
  1096. // eslint-disable-next-line node/no-unsupported-features/node-builtins
  1097. console.profile(`[${name}] ${logEntry.args[0]}`);
  1098. }
  1099. }
  1100. }
  1101. },
  1102. childName => {
  1103. if (typeof name === "function") {
  1104. if (typeof childName === "function") {
  1105. return this.getLogger(() => {
  1106. if (typeof name === "function") {
  1107. name = name();
  1108. if (!name) {
  1109. throw new TypeError(
  1110. "Compilation.getLogger(name) called with a function not returning a name"
  1111. );
  1112. }
  1113. }
  1114. if (typeof childName === "function") {
  1115. childName = childName();
  1116. if (!childName) {
  1117. throw new TypeError(
  1118. "Logger.getChildLogger(name) called with a function not returning a name"
  1119. );
  1120. }
  1121. }
  1122. return `${name}/${childName}`;
  1123. });
  1124. } else {
  1125. return this.getLogger(() => {
  1126. if (typeof name === "function") {
  1127. name = name();
  1128. if (!name) {
  1129. throw new TypeError(
  1130. "Compilation.getLogger(name) called with a function not returning a name"
  1131. );
  1132. }
  1133. }
  1134. return `${name}/${childName}`;
  1135. });
  1136. }
  1137. } else {
  1138. if (typeof childName === "function") {
  1139. return this.getLogger(() => {
  1140. if (typeof childName === "function") {
  1141. childName = childName();
  1142. if (!childName) {
  1143. throw new TypeError(
  1144. "Logger.getChildLogger(name) called with a function not returning a name"
  1145. );
  1146. }
  1147. }
  1148. return `${name}/${childName}`;
  1149. });
  1150. } else {
  1151. return this.getLogger(`${name}/${childName}`);
  1152. }
  1153. }
  1154. }
  1155. );
  1156. }
  1157. /**
  1158. * @param {Module} module module to be added that was created
  1159. * @param {ModuleCallback} callback returns the module in the compilation,
  1160. * it could be the passed one (if new), or an already existing in the compilation
  1161. * @returns {void}
  1162. */
  1163. addModule(module, callback) {
  1164. this.addModuleQueue.add(module, callback);
  1165. }
  1166. /**
  1167. * @param {Module} module module to be added that was created
  1168. * @param {ModuleCallback} callback returns the module in the compilation,
  1169. * it could be the passed one (if new), or an already existing in the compilation
  1170. * @returns {void}
  1171. */
  1172. _addModule(module, callback) {
  1173. const identifier = module.identifier();
  1174. const alreadyAddedModule = this._modules.get(identifier);
  1175. if (alreadyAddedModule) {
  1176. return callback(null, alreadyAddedModule);
  1177. }
  1178. const currentProfile = this.profile
  1179. ? this.moduleGraph.getProfile(module)
  1180. : undefined;
  1181. if (currentProfile !== undefined) {
  1182. currentProfile.markRestoringStart();
  1183. }
  1184. this._modulesCache.get(identifier, null, (err, cacheModule) => {
  1185. if (err) return callback(new ModuleRestoreError(module, err));
  1186. if (currentProfile !== undefined) {
  1187. currentProfile.markRestoringEnd();
  1188. currentProfile.markIntegrationStart();
  1189. }
  1190. if (cacheModule) {
  1191. cacheModule.updateCacheModule(module);
  1192. module = cacheModule;
  1193. }
  1194. this._modules.set(identifier, module);
  1195. this.modules.add(module);
  1196. if (this._backCompat)
  1197. ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
  1198. if (currentProfile !== undefined) {
  1199. currentProfile.markIntegrationEnd();
  1200. }
  1201. callback(null, module);
  1202. });
  1203. }
  1204. /**
  1205. * Fetches a module from a compilation by its identifier
  1206. * @param {Module} module the module provided
  1207. * @returns {Module} the module requested
  1208. */
  1209. getModule(module) {
  1210. const identifier = module.identifier();
  1211. return this._modules.get(identifier);
  1212. }
  1213. /**
  1214. * Attempts to search for a module by its identifier
  1215. * @param {string} identifier identifier (usually path) for module
  1216. * @returns {Module|undefined} attempt to search for module and return it, else undefined
  1217. */
  1218. findModule(identifier) {
  1219. return this._modules.get(identifier);
  1220. }
  1221. /**
  1222. * Schedules a build of the module object
  1223. *
  1224. * @param {Module} module module to be built
  1225. * @param {ModuleCallback} callback the callback
  1226. * @returns {void}
  1227. */
  1228. buildModule(module, callback) {
  1229. this.buildQueue.add(module, callback);
  1230. }
  1231. /**
  1232. * Builds the module object
  1233. *
  1234. * @param {Module} module module to be built
  1235. * @param {ModuleCallback} callback the callback
  1236. * @returns {void}
  1237. */
  1238. _buildModule(module, callback) {
  1239. const currentProfile = this.profile
  1240. ? this.moduleGraph.getProfile(module)
  1241. : undefined;
  1242. if (currentProfile !== undefined) {
  1243. currentProfile.markBuildingStart();
  1244. }
  1245. module.needBuild(
  1246. {
  1247. compilation: this,
  1248. fileSystemInfo: this.fileSystemInfo,
  1249. valueCacheVersions: this.valueCacheVersions
  1250. },
  1251. (err, needBuild) => {
  1252. if (err) return callback(err);
  1253. if (!needBuild) {
  1254. if (currentProfile !== undefined) {
  1255. currentProfile.markBuildingEnd();
  1256. }
  1257. this.hooks.stillValidModule.call(module);
  1258. return callback();
  1259. }
  1260. this.hooks.buildModule.call(module);
  1261. this.builtModules.add(module);
  1262. module.build(
  1263. this.options,
  1264. this,
  1265. this.resolverFactory.get("normal", module.resolveOptions),
  1266. this.inputFileSystem,
  1267. err => {
  1268. if (currentProfile !== undefined) {
  1269. currentProfile.markBuildingEnd();
  1270. }
  1271. if (err) {
  1272. this.hooks.failedModule.call(module, err);
  1273. return callback(err);
  1274. }
  1275. if (currentProfile !== undefined) {
  1276. currentProfile.markStoringStart();
  1277. }
  1278. this._modulesCache.store(module.identifier(), null, module, err => {
  1279. if (currentProfile !== undefined) {
  1280. currentProfile.markStoringEnd();
  1281. }
  1282. if (err) {
  1283. this.hooks.failedModule.call(module, err);
  1284. return callback(new ModuleStoreError(module, err));
  1285. }
  1286. this.hooks.succeedModule.call(module);
  1287. return callback();
  1288. });
  1289. }
  1290. );
  1291. }
  1292. );
  1293. }
  1294. /**
  1295. * @param {Module} module to be processed for deps
  1296. * @param {ModuleCallback} callback callback to be triggered
  1297. * @returns {void}
  1298. */
  1299. processModuleDependencies(module, callback) {
  1300. this.processDependenciesQueue.add(module, callback);
  1301. }
  1302. /**
  1303. * @param {Module} module to be processed for deps
  1304. * @returns {void}
  1305. */
  1306. processModuleDependenciesNonRecursive(module) {
  1307. const processDependenciesBlock = block => {
  1308. if (block.dependencies) {
  1309. let i = 0;
  1310. for (const dep of block.dependencies) {
  1311. this.moduleGraph.setParents(dep, block, module, i++);
  1312. }
  1313. }
  1314. if (block.blocks) {
  1315. for (const b of block.blocks) processDependenciesBlock(b);
  1316. }
  1317. };
  1318. processDependenciesBlock(module);
  1319. }
  1320. /**
  1321. * @param {Module} module to be processed for deps
  1322. * @param {ModuleCallback} callback callback to be triggered
  1323. * @returns {void}
  1324. */
  1325. _processModuleDependencies(module, callback) {
  1326. /** @type {Array<{factory: ModuleFactory, dependencies: Dependency[], context: string|undefined, originModule: Module|null}>} */
  1327. const sortedDependencies = [];
  1328. /** @type {DependenciesBlock} */
  1329. let currentBlock;
  1330. /** @type {Map<ModuleFactory, Map<string, Dependency[]>>} */
  1331. let dependencies;
  1332. /** @type {DepConstructor} */
  1333. let factoryCacheKey;
  1334. /** @type {ModuleFactory} */
  1335. let factoryCacheKey2;
  1336. /** @type {Map<string, Dependency[]>} */
  1337. let factoryCacheValue;
  1338. /** @type {string} */
  1339. let listCacheKey1;
  1340. /** @type {string} */
  1341. let listCacheKey2;
  1342. /** @type {Dependency[]} */
  1343. let listCacheValue;
  1344. let inProgressSorting = 1;
  1345. let inProgressTransitive = 1;
  1346. const onDependenciesSorted = err => {
  1347. if (err) return callback(err);
  1348. // early exit without changing parallelism back and forth
  1349. if (sortedDependencies.length === 0 && inProgressTransitive === 1) {
  1350. return callback();
  1351. }
  1352. // This is nested so we need to allow one additional task
  1353. this.processDependenciesQueue.increaseParallelism();
  1354. for (const item of sortedDependencies) {
  1355. inProgressTransitive++;
  1356. this.handleModuleCreation(item, err => {
  1357. // In V8, the Error objects keep a reference to the functions on the stack. These warnings &
  1358. // errors are created inside closures that keep a reference to the Compilation, so errors are
  1359. // leaking the Compilation object.
  1360. if (err && this.bail) {
  1361. if (inProgressTransitive <= 0) return;
  1362. inProgressTransitive = -1;
  1363. // eslint-disable-next-line no-self-assign
  1364. err.stack = err.stack;
  1365. onTransitiveTasksFinished(err);
  1366. return;
  1367. }
  1368. if (--inProgressTransitive === 0) onTransitiveTasksFinished();
  1369. });
  1370. }
  1371. if (--inProgressTransitive === 0) onTransitiveTasksFinished();
  1372. };
  1373. const onTransitiveTasksFinished = err => {
  1374. if (err) return callback(err);
  1375. this.processDependenciesQueue.decreaseParallelism();
  1376. return callback();
  1377. };
  1378. /**
  1379. * @param {Dependency} dep dependency
  1380. * @param {number} index index in block
  1381. * @returns {void}
  1382. */
  1383. const processDependency = (dep, index) => {
  1384. this.moduleGraph.setParents(dep, currentBlock, module, index);
  1385. if (this._unsafeCache) {
  1386. try {
  1387. const unsafeCachedModule = unsafeCacheDependencies.get(dep);
  1388. if (unsafeCachedModule === null) return;
  1389. if (unsafeCachedModule !== undefined) {
  1390. if (
  1391. this._restoredUnsafeCacheModuleEntries.has(unsafeCachedModule)
  1392. ) {
  1393. this._handleExistingModuleFromUnsafeCache(
  1394. module,
  1395. dep,
  1396. unsafeCachedModule
  1397. );
  1398. return;
  1399. }
  1400. const identifier = unsafeCachedModule.identifier();
  1401. const cachedModule =
  1402. this._restoredUnsafeCacheEntries.get(identifier);
  1403. if (cachedModule !== undefined) {
  1404. // update unsafe cache to new module
  1405. unsafeCacheDependencies.set(dep, cachedModule);
  1406. this._handleExistingModuleFromUnsafeCache(
  1407. module,
  1408. dep,
  1409. cachedModule
  1410. );
  1411. return;
  1412. }
  1413. inProgressSorting++;
  1414. this._modulesCache.get(identifier, null, (err, cachedModule) => {
  1415. if (err) {
  1416. if (inProgressSorting <= 0) return;
  1417. inProgressSorting = -1;
  1418. onDependenciesSorted(err);
  1419. return;
  1420. }
  1421. try {
  1422. if (!this._restoredUnsafeCacheEntries.has(identifier)) {
  1423. const data = unsafeCacheData.get(cachedModule);
  1424. if (data === undefined) {
  1425. processDependencyForResolving(dep);
  1426. if (--inProgressSorting === 0) onDependenciesSorted();
  1427. return;
  1428. }
  1429. if (cachedModule !== unsafeCachedModule) {
  1430. unsafeCacheDependencies.set(dep, cachedModule);
  1431. }
  1432. cachedModule.restoreFromUnsafeCache(
  1433. data,
  1434. this.params.normalModuleFactory,
  1435. this.params
  1436. );
  1437. this._restoredUnsafeCacheEntries.set(
  1438. identifier,
  1439. cachedModule
  1440. );
  1441. this._restoredUnsafeCacheModuleEntries.add(cachedModule);
  1442. if (!this.modules.has(cachedModule)) {
  1443. inProgressTransitive++;
  1444. this._handleNewModuleFromUnsafeCache(
  1445. module,
  1446. dep,
  1447. cachedModule,
  1448. err => {
  1449. if (err) {
  1450. if (inProgressTransitive <= 0) return;
  1451. inProgressTransitive = -1;
  1452. onTransitiveTasksFinished(err);
  1453. }
  1454. if (--inProgressTransitive === 0)
  1455. return onTransitiveTasksFinished();
  1456. }
  1457. );
  1458. if (--inProgressSorting === 0) onDependenciesSorted();
  1459. return;
  1460. }
  1461. }
  1462. if (unsafeCachedModule !== cachedModule) {
  1463. unsafeCacheDependencies.set(dep, cachedModule);
  1464. }
  1465. this._handleExistingModuleFromUnsafeCache(
  1466. module,
  1467. dep,
  1468. cachedModule
  1469. ); // a3
  1470. } catch (err) {
  1471. if (inProgressSorting <= 0) return;
  1472. inProgressSorting = -1;
  1473. onDependenciesSorted(err);
  1474. return;
  1475. }
  1476. if (--inProgressSorting === 0) onDependenciesSorted();
  1477. });
  1478. return;
  1479. }
  1480. } catch (e) {
  1481. console.error(e);
  1482. }
  1483. }
  1484. processDependencyForResolving(dep);
  1485. };
  1486. /**
  1487. * @param {Dependency} dep dependency
  1488. * @returns {void}
  1489. */
  1490. const processDependencyForResolving = dep => {
  1491. const resourceIdent = dep.getResourceIdentifier();
  1492. if (resourceIdent !== undefined && resourceIdent !== null) {
  1493. const category = dep.category;
  1494. const constructor = /** @type {DepConstructor} */ (dep.constructor);
  1495. if (factoryCacheKey === constructor) {
  1496. // Fast path 1: same constructor as prev item
  1497. if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
  1498. // Super fast path 1: also same resource
  1499. listCacheValue.push(dep);
  1500. return;
  1501. }
  1502. } else {
  1503. const factory = this.dependencyFactories.get(constructor);
  1504. if (factory === undefined) {
  1505. throw new Error(
  1506. `No module factory available for dependency type: ${constructor.name}`
  1507. );
  1508. }
  1509. if (factoryCacheKey2 === factory) {
  1510. // Fast path 2: same factory as prev item
  1511. factoryCacheKey = constructor;
  1512. if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
  1513. // Super fast path 2: also same resource
  1514. listCacheValue.push(dep);
  1515. return;
  1516. }
  1517. } else {
  1518. // Slow path
  1519. if (factoryCacheKey2 !== undefined) {
  1520. // Archive last cache entry
  1521. if (dependencies === undefined) dependencies = new Map();
  1522. dependencies.set(factoryCacheKey2, factoryCacheValue);
  1523. factoryCacheValue = dependencies.get(factory);
  1524. if (factoryCacheValue === undefined) {
  1525. factoryCacheValue = new Map();
  1526. }
  1527. } else {
  1528. factoryCacheValue = new Map();
  1529. }
  1530. factoryCacheKey = constructor;
  1531. factoryCacheKey2 = factory;
  1532. }
  1533. }
  1534. // Here webpack is using heuristic that assumes
  1535. // mostly esm dependencies would be used
  1536. // so we don't allocate extra string for them
  1537. const cacheKey =
  1538. category === esmDependencyCategory
  1539. ? resourceIdent
  1540. : `${category}${resourceIdent}`;
  1541. let list = factoryCacheValue.get(cacheKey);
  1542. if (list === undefined) {
  1543. factoryCacheValue.set(cacheKey, (list = []));
  1544. sortedDependencies.push({
  1545. factory: factoryCacheKey2,
  1546. dependencies: list,
  1547. context: dep.getContext(),
  1548. originModule: module
  1549. });
  1550. }
  1551. list.push(dep);
  1552. listCacheKey1 = category;
  1553. listCacheKey2 = resourceIdent;
  1554. listCacheValue = list;
  1555. }
  1556. };
  1557. try {
  1558. /** @type {DependenciesBlock[]} */
  1559. const queue = [module];
  1560. do {
  1561. const block = queue.pop();
  1562. if (block.dependencies) {
  1563. currentBlock = block;
  1564. let i = 0;
  1565. for (const dep of block.dependencies) processDependency(dep, i++);
  1566. }
  1567. if (block.blocks) {
  1568. for (const b of block.blocks) queue.push(b);
  1569. }
  1570. } while (queue.length !== 0);
  1571. } catch (e) {
  1572. return callback(e);
  1573. }
  1574. if (--inProgressSorting === 0) onDependenciesSorted();
  1575. }
  1576. _handleNewModuleFromUnsafeCache(originModule, dependency, module, callback) {
  1577. const moduleGraph = this.moduleGraph;
  1578. moduleGraph.setResolvedModule(originModule, dependency, module);
  1579. moduleGraph.setIssuerIfUnset(
  1580. module,
  1581. originModule !== undefined ? originModule : null
  1582. );
  1583. this._modules.set(module.identifier(), module);
  1584. this.modules.add(module);
  1585. if (this._backCompat)
  1586. ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
  1587. this._handleModuleBuildAndDependencies(
  1588. originModule,
  1589. module,
  1590. true,
  1591. callback
  1592. );
  1593. }
  1594. _handleExistingModuleFromUnsafeCache(originModule, dependency, module) {
  1595. const moduleGraph = this.moduleGraph;
  1596. moduleGraph.setResolvedModule(originModule, dependency, module);
  1597. }
  1598. /**
  1599. * @typedef {Object} HandleModuleCreationOptions
  1600. * @property {ModuleFactory} factory
  1601. * @property {Dependency[]} dependencies
  1602. * @property {Module | null} originModule
  1603. * @property {Partial<ModuleFactoryCreateDataContextInfo>=} contextInfo
  1604. * @property {string=} context
  1605. * @property {boolean=} recursive recurse into dependencies of the created module
  1606. * @property {boolean=} connectOrigin connect the resolved module with the origin module
  1607. */
  1608. /**
  1609. * @param {HandleModuleCreationOptions} options options object
  1610. * @param {ModuleCallback} callback callback
  1611. * @returns {void}
  1612. */
  1613. handleModuleCreation(
  1614. {
  1615. factory,
  1616. dependencies,
  1617. originModule,
  1618. contextInfo,
  1619. context,
  1620. recursive = true,
  1621. connectOrigin = recursive
  1622. },
  1623. callback
  1624. ) {
  1625. const moduleGraph = this.moduleGraph;
  1626. const currentProfile = this.profile ? new ModuleProfile() : undefined;
  1627. this.factorizeModule(
  1628. {
  1629. currentProfile,
  1630. factory,
  1631. dependencies,
  1632. factoryResult: true,
  1633. originModule,
  1634. contextInfo,
  1635. context
  1636. },
  1637. (err, factoryResult) => {
  1638. const applyFactoryResultDependencies = () => {
  1639. const { fileDependencies, contextDependencies, missingDependencies } =
  1640. factoryResult;
  1641. if (fileDependencies) {
  1642. this.fileDependencies.addAll(fileDependencies);
  1643. }
  1644. if (contextDependencies) {
  1645. this.contextDependencies.addAll(contextDependencies);
  1646. }
  1647. if (missingDependencies) {
  1648. this.missingDependencies.addAll(missingDependencies);
  1649. }
  1650. };
  1651. if (err) {
  1652. if (factoryResult) applyFactoryResultDependencies();
  1653. if (dependencies.every(d => d.optional)) {
  1654. this.warnings.push(err);
  1655. return callback();
  1656. } else {
  1657. this.errors.push(err);
  1658. return callback(err);
  1659. }
  1660. }
  1661. const newModule = factoryResult.module;
  1662. if (!newModule) {
  1663. applyFactoryResultDependencies();
  1664. return callback();
  1665. }
  1666. if (currentProfile !== undefined) {
  1667. moduleGraph.setProfile(newModule, currentProfile);
  1668. }
  1669. this.addModule(newModule, (err, module) => {
  1670. if (err) {
  1671. applyFactoryResultDependencies();
  1672. if (!err.module) {
  1673. err.module = module;
  1674. }
  1675. this.errors.push(err);
  1676. return callback(err);
  1677. }
  1678. if (
  1679. this._unsafeCache &&
  1680. factoryResult.cacheable !== false &&
  1681. /** @type {any} */ (module).restoreFromUnsafeCache &&
  1682. this._unsafeCachePredicate(module)
  1683. ) {
  1684. const unsafeCacheableModule =
  1685. /** @type {Module & { restoreFromUnsafeCache: Function }} */ (
  1686. module
  1687. );
  1688. for (let i = 0; i < dependencies.length; i++) {
  1689. const dependency = dependencies[i];
  1690. moduleGraph.setResolvedModule(
  1691. connectOrigin ? originModule : null,
  1692. dependency,
  1693. unsafeCacheableModule
  1694. );
  1695. unsafeCacheDependencies.set(dependency, unsafeCacheableModule);
  1696. }
  1697. if (!unsafeCacheData.has(unsafeCacheableModule)) {
  1698. unsafeCacheData.set(
  1699. unsafeCacheableModule,
  1700. unsafeCacheableModule.getUnsafeCacheData()
  1701. );
  1702. }
  1703. } else {
  1704. applyFactoryResultDependencies();
  1705. for (let i = 0; i < dependencies.length; i++) {
  1706. const dependency = dependencies[i];
  1707. moduleGraph.setResolvedModule(
  1708. connectOrigin ? originModule : null,
  1709. dependency,
  1710. module
  1711. );
  1712. }
  1713. }
  1714. moduleGraph.setIssuerIfUnset(
  1715. module,
  1716. originModule !== undefined ? originModule : null
  1717. );
  1718. if (module !== newModule) {
  1719. if (currentProfile !== undefined) {
  1720. const otherProfile = moduleGraph.getProfile(module);
  1721. if (otherProfile !== undefined) {
  1722. currentProfile.mergeInto(otherProfile);
  1723. } else {
  1724. moduleGraph.setProfile(module, currentProfile);
  1725. }
  1726. }
  1727. }
  1728. this._handleModuleBuildAndDependencies(
  1729. originModule,
  1730. module,
  1731. recursive,
  1732. callback
  1733. );
  1734. });
  1735. }
  1736. );
  1737. }
  1738. _handleModuleBuildAndDependencies(originModule, module, recursive, callback) {
  1739. // Check for cycles when build is trigger inside another build
  1740. let creatingModuleDuringBuildSet = undefined;
  1741. if (!recursive && this.buildQueue.isProcessing(originModule)) {
  1742. // Track build dependency
  1743. creatingModuleDuringBuildSet =
  1744. this.creatingModuleDuringBuild.get(originModule);
  1745. if (creatingModuleDuringBuildSet === undefined) {
  1746. creatingModuleDuringBuildSet = new Set();
  1747. this.creatingModuleDuringBuild.set(
  1748. originModule,
  1749. creatingModuleDuringBuildSet
  1750. );
  1751. }
  1752. creatingModuleDuringBuildSet.add(module);
  1753. // When building is blocked by another module
  1754. // search for a cycle, cancel the cycle by throwing
  1755. // an error (otherwise this would deadlock)
  1756. const blockReasons = this.creatingModuleDuringBuild.get(module);
  1757. if (blockReasons !== undefined) {
  1758. const set = new Set(blockReasons);
  1759. for (const item of set) {
  1760. const blockReasons = this.creatingModuleDuringBuild.get(item);
  1761. if (blockReasons !== undefined) {
  1762. for (const m of blockReasons) {
  1763. if (m === module) {
  1764. return callback(new BuildCycleError(module));
  1765. }
  1766. set.add(m);
  1767. }
  1768. }
  1769. }
  1770. }
  1771. }
  1772. this.buildModule(module, err => {
  1773. if (creatingModuleDuringBuildSet !== undefined) {
  1774. creatingModuleDuringBuildSet.delete(module);
  1775. }
  1776. if (err) {
  1777. if (!err.module) {
  1778. err.module = module;
  1779. }
  1780. this.errors.push(err);
  1781. return callback(err);
  1782. }
  1783. if (!recursive) {
  1784. this.processModuleDependenciesNonRecursive(module);
  1785. callback(null, module);
  1786. return;
  1787. }
  1788. // This avoids deadlocks for circular dependencies
  1789. if (this.processDependenciesQueue.isProcessing(module)) {
  1790. return callback(null, module);
  1791. }
  1792. this.processModuleDependencies(module, err => {
  1793. if (err) {
  1794. return callback(err);
  1795. }
  1796. callback(null, module);
  1797. });
  1798. });
  1799. }
  1800. /**
  1801. * @param {FactorizeModuleOptions} options options object
  1802. * @param {ModuleOrFactoryResultCallback} callback callback
  1803. * @returns {void}
  1804. */
  1805. _factorizeModule(
  1806. {
  1807. currentProfile,
  1808. factory,
  1809. dependencies,
  1810. originModule,
  1811. factoryResult,
  1812. contextInfo,
  1813. context
  1814. },
  1815. callback
  1816. ) {
  1817. if (currentProfile !== undefined) {
  1818. currentProfile.markFactoryStart();
  1819. }
  1820. factory.create(
  1821. {
  1822. contextInfo: {
  1823. issuer: originModule ? originModule.nameForCondition() : "",
  1824. issuerLayer: originModule ? originModule.layer : null,
  1825. compiler: this.compiler.name,
  1826. ...contextInfo
  1827. },
  1828. resolveOptions: originModule ? originModule.resolveOptions : undefined,
  1829. context: context
  1830. ? context
  1831. : originModule
  1832. ? originModule.context
  1833. : this.compiler.context,
  1834. dependencies: dependencies
  1835. },
  1836. (err, result) => {
  1837. if (result) {
  1838. // TODO webpack 6: remove
  1839. // For backward-compat
  1840. if (result.module === undefined && result instanceof Module) {
  1841. result = {
  1842. module: result
  1843. };
  1844. }
  1845. if (!factoryResult) {
  1846. const {
  1847. fileDependencies,
  1848. contextDependencies,
  1849. missingDependencies
  1850. } = result;
  1851. if (fileDependencies) {
  1852. this.fileDependencies.addAll(fileDependencies);
  1853. }
  1854. if (contextDependencies) {
  1855. this.contextDependencies.addAll(contextDependencies);
  1856. }
  1857. if (missingDependencies) {
  1858. this.missingDependencies.addAll(missingDependencies);
  1859. }
  1860. }
  1861. }
  1862. if (err) {
  1863. const notFoundError = new ModuleNotFoundError(
  1864. originModule,
  1865. err,
  1866. dependencies.map(d => d.loc).filter(Boolean)[0]
  1867. );
  1868. return callback(notFoundError, factoryResult ? result : undefined);
  1869. }
  1870. if (!result) {
  1871. return callback();
  1872. }
  1873. if (currentProfile !== undefined) {
  1874. currentProfile.markFactoryEnd();
  1875. }
  1876. callback(null, factoryResult ? result : result.module);
  1877. }
  1878. );
  1879. }
  1880. /**
  1881. * @param {string} context context string path
  1882. * @param {Dependency} dependency dependency used to create Module chain
  1883. * @param {ModuleCallback} callback callback for when module chain is complete
  1884. * @returns {void} will throw if dependency instance is not a valid Dependency
  1885. */
  1886. addModuleChain(context, dependency, callback) {
  1887. return this.addModuleTree({ context, dependency }, callback);
  1888. }
  1889. /**
  1890. * @param {Object} options options
  1891. * @param {string} options.context context string path
  1892. * @param {Dependency} options.dependency dependency used to create Module chain
  1893. * @param {Partial<ModuleFactoryCreateDataContextInfo>=} options.contextInfo additional context info for the root module
  1894. * @param {ModuleCallback} callback callback for when module chain is complete
  1895. * @returns {void} will throw if dependency instance is not a valid Dependency
  1896. */
  1897. addModuleTree({ context, dependency, contextInfo }, callback) {
  1898. if (
  1899. typeof dependency !== "object" ||
  1900. dependency === null ||
  1901. !dependency.constructor
  1902. ) {
  1903. return callback(
  1904. new WebpackError("Parameter 'dependency' must be a Dependency")
  1905. );
  1906. }
  1907. const Dep = /** @type {DepConstructor} */ (dependency.constructor);
  1908. const moduleFactory = this.dependencyFactories.get(Dep);
  1909. if (!moduleFactory) {
  1910. return callback(
  1911. new WebpackError(
  1912. `No dependency factory available for this dependency type: ${dependency.constructor.name}`
  1913. )
  1914. );
  1915. }
  1916. this.handleModuleCreation(
  1917. {
  1918. factory: moduleFactory,
  1919. dependencies: [dependency],
  1920. originModule: null,
  1921. contextInfo,
  1922. context
  1923. },
  1924. (err, result) => {
  1925. if (err && this.bail) {
  1926. callback(err);
  1927. this.buildQueue.stop();
  1928. this.rebuildQueue.stop();
  1929. this.processDependenciesQueue.stop();
  1930. this.factorizeQueue.stop();
  1931. } else if (!err && result) {
  1932. callback(null, result);
  1933. } else {
  1934. callback();
  1935. }
  1936. }
  1937. );
  1938. }
  1939. /**
  1940. * @param {string} context context path for entry
  1941. * @param {Dependency} entry entry dependency that should be followed
  1942. * @param {string | EntryOptions} optionsOrName options or deprecated name of entry
  1943. * @param {ModuleCallback} callback callback function
  1944. * @returns {void} returns
  1945. */
  1946. addEntry(context, entry, optionsOrName, callback) {
  1947. // TODO webpack 6 remove
  1948. const options =
  1949. typeof optionsOrName === "object"
  1950. ? optionsOrName
  1951. : { name: optionsOrName };
  1952. this._addEntryItem(context, entry, "dependencies", options, callback);
  1953. }
  1954. /**
  1955. * @param {string} context context path for entry
  1956. * @param {Dependency} dependency dependency that should be followed
  1957. * @param {EntryOptions} options options
  1958. * @param {ModuleCallback} callback callback function
  1959. * @returns {void} returns
  1960. */
  1961. addInclude(context, dependency, options, callback) {
  1962. this._addEntryItem(
  1963. context,
  1964. dependency,
  1965. "includeDependencies",
  1966. options,
  1967. callback
  1968. );
  1969. }
  1970. /**
  1971. * @param {string} context context path for entry
  1972. * @param {Dependency} entry entry dependency that should be followed
  1973. * @param {"dependencies" | "includeDependencies"} target type of entry
  1974. * @param {EntryOptions} options options
  1975. * @param {ModuleCallback} callback callback function
  1976. * @returns {void} returns
  1977. */
  1978. _addEntryItem(context, entry, target, options, callback) {
  1979. const { name } = options;
  1980. let entryData =
  1981. name !== undefined ? this.entries.get(name) : this.globalEntry;
  1982. if (entryData === undefined) {
  1983. entryData = {
  1984. dependencies: [],
  1985. includeDependencies: [],
  1986. options: {
  1987. name: undefined,
  1988. ...options
  1989. }
  1990. };
  1991. entryData[target].push(entry);
  1992. this.entries.set(name, entryData);
  1993. } else {
  1994. entryData[target].push(entry);
  1995. for (const key of Object.keys(options)) {
  1996. if (options[key] === undefined) continue;
  1997. if (entryData.options[key] === options[key]) continue;
  1998. if (
  1999. Array.isArray(entryData.options[key]) &&
  2000. Array.isArray(options[key]) &&
  2001. arrayEquals(entryData.options[key], options[key])
  2002. ) {
  2003. continue;
  2004. }
  2005. if (entryData.options[key] === undefined) {
  2006. entryData.options[key] = options[key];
  2007. } else {
  2008. return callback(
  2009. new WebpackError(
  2010. `Conflicting entry option ${key} = ${entryData.options[key]} vs ${options[key]}`
  2011. )
  2012. );
  2013. }
  2014. }
  2015. }
  2016. this.hooks.addEntry.call(entry, options);
  2017. this.addModuleTree(
  2018. {
  2019. context,
  2020. dependency: entry,
  2021. contextInfo: entryData.options.layer
  2022. ? { issuerLayer: entryData.options.layer }
  2023. : undefined
  2024. },
  2025. (err, module) => {
  2026. if (err) {
  2027. this.hooks.failedEntry.call(entry, options, err);
  2028. return callback(err);
  2029. }
  2030. this.hooks.succeedEntry.call(entry, options, module);
  2031. return callback(null, module);
  2032. }
  2033. );
  2034. }
  2035. /**
  2036. * @param {Module} module module to be rebuilt
  2037. * @param {ModuleCallback} callback callback when module finishes rebuilding
  2038. * @returns {void}
  2039. */
  2040. rebuildModule(module, callback) {
  2041. this.rebuildQueue.add(module, callback);
  2042. }
  2043. /**
  2044. * @param {Module} module module to be rebuilt
  2045. * @param {ModuleCallback} callback callback when module finishes rebuilding
  2046. * @returns {void}
  2047. */
  2048. _rebuildModule(module, callback) {
  2049. this.hooks.rebuildModule.call(module);
  2050. const oldDependencies = module.dependencies.slice();
  2051. const oldBlocks = module.blocks.slice();
  2052. module.invalidateBuild();
  2053. this.buildQueue.invalidate(module);
  2054. this.buildModule(module, err => {
  2055. if (err) {
  2056. return this.hooks.finishRebuildingModule.callAsync(module, err2 => {
  2057. if (err2) {
  2058. callback(
  2059. makeWebpackError(err2, "Compilation.hooks.finishRebuildingModule")
  2060. );
  2061. return;
  2062. }
  2063. callback(err);
  2064. });
  2065. }
  2066. this.processDependenciesQueue.invalidate(module);
  2067. this.moduleGraph.unfreeze();
  2068. this.processModuleDependencies(module, err => {
  2069. if (err) return callback(err);
  2070. this.removeReasonsOfDependencyBlock(module, {
  2071. dependencies: oldDependencies,
  2072. blocks: oldBlocks
  2073. });
  2074. this.hooks.finishRebuildingModule.callAsync(module, err2 => {
  2075. if (err2) {
  2076. callback(
  2077. makeWebpackError(err2, "Compilation.hooks.finishRebuildingModule")
  2078. );
  2079. return;
  2080. }
  2081. callback(null, module);
  2082. });
  2083. });
  2084. });
  2085. }
  2086. _computeAffectedModules(modules) {
  2087. const moduleMemCacheCache = this.compiler.moduleMemCaches;
  2088. if (!moduleMemCacheCache) return;
  2089. if (!this.moduleMemCaches) {
  2090. this.moduleMemCaches = new Map();
  2091. this.moduleGraph.setModuleMemCaches(this.moduleMemCaches);
  2092. }
  2093. const { moduleGraph, moduleMemCaches } = this;
  2094. const affectedModules = new Set();
  2095. const infectedModules = new Set();
  2096. let statNew = 0;
  2097. let statChanged = 0;
  2098. let statUnchanged = 0;
  2099. let statReferencesChanged = 0;
  2100. let statWithoutBuild = 0;
  2101. const computeReferences = module => {
  2102. /** @type {WeakMap<Dependency, Module>} */
  2103. let references = undefined;
  2104. for (const connection of moduleGraph.getOutgoingConnections(module)) {
  2105. const d = connection.dependency;
  2106. const m = connection.module;
  2107. if (!d || !m || unsafeCacheDependencies.has(d)) continue;
  2108. if (references === undefined) references = new WeakMap();
  2109. references.set(d, m);
  2110. }
  2111. return references;
  2112. };
  2113. /**
  2114. * @param {Module} module the module
  2115. * @param {WeakMap<Dependency, Module>} references references
  2116. * @returns {boolean} true, when the references differ
  2117. */
  2118. const compareReferences = (module, references) => {
  2119. if (references === undefined) return true;
  2120. for (const connection of moduleGraph.getOutgoingConnections(module)) {
  2121. const d = connection.dependency;
  2122. if (!d) continue;
  2123. const entry = references.get(d);
  2124. if (entry === undefined) continue;
  2125. if (entry !== connection.module) return false;
  2126. }
  2127. return true;
  2128. };
  2129. const modulesWithoutCache = new Set(modules);
  2130. for (const [module, cachedMemCache] of moduleMemCacheCache) {
  2131. if (modulesWithoutCache.has(module)) {
  2132. const buildInfo = module.buildInfo;
  2133. if (buildInfo) {
  2134. if (cachedMemCache.buildInfo !== buildInfo) {
  2135. // use a new one
  2136. const memCache = new WeakTupleMap();
  2137. moduleMemCaches.set(module, memCache);
  2138. affectedModules.add(module);
  2139. cachedMemCache.buildInfo = buildInfo;
  2140. cachedMemCache.references = computeReferences(module);
  2141. cachedMemCache.memCache = memCache;
  2142. statChanged++;
  2143. } else if (!compareReferences(module, cachedMemCache.references)) {
  2144. // use a new one
  2145. const memCache = new WeakTupleMap();
  2146. moduleMemCaches.set(module, memCache);
  2147. affectedModules.add(module);
  2148. cachedMemCache.references = computeReferences(module);
  2149. cachedMemCache.memCache = memCache;
  2150. statReferencesChanged++;
  2151. } else {
  2152. // keep the old mem cache
  2153. moduleMemCaches.set(module, cachedMemCache.memCache);
  2154. statUnchanged++;
  2155. }
  2156. } else {
  2157. infectedModules.add(module);
  2158. moduleMemCacheCache.delete(module);
  2159. statWithoutBuild++;
  2160. }
  2161. modulesWithoutCache.delete(module);
  2162. } else {
  2163. moduleMemCacheCache.delete(module);
  2164. }
  2165. }
  2166. for (const module of modulesWithoutCache) {
  2167. const buildInfo = module.buildInfo;
  2168. if (buildInfo) {
  2169. // create a new entry
  2170. const memCache = new WeakTupleMap();
  2171. moduleMemCacheCache.set(module, {
  2172. buildInfo,
  2173. references: computeReferences(module),
  2174. memCache
  2175. });
  2176. moduleMemCaches.set(module, memCache);
  2177. affectedModules.add(module);
  2178. statNew++;
  2179. } else {
  2180. infectedModules.add(module);
  2181. statWithoutBuild++;
  2182. }
  2183. }
  2184. const reduceAffectType = connections => {
  2185. let affected = false;
  2186. for (const { dependency } of connections) {
  2187. if (!dependency) continue;
  2188. const type = dependency.couldAffectReferencingModule();
  2189. if (type === Dependency.TRANSITIVE) return Dependency.TRANSITIVE;
  2190. if (type === false) continue;
  2191. affected = true;
  2192. }
  2193. return affected;
  2194. };
  2195. const directOnlyInfectedModules = new Set();
  2196. for (const module of infectedModules) {
  2197. for (const [
  2198. referencingModule,
  2199. connections
  2200. ] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
  2201. if (!referencingModule) continue;
  2202. if (infectedModules.has(referencingModule)) continue;
  2203. const type = reduceAffectType(connections);
  2204. if (!type) continue;
  2205. if (type === true) {
  2206. directOnlyInfectedModules.add(referencingModule);
  2207. } else {
  2208. infectedModules.add(referencingModule);
  2209. }
  2210. }
  2211. }
  2212. for (const module of directOnlyInfectedModules) infectedModules.add(module);
  2213. const directOnlyAffectModules = new Set();
  2214. for (const module of affectedModules) {
  2215. for (const [
  2216. referencingModule,
  2217. connections
  2218. ] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
  2219. if (!referencingModule) continue;
  2220. if (infectedModules.has(referencingModule)) continue;
  2221. if (affectedModules.has(referencingModule)) continue;
  2222. const type = reduceAffectType(connections);
  2223. if (!type) continue;
  2224. if (type === true) {
  2225. directOnlyAffectModules.add(referencingModule);
  2226. } else {
  2227. affectedModules.add(referencingModule);
  2228. }
  2229. const memCache = new WeakTupleMap();
  2230. const cache = moduleMemCacheCache.get(referencingModule);
  2231. cache.memCache = memCache;
  2232. moduleMemCaches.set(referencingModule, memCache);
  2233. }
  2234. }
  2235. for (const module of directOnlyAffectModules) affectedModules.add(module);
  2236. this.logger.log(
  2237. `${Math.round(
  2238. (100 * (affectedModules.size + infectedModules.size)) /
  2239. this.modules.size
  2240. )}% (${affectedModules.size} affected + ${
  2241. infectedModules.size
  2242. } infected of ${
  2243. this.modules.size
  2244. }) modules flagged as affected (${statNew} new modules, ${statChanged} changed, ${statReferencesChanged} references changed, ${statUnchanged} unchanged, ${statWithoutBuild} were not built)`
  2245. );
  2246. }
  2247. _computeAffectedModulesWithChunkGraph() {
  2248. const { moduleMemCaches } = this;
  2249. if (!moduleMemCaches) return;
  2250. const moduleMemCaches2 = (this.moduleMemCaches2 = new Map());
  2251. const { moduleGraph, chunkGraph } = this;
  2252. const key = "memCache2";
  2253. let statUnchanged = 0;
  2254. let statChanged = 0;
  2255. let statNew = 0;
  2256. /**
  2257. * @param {Module} module module
  2258. * @returns {{ id: string | number, modules?: Map<Module, string | number | undefined>, blocks?: (string | number)[] }} references
  2259. */
  2260. const computeReferences = module => {
  2261. const id = chunkGraph.getModuleId(module);
  2262. /** @type {Map<Module, string | number | undefined>} */
  2263. let modules = undefined;
  2264. /** @type {(string | number)[] | undefined} */
  2265. let blocks = undefined;
  2266. const outgoing = moduleGraph.getOutgoingConnectionsByModule(module);
  2267. if (outgoing !== undefined) {
  2268. for (const m of outgoing.keys()) {
  2269. if (!m) continue;
  2270. if (modules === undefined) modules = new Map();
  2271. modules.set(m, chunkGraph.getModuleId(m));
  2272. }
  2273. }
  2274. if (module.blocks.length > 0) {
  2275. blocks = [];
  2276. const queue = Array.from(module.blocks);
  2277. for (const block of queue) {
  2278. const chunkGroup = chunkGraph.getBlockChunkGroup(block);
  2279. if (chunkGroup) {
  2280. for (const chunk of chunkGroup.chunks) {
  2281. blocks.push(chunk.id);
  2282. }
  2283. } else {
  2284. blocks.push(null);
  2285. }
  2286. queue.push.apply(queue, block.blocks);
  2287. }
  2288. }
  2289. return { id, modules, blocks };
  2290. };
  2291. /**
  2292. * @param {Module} module module
  2293. * @param {Object} references references
  2294. * @param {string | number} references.id id
  2295. * @param {Map<Module, string | number>=} references.modules modules
  2296. * @param {(string | number)[]=} references.blocks blocks
  2297. * @returns {boolean} ok?
  2298. */
  2299. const compareReferences = (module, { id, modules, blocks }) => {
  2300. if (id !== chunkGraph.getModuleId(module)) return false;
  2301. if (modules !== undefined) {
  2302. for (const [module, id] of modules) {
  2303. if (chunkGraph.getModuleId(module) !== id) return false;
  2304. }
  2305. }
  2306. if (blocks !== undefined) {
  2307. const queue = Array.from(module.blocks);
  2308. let i = 0;
  2309. for (const block of queue) {
  2310. const chunkGroup = chunkGraph.getBlockChunkGroup(block);
  2311. if (chunkGroup) {
  2312. for (const chunk of chunkGroup.chunks) {
  2313. if (i >= blocks.length || blocks[i++] !== chunk.id) return false;
  2314. }
  2315. } else {
  2316. if (i >= blocks.length || blocks[i++] !== null) return false;
  2317. }
  2318. queue.push.apply(queue, block.blocks);
  2319. }
  2320. if (i !== blocks.length) return false;
  2321. }
  2322. return true;
  2323. };
  2324. for (const [module, memCache] of moduleMemCaches) {
  2325. /** @type {{ references: { id: string | number, modules?: Map<Module, string | number | undefined>, blocks?: (string | number)[]}, memCache: WeakTupleMap<any[], any> }} */
  2326. const cache = memCache.get(key);
  2327. if (cache === undefined) {
  2328. const memCache2 = new WeakTupleMap();
  2329. memCache.set(key, {
  2330. references: computeReferences(module),
  2331. memCache: memCache2
  2332. });
  2333. moduleMemCaches2.set(module, memCache2);
  2334. statNew++;
  2335. } else if (!compareReferences(module, cache.references)) {
  2336. const memCache = new WeakTupleMap();
  2337. cache.references = computeReferences(module);
  2338. cache.memCache = memCache;
  2339. moduleMemCaches2.set(module, memCache);
  2340. statChanged++;
  2341. } else {
  2342. moduleMemCaches2.set(module, cache.memCache);
  2343. statUnchanged++;
  2344. }
  2345. }
  2346. this.logger.log(
  2347. `${Math.round(
  2348. (100 * statChanged) / (statNew + statChanged + statUnchanged)
  2349. )}% modules flagged as affected by chunk graph (${statNew} new modules, ${statChanged} changed, ${statUnchanged} unchanged)`
  2350. );
  2351. }
  2352. finish(callback) {
  2353. this.factorizeQueue.clear();
  2354. if (this.profile) {
  2355. this.logger.time("finish module profiles");
  2356. const ParallelismFactorCalculator = require("./util/ParallelismFactorCalculator");
  2357. const p = new ParallelismFactorCalculator();
  2358. const moduleGraph = this.moduleGraph;
  2359. const modulesWithProfiles = new Map();
  2360. for (const module of this.modules) {
  2361. const profile = moduleGraph.getProfile(module);
  2362. if (!profile) continue;
  2363. modulesWithProfiles.set(module, profile);
  2364. p.range(
  2365. profile.buildingStartTime,
  2366. profile.buildingEndTime,
  2367. f => (profile.buildingParallelismFactor = f)
  2368. );
  2369. p.range(
  2370. profile.factoryStartTime,
  2371. profile.factoryEndTime,
  2372. f => (profile.factoryParallelismFactor = f)
  2373. );
  2374. p.range(
  2375. profile.integrationStartTime,
  2376. profile.integrationEndTime,
  2377. f => (profile.integrationParallelismFactor = f)
  2378. );
  2379. p.range(
  2380. profile.storingStartTime,
  2381. profile.storingEndTime,
  2382. f => (profile.storingParallelismFactor = f)
  2383. );
  2384. p.range(
  2385. profile.restoringStartTime,
  2386. profile.restoringEndTime,
  2387. f => (profile.restoringParallelismFactor = f)
  2388. );
  2389. if (profile.additionalFactoryTimes) {
  2390. for (const { start, end } of profile.additionalFactoryTimes) {
  2391. const influence = (end - start) / profile.additionalFactories;
  2392. p.range(
  2393. start,
  2394. end,
  2395. f =>
  2396. (profile.additionalFactoriesParallelismFactor += f * influence)
  2397. );
  2398. }
  2399. }
  2400. }
  2401. p.calculate();
  2402. const logger = this.getLogger("webpack.Compilation.ModuleProfile");
  2403. const logByValue = (value, msg) => {
  2404. if (value > 1000) {
  2405. logger.error(msg);
  2406. } else if (value > 500) {
  2407. logger.warn(msg);
  2408. } else if (value > 200) {
  2409. logger.info(msg);
  2410. } else if (value > 30) {
  2411. logger.log(msg);
  2412. } else {
  2413. logger.debug(msg);
  2414. }
  2415. };
  2416. const logNormalSummary = (category, getDuration, getParallelism) => {
  2417. let sum = 0;
  2418. let max = 0;
  2419. for (const [module, profile] of modulesWithProfiles) {
  2420. const p = getParallelism(profile);
  2421. const d = getDuration(profile);
  2422. if (d === 0 || p === 0) continue;
  2423. const t = d / p;
  2424. sum += t;
  2425. if (t <= 10) continue;
  2426. logByValue(
  2427. t,
  2428. ` | ${Math.round(t)} ms${
  2429. p >= 1.1 ? ` (parallelism ${Math.round(p * 10) / 10})` : ""
  2430. } ${category} > ${module.readableIdentifier(this.requestShortener)}`
  2431. );
  2432. max = Math.max(max, t);
  2433. }
  2434. if (sum <= 10) return;
  2435. logByValue(
  2436. Math.max(sum / 10, max),
  2437. `${Math.round(sum)} ms ${category}`
  2438. );
  2439. };
  2440. const logByLoadersSummary = (category, getDuration, getParallelism) => {
  2441. const map = new Map();
  2442. for (const [module, profile] of modulesWithProfiles) {
  2443. const list = provide(
  2444. map,
  2445. module.type + "!" + module.identifier().replace(/(!|^)[^!]*$/, ""),
  2446. () => []
  2447. );
  2448. list.push({ module, profile });
  2449. }
  2450. let sum = 0;
  2451. let max = 0;
  2452. for (const [key, modules] of map) {
  2453. let innerSum = 0;
  2454. let innerMax = 0;
  2455. for (const { module, profile } of modules) {
  2456. const p = getParallelism(profile);
  2457. const d = getDuration(profile);
  2458. if (d === 0 || p === 0) continue;
  2459. const t = d / p;
  2460. innerSum += t;
  2461. if (t <= 10) continue;
  2462. logByValue(
  2463. t,
  2464. ` | | ${Math.round(t)} ms${
  2465. p >= 1.1 ? ` (parallelism ${Math.round(p * 10) / 10})` : ""
  2466. } ${category} > ${module.readableIdentifier(
  2467. this.requestShortener
  2468. )}`
  2469. );
  2470. innerMax = Math.max(innerMax, t);
  2471. }
  2472. sum += innerSum;
  2473. if (innerSum <= 10) continue;
  2474. const idx = key.indexOf("!");
  2475. const loaders = key.slice(idx + 1);
  2476. const moduleType = key.slice(0, idx);
  2477. const t = Math.max(innerSum / 10, innerMax);
  2478. logByValue(
  2479. t,
  2480. ` | ${Math.round(innerSum)} ms ${category} > ${
  2481. loaders
  2482. ? `${
  2483. modules.length
  2484. } x ${moduleType} with ${this.requestShortener.shorten(
  2485. loaders
  2486. )}`
  2487. : `${modules.length} x ${moduleType}`
  2488. }`
  2489. );
  2490. max = Math.max(max, t);
  2491. }
  2492. if (sum <= 10) return;
  2493. logByValue(
  2494. Math.max(sum / 10, max),
  2495. `${Math.round(sum)} ms ${category}`
  2496. );
  2497. };
  2498. logNormalSummary(
  2499. "resolve to new modules",
  2500. p => p.factory,
  2501. p => p.factoryParallelismFactor
  2502. );
  2503. logNormalSummary(
  2504. "resolve to existing modules",
  2505. p => p.additionalFactories,
  2506. p => p.additionalFactoriesParallelismFactor
  2507. );
  2508. logNormalSummary(
  2509. "integrate modules",
  2510. p => p.restoring,
  2511. p => p.restoringParallelismFactor
  2512. );
  2513. logByLoadersSummary(
  2514. "build modules",
  2515. p => p.building,
  2516. p => p.buildingParallelismFactor
  2517. );
  2518. logNormalSummary(
  2519. "store modules",
  2520. p => p.storing,
  2521. p => p.storingParallelismFactor
  2522. );
  2523. logNormalSummary(
  2524. "restore modules",
  2525. p => p.restoring,
  2526. p => p.restoringParallelismFactor
  2527. );
  2528. this.logger.timeEnd("finish module profiles");
  2529. }
  2530. this.logger.time("compute affected modules");
  2531. this._computeAffectedModules(this.modules);
  2532. this.logger.timeEnd("compute affected modules");
  2533. this.logger.time("finish modules");
  2534. const { modules, moduleMemCaches } = this;
  2535. this.hooks.finishModules.callAsync(modules, err => {
  2536. this.logger.timeEnd("finish modules");
  2537. if (err) return callback(err);
  2538. // extract warnings and errors from modules
  2539. this.moduleGraph.freeze("dependency errors");
  2540. // TODO keep a cacheToken (= {}) for each module in the graph
  2541. // create a new one per compilation and flag all updated files
  2542. // and parents with it
  2543. this.logger.time("report dependency errors and warnings");
  2544. for (const module of modules) {
  2545. // TODO only run for modules with changed cacheToken
  2546. // global WeakMap<CacheToken, WeakSet<Module>> to keep modules without errors/warnings
  2547. const memCache = moduleMemCaches && moduleMemCaches.get(module);
  2548. if (memCache && memCache.get("noWarningsOrErrors")) continue;
  2549. let hasProblems = this.reportDependencyErrorsAndWarnings(module, [
  2550. module
  2551. ]);
  2552. const errors = module.getErrors();
  2553. if (errors !== undefined) {
  2554. for (const error of errors) {
  2555. if (!error.module) {
  2556. error.module = module;
  2557. }
  2558. this.errors.push(error);
  2559. hasProblems = true;
  2560. }
  2561. }
  2562. const warnings = module.getWarnings();
  2563. if (warnings !== undefined) {
  2564. for (const warning of warnings) {
  2565. if (!warning.module) {
  2566. warning.module = module;
  2567. }
  2568. this.warnings.push(warning);
  2569. hasProblems = true;
  2570. }
  2571. }
  2572. if (!hasProblems && memCache) memCache.set("noWarningsOrErrors", true);
  2573. }
  2574. this.moduleGraph.unfreeze();
  2575. this.logger.timeEnd("report dependency errors and warnings");
  2576. callback();
  2577. });
  2578. }
  2579. unseal() {
  2580. this.hooks.unseal.call();
  2581. this.chunks.clear();
  2582. this.chunkGroups.length = 0;
  2583. this.namedChunks.clear();
  2584. this.namedChunkGroups.clear();
  2585. this.entrypoints.clear();
  2586. this.additionalChunkAssets.length = 0;
  2587. this.assets = {};
  2588. this.assetsInfo.clear();
  2589. this.moduleGraph.removeAllModuleAttributes();
  2590. this.moduleGraph.unfreeze();
  2591. this.moduleMemCaches2 = undefined;
  2592. }
  2593. /**
  2594. * @param {Callback} callback signals when the call finishes
  2595. * @returns {void}
  2596. */
  2597. seal(callback) {
  2598. const finalCallback = err => {
  2599. this.factorizeQueue.clear();
  2600. this.buildQueue.clear();
  2601. this.rebuildQueue.clear();
  2602. this.processDependenciesQueue.clear();
  2603. this.addModuleQueue.clear();
  2604. return callback(err);
  2605. };
  2606. const chunkGraph = new ChunkGraph(
  2607. this.moduleGraph,
  2608. this.outputOptions.hashFunction
  2609. );
  2610. this.chunkGraph = chunkGraph;
  2611. if (this._backCompat) {
  2612. for (const module of this.modules) {
  2613. ChunkGraph.setChunkGraphForModule(module, chunkGraph);
  2614. }
  2615. }
  2616. this.hooks.seal.call();
  2617. this.logger.time("optimize dependencies");
  2618. while (this.hooks.optimizeDependencies.call(this.modules)) {
  2619. /* empty */
  2620. }
  2621. this.hooks.afterOptimizeDependencies.call(this.modules);
  2622. this.logger.timeEnd("optimize dependencies");
  2623. this.logger.time("create chunks");
  2624. this.hooks.beforeChunks.call();
  2625. this.moduleGraph.freeze("seal");
  2626. /** @type {Map<Entrypoint, Module[]>} */
  2627. const chunkGraphInit = new Map();
  2628. for (const [name, { dependencies, includeDependencies, options }] of this
  2629. .entries) {
  2630. const chunk = this.addChunk(name);
  2631. if (options.filename) {
  2632. chunk.filenameTemplate = options.filename;
  2633. }
  2634. const entrypoint = new Entrypoint(options);
  2635. if (!options.dependOn && !options.runtime) {
  2636. entrypoint.setRuntimeChunk(chunk);
  2637. }
  2638. entrypoint.setEntrypointChunk(chunk);
  2639. this.namedChunkGroups.set(name, entrypoint);
  2640. this.entrypoints.set(name, entrypoint);
  2641. this.chunkGroups.push(entrypoint);
  2642. connectChunkGroupAndChunk(entrypoint, chunk);
  2643. const entryModules = new Set();
  2644. for (const dep of [...this.globalEntry.dependencies, ...dependencies]) {
  2645. entrypoint.addOrigin(null, { name }, /** @type {any} */ (dep).request);
  2646. const module = this.moduleGraph.getModule(dep);
  2647. if (module) {
  2648. chunkGraph.connectChunkAndEntryModule(chunk, module, entrypoint);
  2649. entryModules.add(module);
  2650. const modulesList = chunkGraphInit.get(entrypoint);
  2651. if (modulesList === undefined) {
  2652. chunkGraphInit.set(entrypoint, [module]);
  2653. } else {
  2654. modulesList.push(module);
  2655. }
  2656. }
  2657. }
  2658. this.assignDepths(entryModules);
  2659. const mapAndSort = deps =>
  2660. deps
  2661. .map(dep => this.moduleGraph.getModule(dep))
  2662. .filter(Boolean)
  2663. .sort(compareModulesByIdentifier);
  2664. const includedModules = [
  2665. ...mapAndSort(this.globalEntry.includeDependencies),
  2666. ...mapAndSort(includeDependencies)
  2667. ];
  2668. let modulesList = chunkGraphInit.get(entrypoint);
  2669. if (modulesList === undefined) {
  2670. chunkGraphInit.set(entrypoint, (modulesList = []));
  2671. }
  2672. for (const module of includedModules) {
  2673. this.assignDepth(module);
  2674. modulesList.push(module);
  2675. }
  2676. }
  2677. const runtimeChunks = new Set();
  2678. outer: for (const [
  2679. name,
  2680. {
  2681. options: { dependOn, runtime }
  2682. }
  2683. ] of this.entries) {
  2684. if (dependOn && runtime) {
  2685. const err =
  2686. new WebpackError(`Entrypoint '${name}' has 'dependOn' and 'runtime' specified. This is not valid.
  2687. Entrypoints that depend on other entrypoints do not have their own runtime.
  2688. They will use the runtime(s) from referenced entrypoints instead.
  2689. Remove the 'runtime' option from the entrypoint.`);
  2690. const entry = this.entrypoints.get(name);
  2691. err.chunk = entry.getEntrypointChunk();
  2692. this.errors.push(err);
  2693. }
  2694. if (dependOn) {
  2695. const entry = this.entrypoints.get(name);
  2696. const referencedChunks = entry
  2697. .getEntrypointChunk()
  2698. .getAllReferencedChunks();
  2699. const dependOnEntries = [];
  2700. for (const dep of dependOn) {
  2701. const dependency = this.entrypoints.get(dep);
  2702. if (!dependency) {
  2703. throw new Error(
  2704. `Entry ${name} depends on ${dep}, but this entry was not found`
  2705. );
  2706. }
  2707. if (referencedChunks.has(dependency.getEntrypointChunk())) {
  2708. const err = new WebpackError(
  2709. `Entrypoints '${name}' and '${dep}' use 'dependOn' to depend on each other in a circular way.`
  2710. );
  2711. const entryChunk = entry.getEntrypointChunk();
  2712. err.chunk = entryChunk;
  2713. this.errors.push(err);
  2714. entry.setRuntimeChunk(entryChunk);
  2715. continue outer;
  2716. }
  2717. dependOnEntries.push(dependency);
  2718. }
  2719. for (const dependency of dependOnEntries) {
  2720. connectChunkGroupParentAndChild(dependency, entry);
  2721. }
  2722. } else if (runtime) {
  2723. const entry = this.entrypoints.get(name);
  2724. let chunk = this.namedChunks.get(runtime);
  2725. if (chunk) {
  2726. if (!runtimeChunks.has(chunk)) {
  2727. const err =
  2728. new WebpackError(`Entrypoint '${name}' has a 'runtime' option which points to another entrypoint named '${runtime}'.
  2729. It's not valid to use other entrypoints as runtime chunk.
  2730. Did you mean to use 'dependOn: ${JSON.stringify(
  2731. runtime
  2732. )}' instead to allow using entrypoint '${name}' within the runtime of entrypoint '${runtime}'? For this '${runtime}' must always be loaded when '${name}' is used.
  2733. Or do you want to use the entrypoints '${name}' and '${runtime}' independently on the same page with a shared runtime? In this case give them both the same value for the 'runtime' option. It must be a name not already used by an entrypoint.`);
  2734. const entryChunk = entry.getEntrypointChunk();
  2735. err.chunk = entryChunk;
  2736. this.errors.push(err);
  2737. entry.setRuntimeChunk(entryChunk);
  2738. continue;
  2739. }
  2740. } else {
  2741. chunk = this.addChunk(runtime);
  2742. chunk.preventIntegration = true;
  2743. runtimeChunks.add(chunk);
  2744. }
  2745. entry.unshiftChunk(chunk);
  2746. chunk.addGroup(entry);
  2747. entry.setRuntimeChunk(chunk);
  2748. }
  2749. }
  2750. buildChunkGraph(this, chunkGraphInit);
  2751. this.hooks.afterChunks.call(this.chunks);
  2752. this.logger.timeEnd("create chunks");
  2753. this.logger.time("optimize");
  2754. this.hooks.optimize.call();
  2755. while (this.hooks.optimizeModules.call(this.modules)) {
  2756. /* empty */
  2757. }
  2758. this.hooks.afterOptimizeModules.call(this.modules);
  2759. while (this.hooks.optimizeChunks.call(this.chunks, this.chunkGroups)) {
  2760. /* empty */
  2761. }
  2762. this.hooks.afterOptimizeChunks.call(this.chunks, this.chunkGroups);
  2763. this.hooks.optimizeTree.callAsync(this.chunks, this.modules, err => {
  2764. if (err) {
  2765. return finalCallback(
  2766. makeWebpackError(err, "Compilation.hooks.optimizeTree")
  2767. );
  2768. }
  2769. this.hooks.afterOptimizeTree.call(this.chunks, this.modules);
  2770. this.hooks.optimizeChunkModules.callAsync(
  2771. this.chunks,
  2772. this.modules,
  2773. err => {
  2774. if (err) {
  2775. return finalCallback(
  2776. makeWebpackError(err, "Compilation.hooks.optimizeChunkModules")
  2777. );
  2778. }
  2779. this.hooks.afterOptimizeChunkModules.call(this.chunks, this.modules);
  2780. const shouldRecord = this.hooks.shouldRecord.call() !== false;
  2781. this.hooks.reviveModules.call(this.modules, this.records);
  2782. this.hooks.beforeModuleIds.call(this.modules);
  2783. this.hooks.moduleIds.call(this.modules);
  2784. this.hooks.optimizeModuleIds.call(this.modules);
  2785. this.hooks.afterOptimizeModuleIds.call(this.modules);
  2786. this.hooks.reviveChunks.call(this.chunks, this.records);
  2787. this.hooks.beforeChunkIds.call(this.chunks);
  2788. this.hooks.chunkIds.call(this.chunks);
  2789. this.hooks.optimizeChunkIds.call(this.chunks);
  2790. this.hooks.afterOptimizeChunkIds.call(this.chunks);
  2791. this.assignRuntimeIds();
  2792. this.logger.time("compute affected modules with chunk graph");
  2793. this._computeAffectedModulesWithChunkGraph();
  2794. this.logger.timeEnd("compute affected modules with chunk graph");
  2795. this.sortItemsWithChunkIds();
  2796. if (shouldRecord) {
  2797. this.hooks.recordModules.call(this.modules, this.records);
  2798. this.hooks.recordChunks.call(this.chunks, this.records);
  2799. }
  2800. this.hooks.optimizeCodeGeneration.call(this.modules);
  2801. this.logger.timeEnd("optimize");
  2802. this.logger.time("module hashing");
  2803. this.hooks.beforeModuleHash.call();
  2804. this.createModuleHashes();
  2805. this.hooks.afterModuleHash.call();
  2806. this.logger.timeEnd("module hashing");
  2807. this.logger.time("code generation");
  2808. this.hooks.beforeCodeGeneration.call();
  2809. this.codeGeneration(err => {
  2810. if (err) {
  2811. return finalCallback(err);
  2812. }
  2813. this.hooks.afterCodeGeneration.call();
  2814. this.logger.timeEnd("code generation");
  2815. this.logger.time("runtime requirements");
  2816. this.hooks.beforeRuntimeRequirements.call();
  2817. this.processRuntimeRequirements();
  2818. this.hooks.afterRuntimeRequirements.call();
  2819. this.logger.timeEnd("runtime requirements");
  2820. this.logger.time("hashing");
  2821. this.hooks.beforeHash.call();
  2822. const codeGenerationJobs = this.createHash();
  2823. this.hooks.afterHash.call();
  2824. this.logger.timeEnd("hashing");
  2825. this._runCodeGenerationJobs(codeGenerationJobs, err => {
  2826. if (err) {
  2827. return finalCallback(err);
  2828. }
  2829. if (shouldRecord) {
  2830. this.logger.time("record hash");
  2831. this.hooks.recordHash.call(this.records);
  2832. this.logger.timeEnd("record hash");
  2833. }
  2834. this.logger.time("module assets");
  2835. this.clearAssets();
  2836. this.hooks.beforeModuleAssets.call();
  2837. this.createModuleAssets();
  2838. this.logger.timeEnd("module assets");
  2839. const cont = () => {
  2840. this.logger.time("process assets");
  2841. this.hooks.processAssets.callAsync(this.assets, err => {
  2842. if (err) {
  2843. return finalCallback(
  2844. makeWebpackError(err, "Compilation.hooks.processAssets")
  2845. );
  2846. }
  2847. this.hooks.afterProcessAssets.call(this.assets);
  2848. this.logger.timeEnd("process assets");
  2849. this.assets = this._backCompat
  2850. ? soonFrozenObjectDeprecation(
  2851. this.assets,
  2852. "Compilation.assets",
  2853. "DEP_WEBPACK_COMPILATION_ASSETS",
  2854. `BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
  2855. Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
  2856. Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.`
  2857. )
  2858. : Object.freeze(this.assets);
  2859. this.summarizeDependencies();
  2860. if (shouldRecord) {
  2861. this.hooks.record.call(this, this.records);
  2862. }
  2863. if (this.hooks.needAdditionalSeal.call()) {
  2864. this.unseal();
  2865. return this.seal(callback);
  2866. }
  2867. return this.hooks.afterSeal.callAsync(err => {
  2868. if (err) {
  2869. return finalCallback(
  2870. makeWebpackError(err, "Compilation.hooks.afterSeal")
  2871. );
  2872. }
  2873. this.fileSystemInfo.logStatistics();
  2874. finalCallback();
  2875. });
  2876. });
  2877. };
  2878. this.logger.time("create chunk assets");
  2879. if (this.hooks.shouldGenerateChunkAssets.call() !== false) {
  2880. this.hooks.beforeChunkAssets.call();
  2881. this.createChunkAssets(err => {
  2882. this.logger.timeEnd("create chunk assets");
  2883. if (err) {
  2884. return finalCallback(err);
  2885. }
  2886. cont();
  2887. });
  2888. } else {
  2889. this.logger.timeEnd("create chunk assets");
  2890. cont();
  2891. }
  2892. });
  2893. });
  2894. }
  2895. );
  2896. });
  2897. }
  2898. /**
  2899. * @param {Module} module module to report from
  2900. * @param {DependenciesBlock[]} blocks blocks to report from
  2901. * @returns {boolean} true, when it has warnings or errors
  2902. */
  2903. reportDependencyErrorsAndWarnings(module, blocks) {
  2904. let hasProblems = false;
  2905. for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
  2906. const block = blocks[indexBlock];
  2907. const dependencies = block.dependencies;
  2908. for (let indexDep = 0; indexDep < dependencies.length; indexDep++) {
  2909. const d = dependencies[indexDep];
  2910. const warnings = d.getWarnings(this.moduleGraph);
  2911. if (warnings) {
  2912. for (let indexWar = 0; indexWar < warnings.length; indexWar++) {
  2913. const w = warnings[indexWar];
  2914. const warning = new ModuleDependencyWarning(module, w, d.loc);
  2915. this.warnings.push(warning);
  2916. hasProblems = true;
  2917. }
  2918. }
  2919. const errors = d.getErrors(this.moduleGraph);
  2920. if (errors) {
  2921. for (let indexErr = 0; indexErr < errors.length; indexErr++) {
  2922. const e = errors[indexErr];
  2923. const error = new ModuleDependencyError(module, e, d.loc);
  2924. this.errors.push(error);
  2925. hasProblems = true;
  2926. }
  2927. }
  2928. }
  2929. if (this.reportDependencyErrorsAndWarnings(module, block.blocks))
  2930. hasProblems = true;
  2931. }
  2932. return hasProblems;
  2933. }
  2934. codeGeneration(callback) {
  2935. const { chunkGraph } = this;
  2936. this.codeGenerationResults = new CodeGenerationResults(
  2937. this.outputOptions.hashFunction
  2938. );
  2939. /** @type {{module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}[]} */
  2940. const jobs = [];
  2941. for (const module of this.modules) {
  2942. const runtimes = chunkGraph.getModuleRuntimes(module);
  2943. if (runtimes.size === 1) {
  2944. for (const runtime of runtimes) {
  2945. const hash = chunkGraph.getModuleHash(module, runtime);
  2946. jobs.push({ module, hash, runtime, runtimes: [runtime] });
  2947. }
  2948. } else if (runtimes.size > 1) {
  2949. /** @type {Map<string, { runtimes: RuntimeSpec[] }>} */
  2950. const map = new Map();
  2951. for (const runtime of runtimes) {
  2952. const hash = chunkGraph.getModuleHash(module, runtime);
  2953. const job = map.get(hash);
  2954. if (job === undefined) {
  2955. const newJob = { module, hash, runtime, runtimes: [runtime] };
  2956. jobs.push(newJob);
  2957. map.set(hash, newJob);
  2958. } else {
  2959. job.runtimes.push(runtime);
  2960. }
  2961. }
  2962. }
  2963. }
  2964. this._runCodeGenerationJobs(jobs, callback);
  2965. }
  2966. _runCodeGenerationJobs(jobs, callback) {
  2967. if (jobs.length === 0) {
  2968. return callback();
  2969. }
  2970. let statModulesFromCache = 0;
  2971. let statModulesGenerated = 0;
  2972. const { chunkGraph, moduleGraph, dependencyTemplates, runtimeTemplate } =
  2973. this;
  2974. const results = this.codeGenerationResults;
  2975. const errors = [];
  2976. /** @type {Set<Module> | undefined} */
  2977. let notCodeGeneratedModules = undefined;
  2978. const runIteration = () => {
  2979. let delayedJobs = [];
  2980. let delayedModules = new Set();
  2981. asyncLib.eachLimit(
  2982. jobs,
  2983. this.options.parallelism,
  2984. (job, callback) => {
  2985. const { module } = job;
  2986. const { codeGenerationDependencies } = module;
  2987. if (codeGenerationDependencies !== undefined) {
  2988. if (
  2989. notCodeGeneratedModules === undefined ||
  2990. codeGenerationDependencies.some(dep => {
  2991. const referencedModule = moduleGraph.getModule(dep);
  2992. return notCodeGeneratedModules.has(referencedModule);
  2993. })
  2994. ) {
  2995. delayedJobs.push(job);
  2996. delayedModules.add(module);
  2997. return callback();
  2998. }
  2999. }
  3000. const { hash, runtime, runtimes } = job;
  3001. this._codeGenerationModule(
  3002. module,
  3003. runtime,
  3004. runtimes,
  3005. hash,
  3006. dependencyTemplates,
  3007. chunkGraph,
  3008. moduleGraph,
  3009. runtimeTemplate,
  3010. errors,
  3011. results,
  3012. (err, codeGenerated) => {
  3013. if (codeGenerated) statModulesGenerated++;
  3014. else statModulesFromCache++;
  3015. callback(err);
  3016. }
  3017. );
  3018. },
  3019. err => {
  3020. if (err) return callback(err);
  3021. if (delayedJobs.length > 0) {
  3022. if (delayedJobs.length === jobs.length) {
  3023. return callback(
  3024. new Error(
  3025. `Unable to make progress during code generation because of circular code generation dependency: ${Array.from(
  3026. delayedModules,
  3027. m => m.identifier()
  3028. ).join(", ")}`
  3029. )
  3030. );
  3031. }
  3032. jobs = delayedJobs;
  3033. delayedJobs = [];
  3034. notCodeGeneratedModules = delayedModules;
  3035. delayedModules = new Set();
  3036. return runIteration();
  3037. }
  3038. if (errors.length > 0) {
  3039. errors.sort(
  3040. compareSelect(err => err.module, compareModulesByIdentifier)
  3041. );
  3042. for (const error of errors) {
  3043. this.errors.push(error);
  3044. }
  3045. }
  3046. this.logger.log(
  3047. `${Math.round(
  3048. (100 * statModulesGenerated) /
  3049. (statModulesGenerated + statModulesFromCache)
  3050. )}% code generated (${statModulesGenerated} generated, ${statModulesFromCache} from cache)`
  3051. );
  3052. callback();
  3053. }
  3054. );
  3055. };
  3056. runIteration();
  3057. }
  3058. /**
  3059. * @param {Module} module module
  3060. * @param {RuntimeSpec} runtime runtime
  3061. * @param {RuntimeSpec[]} runtimes runtimes
  3062. * @param {string} hash hash
  3063. * @param {DependencyTemplates} dependencyTemplates dependencyTemplates
  3064. * @param {ChunkGraph} chunkGraph chunkGraph
  3065. * @param {ModuleGraph} moduleGraph moduleGraph
  3066. * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
  3067. * @param {WebpackError[]} errors errors
  3068. * @param {CodeGenerationResults} results results
  3069. * @param {function(WebpackError=, boolean=): void} callback callback
  3070. */
  3071. _codeGenerationModule(
  3072. module,
  3073. runtime,
  3074. runtimes,
  3075. hash,
  3076. dependencyTemplates,
  3077. chunkGraph,
  3078. moduleGraph,
  3079. runtimeTemplate,
  3080. errors,
  3081. results,
  3082. callback
  3083. ) {
  3084. let codeGenerated = false;
  3085. const cache = new MultiItemCache(
  3086. runtimes.map(runtime =>
  3087. this._codeGenerationCache.getItemCache(
  3088. `${module.identifier()}|${getRuntimeKey(runtime)}`,
  3089. `${hash}|${dependencyTemplates.getHash()}`
  3090. )
  3091. )
  3092. );
  3093. cache.get((err, cachedResult) => {
  3094. if (err) return callback(err);
  3095. let result;
  3096. if (!cachedResult) {
  3097. try {
  3098. codeGenerated = true;
  3099. this.codeGeneratedModules.add(module);
  3100. result = module.codeGeneration({
  3101. chunkGraph,
  3102. moduleGraph,
  3103. dependencyTemplates,
  3104. runtimeTemplate,
  3105. runtime,
  3106. codeGenerationResults: results,
  3107. compilation: this
  3108. });
  3109. } catch (err) {
  3110. errors.push(new CodeGenerationError(module, err));
  3111. result = cachedResult = {
  3112. sources: new Map(),
  3113. runtimeRequirements: null
  3114. };
  3115. }
  3116. } else {
  3117. result = cachedResult;
  3118. }
  3119. for (const runtime of runtimes) {
  3120. results.add(module, runtime, result);
  3121. }
  3122. if (!cachedResult) {
  3123. cache.store(result, err => callback(err, codeGenerated));
  3124. } else {
  3125. callback(null, codeGenerated);
  3126. }
  3127. });
  3128. }
  3129. _getChunkGraphEntries() {
  3130. /** @type {Set<Chunk>} */
  3131. const treeEntries = new Set();
  3132. for (const ep of this.entrypoints.values()) {
  3133. const chunk = ep.getRuntimeChunk();
  3134. if (chunk) treeEntries.add(chunk);
  3135. }
  3136. for (const ep of this.asyncEntrypoints) {
  3137. const chunk = ep.getRuntimeChunk();
  3138. if (chunk) treeEntries.add(chunk);
  3139. }
  3140. return treeEntries;
  3141. }
  3142. /**
  3143. * @param {Object} options options
  3144. * @param {ChunkGraph=} options.chunkGraph the chunk graph
  3145. * @param {Iterable<Module>=} options.modules modules
  3146. * @param {Iterable<Chunk>=} options.chunks chunks
  3147. * @param {CodeGenerationResults=} options.codeGenerationResults codeGenerationResults
  3148. * @param {Iterable<Chunk>=} options.chunkGraphEntries chunkGraphEntries
  3149. * @returns {void}
  3150. */
  3151. processRuntimeRequirements({
  3152. chunkGraph = this.chunkGraph,
  3153. modules = this.modules,
  3154. chunks = this.chunks,
  3155. codeGenerationResults = this.codeGenerationResults,
  3156. chunkGraphEntries = this._getChunkGraphEntries()
  3157. } = {}) {
  3158. const context = { chunkGraph, codeGenerationResults };
  3159. const { moduleMemCaches2 } = this;
  3160. this.logger.time("runtime requirements.modules");
  3161. const additionalModuleRuntimeRequirements =
  3162. this.hooks.additionalModuleRuntimeRequirements;
  3163. const runtimeRequirementInModule = this.hooks.runtimeRequirementInModule;
  3164. for (const module of modules) {
  3165. if (chunkGraph.getNumberOfModuleChunks(module) > 0) {
  3166. const memCache = moduleMemCaches2 && moduleMemCaches2.get(module);
  3167. for (const runtime of chunkGraph.getModuleRuntimes(module)) {
  3168. if (memCache) {
  3169. const cached = memCache.get(
  3170. `moduleRuntimeRequirements-${getRuntimeKey(runtime)}`
  3171. );
  3172. if (cached !== undefined) {
  3173. if (cached !== null) {
  3174. chunkGraph.addModuleRuntimeRequirements(
  3175. module,
  3176. runtime,
  3177. cached,
  3178. false
  3179. );
  3180. }
  3181. continue;
  3182. }
  3183. }
  3184. let set;
  3185. const runtimeRequirements =
  3186. codeGenerationResults.getRuntimeRequirements(module, runtime);
  3187. if (runtimeRequirements && runtimeRequirements.size > 0) {
  3188. set = new Set(runtimeRequirements);
  3189. } else if (additionalModuleRuntimeRequirements.isUsed()) {
  3190. set = new Set();
  3191. } else {
  3192. if (memCache) {
  3193. memCache.set(
  3194. `moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
  3195. null
  3196. );
  3197. }
  3198. continue;
  3199. }
  3200. additionalModuleRuntimeRequirements.call(module, set, context);
  3201. for (const r of set) {
  3202. const hook = runtimeRequirementInModule.get(r);
  3203. if (hook !== undefined) hook.call(module, set, context);
  3204. }
  3205. if (set.size === 0) {
  3206. if (memCache) {
  3207. memCache.set(
  3208. `moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
  3209. null
  3210. );
  3211. }
  3212. } else {
  3213. if (memCache) {
  3214. memCache.set(
  3215. `moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
  3216. set
  3217. );
  3218. chunkGraph.addModuleRuntimeRequirements(
  3219. module,
  3220. runtime,
  3221. set,
  3222. false
  3223. );
  3224. } else {
  3225. chunkGraph.addModuleRuntimeRequirements(module, runtime, set);
  3226. }
  3227. }
  3228. }
  3229. }
  3230. }
  3231. this.logger.timeEnd("runtime requirements.modules");
  3232. this.logger.time("runtime requirements.chunks");
  3233. for (const chunk of chunks) {
  3234. const set = new Set();
  3235. for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
  3236. const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
  3237. module,
  3238. chunk.runtime
  3239. );
  3240. for (const r of runtimeRequirements) set.add(r);
  3241. }
  3242. this.hooks.additionalChunkRuntimeRequirements.call(chunk, set, context);
  3243. for (const r of set) {
  3244. this.hooks.runtimeRequirementInChunk.for(r).call(chunk, set, context);
  3245. }
  3246. chunkGraph.addChunkRuntimeRequirements(chunk, set);
  3247. }
  3248. this.logger.timeEnd("runtime requirements.chunks");
  3249. this.logger.time("runtime requirements.entries");
  3250. for (const treeEntry of chunkGraphEntries) {
  3251. const set = new Set();
  3252. for (const chunk of treeEntry.getAllReferencedChunks()) {
  3253. const runtimeRequirements =
  3254. chunkGraph.getChunkRuntimeRequirements(chunk);
  3255. for (const r of runtimeRequirements) set.add(r);
  3256. }
  3257. this.hooks.additionalTreeRuntimeRequirements.call(
  3258. treeEntry,
  3259. set,
  3260. context
  3261. );
  3262. for (const r of set) {
  3263. this.hooks.runtimeRequirementInTree
  3264. .for(r)
  3265. .call(treeEntry, set, context);
  3266. }
  3267. chunkGraph.addTreeRuntimeRequirements(treeEntry, set);
  3268. }
  3269. this.logger.timeEnd("runtime requirements.entries");
  3270. }
  3271. // TODO webpack 6 make chunkGraph argument non-optional
  3272. /**
  3273. * @param {Chunk} chunk target chunk
  3274. * @param {RuntimeModule} module runtime module
  3275. * @param {ChunkGraph} chunkGraph the chunk graph
  3276. * @returns {void}
  3277. */
  3278. addRuntimeModule(chunk, module, chunkGraph = this.chunkGraph) {
  3279. // Deprecated ModuleGraph association
  3280. if (this._backCompat)
  3281. ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
  3282. // add it to the list
  3283. this.modules.add(module);
  3284. this._modules.set(module.identifier(), module);
  3285. // connect to the chunk graph
  3286. chunkGraph.connectChunkAndModule(chunk, module);
  3287. chunkGraph.connectChunkAndRuntimeModule(chunk, module);
  3288. if (module.fullHash) {
  3289. chunkGraph.addFullHashModuleToChunk(chunk, module);
  3290. } else if (module.dependentHash) {
  3291. chunkGraph.addDependentHashModuleToChunk(chunk, module);
  3292. }
  3293. // attach runtime module
  3294. module.attach(this, chunk, chunkGraph);
  3295. // Setup internals
  3296. const exportsInfo = this.moduleGraph.getExportsInfo(module);
  3297. exportsInfo.setHasProvideInfo();
  3298. if (typeof chunk.runtime === "string") {
  3299. exportsInfo.setUsedForSideEffectsOnly(chunk.runtime);
  3300. } else if (chunk.runtime === undefined) {
  3301. exportsInfo.setUsedForSideEffectsOnly(undefined);
  3302. } else {
  3303. for (const runtime of chunk.runtime) {
  3304. exportsInfo.setUsedForSideEffectsOnly(runtime);
  3305. }
  3306. }
  3307. chunkGraph.addModuleRuntimeRequirements(
  3308. module,
  3309. chunk.runtime,
  3310. new Set([RuntimeGlobals.requireScope])
  3311. );
  3312. // runtime modules don't need ids
  3313. chunkGraph.setModuleId(module, "");
  3314. // Call hook
  3315. this.hooks.runtimeModule.call(module, chunk);
  3316. }
  3317. /**
  3318. * If `module` is passed, `loc` and `request` must also be passed.
  3319. * @param {string | ChunkGroupOptions} groupOptions options for the chunk group
  3320. * @param {Module=} module the module the references the chunk group
  3321. * @param {DependencyLocation=} loc the location from with the chunk group is referenced (inside of module)
  3322. * @param {string=} request the request from which the the chunk group is referenced
  3323. * @returns {ChunkGroup} the new or existing chunk group
  3324. */
  3325. addChunkInGroup(groupOptions, module, loc, request) {
  3326. if (typeof groupOptions === "string") {
  3327. groupOptions = { name: groupOptions };
  3328. }
  3329. const name = groupOptions.name;
  3330. if (name) {
  3331. const chunkGroup = this.namedChunkGroups.get(name);
  3332. if (chunkGroup !== undefined) {
  3333. chunkGroup.addOptions(groupOptions);
  3334. if (module) {
  3335. chunkGroup.addOrigin(module, loc, request);
  3336. }
  3337. return chunkGroup;
  3338. }
  3339. }
  3340. const chunkGroup = new ChunkGroup(groupOptions);
  3341. if (module) chunkGroup.addOrigin(module, loc, request);
  3342. const chunk = this.addChunk(name);
  3343. connectChunkGroupAndChunk(chunkGroup, chunk);
  3344. this.chunkGroups.push(chunkGroup);
  3345. if (name) {
  3346. this.namedChunkGroups.set(name, chunkGroup);
  3347. }
  3348. return chunkGroup;
  3349. }
  3350. /**
  3351. * @param {EntryOptions} options options for the entrypoint
  3352. * @param {Module} module the module the references the chunk group
  3353. * @param {DependencyLocation} loc the location from with the chunk group is referenced (inside of module)
  3354. * @param {string} request the request from which the the chunk group is referenced
  3355. * @returns {Entrypoint} the new or existing entrypoint
  3356. */
  3357. addAsyncEntrypoint(options, module, loc, request) {
  3358. const name = options.name;
  3359. if (name) {
  3360. const entrypoint = this.namedChunkGroups.get(name);
  3361. if (entrypoint instanceof Entrypoint) {
  3362. if (entrypoint !== undefined) {
  3363. if (module) {
  3364. entrypoint.addOrigin(module, loc, request);
  3365. }
  3366. return entrypoint;
  3367. }
  3368. } else if (entrypoint) {
  3369. throw new Error(
  3370. `Cannot add an async entrypoint with the name '${name}', because there is already an chunk group with this name`
  3371. );
  3372. }
  3373. }
  3374. const chunk = this.addChunk(name);
  3375. if (options.filename) {
  3376. chunk.filenameTemplate = options.filename;
  3377. }
  3378. const entrypoint = new Entrypoint(options, false);
  3379. entrypoint.setRuntimeChunk(chunk);
  3380. entrypoint.setEntrypointChunk(chunk);
  3381. if (name) {
  3382. this.namedChunkGroups.set(name, entrypoint);
  3383. }
  3384. this.chunkGroups.push(entrypoint);
  3385. this.asyncEntrypoints.push(entrypoint);
  3386. connectChunkGroupAndChunk(entrypoint, chunk);
  3387. if (module) {
  3388. entrypoint.addOrigin(module, loc, request);
  3389. }
  3390. return entrypoint;
  3391. }
  3392. /**
  3393. * This method first looks to see if a name is provided for a new chunk,
  3394. * and first looks to see if any named chunks already exist and reuse that chunk instead.
  3395. *
  3396. * @param {string=} name optional chunk name to be provided
  3397. * @returns {Chunk} create a chunk (invoked during seal event)
  3398. */
  3399. addChunk(name) {
  3400. if (name) {
  3401. const chunk = this.namedChunks.get(name);
  3402. if (chunk !== undefined) {
  3403. return chunk;
  3404. }
  3405. }
  3406. const chunk = new Chunk(name, this._backCompat);
  3407. this.chunks.add(chunk);
  3408. if (this._backCompat)
  3409. ChunkGraph.setChunkGraphForChunk(chunk, this.chunkGraph);
  3410. if (name) {
  3411. this.namedChunks.set(name, chunk);
  3412. }
  3413. return chunk;
  3414. }
  3415. /**
  3416. * @deprecated
  3417. * @param {Module} module module to assign depth
  3418. * @returns {void}
  3419. */
  3420. assignDepth(module) {
  3421. const moduleGraph = this.moduleGraph;
  3422. const queue = new Set([module]);
  3423. let depth;
  3424. moduleGraph.setDepth(module, 0);
  3425. /**
  3426. * @param {Module} module module for processing
  3427. * @returns {void}
  3428. */
  3429. const processModule = module => {
  3430. if (!moduleGraph.setDepthIfLower(module, depth)) return;
  3431. queue.add(module);
  3432. };
  3433. for (module of queue) {
  3434. queue.delete(module);
  3435. depth = moduleGraph.getDepth(module) + 1;
  3436. for (const connection of moduleGraph.getOutgoingConnections(module)) {
  3437. const refModule = connection.module;
  3438. if (refModule) {
  3439. processModule(refModule);
  3440. }
  3441. }
  3442. }
  3443. }
  3444. /**
  3445. * @param {Set<Module>} modules module to assign depth
  3446. * @returns {void}
  3447. */
  3448. assignDepths(modules) {
  3449. const moduleGraph = this.moduleGraph;
  3450. /** @type {Set<Module | number>} */
  3451. const queue = new Set(modules);
  3452. queue.add(1);
  3453. let depth = 0;
  3454. let i = 0;
  3455. for (const module of queue) {
  3456. i++;
  3457. if (typeof module === "number") {
  3458. depth = module;
  3459. if (queue.size === i) return;
  3460. queue.add(depth + 1);
  3461. } else {
  3462. moduleGraph.setDepth(module, depth);
  3463. for (const { module: refModule } of moduleGraph.getOutgoingConnections(
  3464. module
  3465. )) {
  3466. if (refModule) {
  3467. queue.add(refModule);
  3468. }
  3469. }
  3470. }
  3471. }
  3472. }
  3473. /**
  3474. * @param {Dependency} dependency the dependency
  3475. * @param {RuntimeSpec} runtime the runtime
  3476. * @returns {(string[] | ReferencedExport)[]} referenced exports
  3477. */
  3478. getDependencyReferencedExports(dependency, runtime) {
  3479. const referencedExports = dependency.getReferencedExports(
  3480. this.moduleGraph,
  3481. runtime
  3482. );
  3483. return this.hooks.dependencyReferencedExports.call(
  3484. referencedExports,
  3485. dependency,
  3486. runtime
  3487. );
  3488. }
  3489. /**
  3490. *
  3491. * @param {Module} module module relationship for removal
  3492. * @param {DependenciesBlockLike} block //TODO: good description
  3493. * @returns {void}
  3494. */
  3495. removeReasonsOfDependencyBlock(module, block) {
  3496. if (block.blocks) {
  3497. for (const b of block.blocks) {
  3498. this.removeReasonsOfDependencyBlock(module, b);
  3499. }
  3500. }
  3501. if (block.dependencies) {
  3502. for (const dep of block.dependencies) {
  3503. const originalModule = this.moduleGraph.getModule(dep);
  3504. if (originalModule) {
  3505. this.moduleGraph.removeConnection(dep);
  3506. if (this.chunkGraph) {
  3507. for (const chunk of this.chunkGraph.getModuleChunks(
  3508. originalModule
  3509. )) {
  3510. this.patchChunksAfterReasonRemoval(originalModule, chunk);
  3511. }
  3512. }
  3513. }
  3514. }
  3515. }
  3516. }
  3517. /**
  3518. * @param {Module} module module to patch tie
  3519. * @param {Chunk} chunk chunk to patch tie
  3520. * @returns {void}
  3521. */
  3522. patchChunksAfterReasonRemoval(module, chunk) {
  3523. if (!module.hasReasons(this.moduleGraph, chunk.runtime)) {
  3524. this.removeReasonsOfDependencyBlock(module, module);
  3525. }
  3526. if (!module.hasReasonForChunk(chunk, this.moduleGraph, this.chunkGraph)) {
  3527. if (this.chunkGraph.isModuleInChunk(module, chunk)) {
  3528. this.chunkGraph.disconnectChunkAndModule(chunk, module);
  3529. this.removeChunkFromDependencies(module, chunk);
  3530. }
  3531. }
  3532. }
  3533. /**
  3534. *
  3535. * @param {DependenciesBlock} block block tie for Chunk
  3536. * @param {Chunk} chunk chunk to remove from dep
  3537. * @returns {void}
  3538. */
  3539. removeChunkFromDependencies(block, chunk) {
  3540. /**
  3541. * @param {Dependency} d dependency to (maybe) patch up
  3542. */
  3543. const iteratorDependency = d => {
  3544. const depModule = this.moduleGraph.getModule(d);
  3545. if (!depModule) {
  3546. return;
  3547. }
  3548. this.patchChunksAfterReasonRemoval(depModule, chunk);
  3549. };
  3550. const blocks = block.blocks;
  3551. for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
  3552. const asyncBlock = blocks[indexBlock];
  3553. const chunkGroup = this.chunkGraph.getBlockChunkGroup(asyncBlock);
  3554. // Grab all chunks from the first Block's AsyncDepBlock
  3555. const chunks = chunkGroup.chunks;
  3556. // For each chunk in chunkGroup
  3557. for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  3558. const iteratedChunk = chunks[indexChunk];
  3559. chunkGroup.removeChunk(iteratedChunk);
  3560. // Recurse
  3561. this.removeChunkFromDependencies(block, iteratedChunk);
  3562. }
  3563. }
  3564. if (block.dependencies) {
  3565. for (const dep of block.dependencies) iteratorDependency(dep);
  3566. }
  3567. }
  3568. assignRuntimeIds() {
  3569. const { chunkGraph } = this;
  3570. const processEntrypoint = ep => {
  3571. const runtime = ep.options.runtime || ep.name;
  3572. const chunk = ep.getRuntimeChunk();
  3573. chunkGraph.setRuntimeId(runtime, chunk.id);
  3574. };
  3575. for (const ep of this.entrypoints.values()) {
  3576. processEntrypoint(ep);
  3577. }
  3578. for (const ep of this.asyncEntrypoints) {
  3579. processEntrypoint(ep);
  3580. }
  3581. }
  3582. sortItemsWithChunkIds() {
  3583. for (const chunkGroup of this.chunkGroups) {
  3584. chunkGroup.sortItems();
  3585. }
  3586. this.errors.sort(compareErrors);
  3587. this.warnings.sort(compareErrors);
  3588. this.children.sort(byNameOrHash);
  3589. }
  3590. summarizeDependencies() {
  3591. for (
  3592. let indexChildren = 0;
  3593. indexChildren < this.children.length;
  3594. indexChildren++
  3595. ) {
  3596. const child = this.children[indexChildren];
  3597. this.fileDependencies.addAll(child.fileDependencies);
  3598. this.contextDependencies.addAll(child.contextDependencies);
  3599. this.missingDependencies.addAll(child.missingDependencies);
  3600. this.buildDependencies.addAll(child.buildDependencies);
  3601. }
  3602. for (const module of this.modules) {
  3603. module.addCacheDependencies(
  3604. this.fileDependencies,
  3605. this.contextDependencies,
  3606. this.missingDependencies,
  3607. this.buildDependencies
  3608. );
  3609. }
  3610. }
  3611. createModuleHashes() {
  3612. let statModulesHashed = 0;
  3613. let statModulesFromCache = 0;
  3614. const { chunkGraph, runtimeTemplate, moduleMemCaches2 } = this;
  3615. const { hashFunction, hashDigest, hashDigestLength } = this.outputOptions;
  3616. const errors = [];
  3617. for (const module of this.modules) {
  3618. const memCache = moduleMemCaches2 && moduleMemCaches2.get(module);
  3619. for (const runtime of chunkGraph.getModuleRuntimes(module)) {
  3620. if (memCache) {
  3621. const digest = memCache.get(`moduleHash-${getRuntimeKey(runtime)}`);
  3622. if (digest !== undefined) {
  3623. chunkGraph.setModuleHashes(
  3624. module,
  3625. runtime,
  3626. digest,
  3627. digest.slice(0, hashDigestLength)
  3628. );
  3629. statModulesFromCache++;
  3630. continue;
  3631. }
  3632. }
  3633. statModulesHashed++;
  3634. const digest = this._createModuleHash(
  3635. module,
  3636. chunkGraph,
  3637. runtime,
  3638. hashFunction,
  3639. runtimeTemplate,
  3640. hashDigest,
  3641. hashDigestLength,
  3642. errors
  3643. );
  3644. if (memCache) {
  3645. memCache.set(`moduleHash-${getRuntimeKey(runtime)}`, digest);
  3646. }
  3647. }
  3648. }
  3649. if (errors.length > 0) {
  3650. errors.sort(compareSelect(err => err.module, compareModulesByIdentifier));
  3651. for (const error of errors) {
  3652. this.errors.push(error);
  3653. }
  3654. }
  3655. this.logger.log(
  3656. `${statModulesHashed} modules hashed, ${statModulesFromCache} from cache (${
  3657. Math.round(
  3658. (100 * (statModulesHashed + statModulesFromCache)) / this.modules.size
  3659. ) / 100
  3660. } variants per module in average)`
  3661. );
  3662. }
  3663. _createModuleHash(
  3664. module,
  3665. chunkGraph,
  3666. runtime,
  3667. hashFunction,
  3668. runtimeTemplate,
  3669. hashDigest,
  3670. hashDigestLength,
  3671. errors
  3672. ) {
  3673. let moduleHashDigest;
  3674. try {
  3675. const moduleHash = createHash(hashFunction);
  3676. module.updateHash(moduleHash, {
  3677. chunkGraph,
  3678. runtime,
  3679. runtimeTemplate
  3680. });
  3681. moduleHashDigest = /** @type {string} */ (moduleHash.digest(hashDigest));
  3682. } catch (err) {
  3683. errors.push(new ModuleHashingError(module, err));
  3684. moduleHashDigest = "XXXXXX";
  3685. }
  3686. chunkGraph.setModuleHashes(
  3687. module,
  3688. runtime,
  3689. moduleHashDigest,
  3690. moduleHashDigest.slice(0, hashDigestLength)
  3691. );
  3692. return moduleHashDigest;
  3693. }
  3694. createHash() {
  3695. this.logger.time("hashing: initialize hash");
  3696. const chunkGraph = this.chunkGraph;
  3697. const runtimeTemplate = this.runtimeTemplate;
  3698. const outputOptions = this.outputOptions;
  3699. const hashFunction = outputOptions.hashFunction;
  3700. const hashDigest = outputOptions.hashDigest;
  3701. const hashDigestLength = outputOptions.hashDigestLength;
  3702. const hash = createHash(hashFunction);
  3703. if (outputOptions.hashSalt) {
  3704. hash.update(outputOptions.hashSalt);
  3705. }
  3706. this.logger.timeEnd("hashing: initialize hash");
  3707. if (this.children.length > 0) {
  3708. this.logger.time("hashing: hash child compilations");
  3709. for (const child of this.children) {
  3710. hash.update(child.hash);
  3711. }
  3712. this.logger.timeEnd("hashing: hash child compilations");
  3713. }
  3714. if (this.warnings.length > 0) {
  3715. this.logger.time("hashing: hash warnings");
  3716. for (const warning of this.warnings) {
  3717. hash.update(`${warning.message}`);
  3718. }
  3719. this.logger.timeEnd("hashing: hash warnings");
  3720. }
  3721. if (this.errors.length > 0) {
  3722. this.logger.time("hashing: hash errors");
  3723. for (const error of this.errors) {
  3724. hash.update(`${error.message}`);
  3725. }
  3726. this.logger.timeEnd("hashing: hash errors");
  3727. }
  3728. this.logger.time("hashing: sort chunks");
  3729. /*
  3730. * all non-runtime chunks need to be hashes first,
  3731. * since runtime chunk might use their hashes.
  3732. * runtime chunks need to be hashed in the correct order
  3733. * since they may depend on each other (for async entrypoints).
  3734. * So we put all non-runtime chunks first and hash them in any order.
  3735. * And order runtime chunks according to referenced between each other.
  3736. * Chunks need to be in deterministic order since we add hashes to full chunk
  3737. * during these hashing.
  3738. */
  3739. /** @type {Chunk[]} */
  3740. const unorderedRuntimeChunks = [];
  3741. /** @type {Chunk[]} */
  3742. const otherChunks = [];
  3743. for (const c of this.chunks) {
  3744. if (c.hasRuntime()) {
  3745. unorderedRuntimeChunks.push(c);
  3746. } else {
  3747. otherChunks.push(c);
  3748. }
  3749. }
  3750. unorderedRuntimeChunks.sort(byId);
  3751. otherChunks.sort(byId);
  3752. /** @typedef {{ chunk: Chunk, referencedBy: RuntimeChunkInfo[], remaining: number }} RuntimeChunkInfo */
  3753. /** @type {Map<Chunk, RuntimeChunkInfo>} */
  3754. const runtimeChunksMap = new Map();
  3755. for (const chunk of unorderedRuntimeChunks) {
  3756. runtimeChunksMap.set(chunk, {
  3757. chunk,
  3758. referencedBy: [],
  3759. remaining: 0
  3760. });
  3761. }
  3762. let remaining = 0;
  3763. for (const info of runtimeChunksMap.values()) {
  3764. for (const other of new Set(
  3765. Array.from(info.chunk.getAllReferencedAsyncEntrypoints()).map(
  3766. e => e.chunks[e.chunks.length - 1]
  3767. )
  3768. )) {
  3769. const otherInfo = runtimeChunksMap.get(other);
  3770. otherInfo.referencedBy.push(info);
  3771. info.remaining++;
  3772. remaining++;
  3773. }
  3774. }
  3775. /** @type {Chunk[]} */
  3776. const runtimeChunks = [];
  3777. for (const info of runtimeChunksMap.values()) {
  3778. if (info.remaining === 0) {
  3779. runtimeChunks.push(info.chunk);
  3780. }
  3781. }
  3782. // If there are any references between chunks
  3783. // make sure to follow these chains
  3784. if (remaining > 0) {
  3785. const readyChunks = [];
  3786. for (const chunk of runtimeChunks) {
  3787. const hasFullHashModules =
  3788. chunkGraph.getNumberOfChunkFullHashModules(chunk) !== 0;
  3789. const info = runtimeChunksMap.get(chunk);
  3790. for (const otherInfo of info.referencedBy) {
  3791. if (hasFullHashModules) {
  3792. chunkGraph.upgradeDependentToFullHashModules(otherInfo.chunk);
  3793. }
  3794. remaining--;
  3795. if (--otherInfo.remaining === 0) {
  3796. readyChunks.push(otherInfo.chunk);
  3797. }
  3798. }
  3799. if (readyChunks.length > 0) {
  3800. // This ensures deterministic ordering, since referencedBy is non-deterministic
  3801. readyChunks.sort(byId);
  3802. for (const c of readyChunks) runtimeChunks.push(c);
  3803. readyChunks.length = 0;
  3804. }
  3805. }
  3806. }
  3807. // If there are still remaining references we have cycles and want to create a warning
  3808. if (remaining > 0) {
  3809. let circularRuntimeChunkInfo = [];
  3810. for (const info of runtimeChunksMap.values()) {
  3811. if (info.remaining !== 0) {
  3812. circularRuntimeChunkInfo.push(info);
  3813. }
  3814. }
  3815. circularRuntimeChunkInfo.sort(compareSelect(i => i.chunk, byId));
  3816. const err =
  3817. new WebpackError(`Circular dependency between chunks with runtime (${Array.from(
  3818. circularRuntimeChunkInfo,
  3819. c => c.chunk.name || c.chunk.id
  3820. ).join(", ")})
  3821. This prevents using hashes of each other and should be avoided.`);
  3822. err.chunk = circularRuntimeChunkInfo[0].chunk;
  3823. this.warnings.push(err);
  3824. for (const i of circularRuntimeChunkInfo) runtimeChunks.push(i.chunk);
  3825. }
  3826. this.logger.timeEnd("hashing: sort chunks");
  3827. const fullHashChunks = new Set();
  3828. /** @type {{module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}[]} */
  3829. const codeGenerationJobs = [];
  3830. /** @type {Map<string, Map<Module, {module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}>>} */
  3831. const codeGenerationJobsMap = new Map();
  3832. const errors = [];
  3833. const processChunk = chunk => {
  3834. // Last minute module hash generation for modules that depend on chunk hashes
  3835. this.logger.time("hashing: hash runtime modules");
  3836. const runtime = chunk.runtime;
  3837. for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
  3838. if (!chunkGraph.hasModuleHashes(module, runtime)) {
  3839. const hash = this._createModuleHash(
  3840. module,
  3841. chunkGraph,
  3842. runtime,
  3843. hashFunction,
  3844. runtimeTemplate,
  3845. hashDigest,
  3846. hashDigestLength,
  3847. errors
  3848. );
  3849. let hashMap = codeGenerationJobsMap.get(hash);
  3850. if (hashMap) {
  3851. const moduleJob = hashMap.get(module);
  3852. if (moduleJob) {
  3853. moduleJob.runtimes.push(runtime);
  3854. continue;
  3855. }
  3856. } else {
  3857. hashMap = new Map();
  3858. codeGenerationJobsMap.set(hash, hashMap);
  3859. }
  3860. const job = {
  3861. module,
  3862. hash,
  3863. runtime,
  3864. runtimes: [runtime]
  3865. };
  3866. hashMap.set(module, job);
  3867. codeGenerationJobs.push(job);
  3868. }
  3869. }
  3870. this.logger.timeAggregate("hashing: hash runtime modules");
  3871. try {
  3872. this.logger.time("hashing: hash chunks");
  3873. const chunkHash = createHash(hashFunction);
  3874. if (outputOptions.hashSalt) {
  3875. chunkHash.update(outputOptions.hashSalt);
  3876. }
  3877. chunk.updateHash(chunkHash, chunkGraph);
  3878. this.hooks.chunkHash.call(chunk, chunkHash, {
  3879. chunkGraph,
  3880. codeGenerationResults: this.codeGenerationResults,
  3881. moduleGraph: this.moduleGraph,
  3882. runtimeTemplate: this.runtimeTemplate
  3883. });
  3884. const chunkHashDigest = /** @type {string} */ (
  3885. chunkHash.digest(hashDigest)
  3886. );
  3887. hash.update(chunkHashDigest);
  3888. chunk.hash = chunkHashDigest;
  3889. chunk.renderedHash = chunk.hash.slice(0, hashDigestLength);
  3890. const fullHashModules =
  3891. chunkGraph.getChunkFullHashModulesIterable(chunk);
  3892. if (fullHashModules) {
  3893. fullHashChunks.add(chunk);
  3894. } else {
  3895. this.hooks.contentHash.call(chunk);
  3896. }
  3897. } catch (err) {
  3898. this.errors.push(new ChunkRenderError(chunk, "", err));
  3899. }
  3900. this.logger.timeAggregate("hashing: hash chunks");
  3901. };
  3902. otherChunks.forEach(processChunk);
  3903. for (const chunk of runtimeChunks) processChunk(chunk);
  3904. if (errors.length > 0) {
  3905. errors.sort(compareSelect(err => err.module, compareModulesByIdentifier));
  3906. for (const error of errors) {
  3907. this.errors.push(error);
  3908. }
  3909. }
  3910. this.logger.timeAggregateEnd("hashing: hash runtime modules");
  3911. this.logger.timeAggregateEnd("hashing: hash chunks");
  3912. this.logger.time("hashing: hash digest");
  3913. this.hooks.fullHash.call(hash);
  3914. this.fullHash = /** @type {string} */ (hash.digest(hashDigest));
  3915. this.hash = this.fullHash.slice(0, hashDigestLength);
  3916. this.logger.timeEnd("hashing: hash digest");
  3917. this.logger.time("hashing: process full hash modules");
  3918. for (const chunk of fullHashChunks) {
  3919. for (const module of chunkGraph.getChunkFullHashModulesIterable(chunk)) {
  3920. const moduleHash = createHash(hashFunction);
  3921. module.updateHash(moduleHash, {
  3922. chunkGraph,
  3923. runtime: chunk.runtime,
  3924. runtimeTemplate
  3925. });
  3926. const moduleHashDigest = /** @type {string} */ (
  3927. moduleHash.digest(hashDigest)
  3928. );
  3929. const oldHash = chunkGraph.getModuleHash(module, chunk.runtime);
  3930. chunkGraph.setModuleHashes(
  3931. module,
  3932. chunk.runtime,
  3933. moduleHashDigest,
  3934. moduleHashDigest.slice(0, hashDigestLength)
  3935. );
  3936. codeGenerationJobsMap.get(oldHash).get(module).hash = moduleHashDigest;
  3937. }
  3938. const chunkHash = createHash(hashFunction);
  3939. chunkHash.update(chunk.hash);
  3940. chunkHash.update(this.hash);
  3941. const chunkHashDigest = /** @type {string} */ (
  3942. chunkHash.digest(hashDigest)
  3943. );
  3944. chunk.hash = chunkHashDigest;
  3945. chunk.renderedHash = chunk.hash.slice(0, hashDigestLength);
  3946. this.hooks.contentHash.call(chunk);
  3947. }
  3948. this.logger.timeEnd("hashing: process full hash modules");
  3949. return codeGenerationJobs;
  3950. }
  3951. /**
  3952. * @param {string} file file name
  3953. * @param {Source} source asset source
  3954. * @param {AssetInfo} assetInfo extra asset information
  3955. * @returns {void}
  3956. */
  3957. emitAsset(file, source, assetInfo = {}) {
  3958. if (this.assets[file]) {
  3959. if (!isSourceEqual(this.assets[file], source)) {
  3960. this.errors.push(
  3961. new WebpackError(
  3962. `Conflict: Multiple assets emit different content to the same filename ${file}${
  3963. assetInfo.sourceFilename
  3964. ? `. Original source ${assetInfo.sourceFilename}`
  3965. : ""
  3966. }`
  3967. )
  3968. );
  3969. this.assets[file] = source;
  3970. this._setAssetInfo(file, assetInfo);
  3971. return;
  3972. }
  3973. const oldInfo = this.assetsInfo.get(file);
  3974. const newInfo = Object.assign({}, oldInfo, assetInfo);
  3975. this._setAssetInfo(file, newInfo, oldInfo);
  3976. return;
  3977. }
  3978. this.assets[file] = source;
  3979. this._setAssetInfo(file, assetInfo, undefined);
  3980. }
  3981. _setAssetInfo(file, newInfo, oldInfo = this.assetsInfo.get(file)) {
  3982. if (newInfo === undefined) {
  3983. this.assetsInfo.delete(file);
  3984. } else {
  3985. this.assetsInfo.set(file, newInfo);
  3986. }
  3987. const oldRelated = oldInfo && oldInfo.related;
  3988. const newRelated = newInfo && newInfo.related;
  3989. if (oldRelated) {
  3990. for (const key of Object.keys(oldRelated)) {
  3991. const remove = name => {
  3992. const relatedIn = this._assetsRelatedIn.get(name);
  3993. if (relatedIn === undefined) return;
  3994. const entry = relatedIn.get(key);
  3995. if (entry === undefined) return;
  3996. entry.delete(file);
  3997. if (entry.size !== 0) return;
  3998. relatedIn.delete(key);
  3999. if (relatedIn.size === 0) this._assetsRelatedIn.delete(name);
  4000. };
  4001. const entry = oldRelated[key];
  4002. if (Array.isArray(entry)) {
  4003. entry.forEach(remove);
  4004. } else if (entry) {
  4005. remove(entry);
  4006. }
  4007. }
  4008. }
  4009. if (newRelated) {
  4010. for (const key of Object.keys(newRelated)) {
  4011. const add = name => {
  4012. let relatedIn = this._assetsRelatedIn.get(name);
  4013. if (relatedIn === undefined) {
  4014. this._assetsRelatedIn.set(name, (relatedIn = new Map()));
  4015. }
  4016. let entry = relatedIn.get(key);
  4017. if (entry === undefined) {
  4018. relatedIn.set(key, (entry = new Set()));
  4019. }
  4020. entry.add(file);
  4021. };
  4022. const entry = newRelated[key];
  4023. if (Array.isArray(entry)) {
  4024. entry.forEach(add);
  4025. } else if (entry) {
  4026. add(entry);
  4027. }
  4028. }
  4029. }
  4030. }
  4031. /**
  4032. * @param {string} file file name
  4033. * @param {Source | function(Source): Source} newSourceOrFunction new asset source or function converting old to new
  4034. * @param {AssetInfo | function(AssetInfo | undefined): AssetInfo} assetInfoUpdateOrFunction new asset info or function converting old to new
  4035. */
  4036. updateAsset(
  4037. file,
  4038. newSourceOrFunction,
  4039. assetInfoUpdateOrFunction = undefined
  4040. ) {
  4041. if (!this.assets[file]) {
  4042. throw new Error(
  4043. `Called Compilation.updateAsset for not existing filename ${file}`
  4044. );
  4045. }
  4046. if (typeof newSourceOrFunction === "function") {
  4047. this.assets[file] = newSourceOrFunction(this.assets[file]);
  4048. } else {
  4049. this.assets[file] = newSourceOrFunction;
  4050. }
  4051. if (assetInfoUpdateOrFunction !== undefined) {
  4052. const oldInfo = this.assetsInfo.get(file) || EMPTY_ASSET_INFO;
  4053. if (typeof assetInfoUpdateOrFunction === "function") {
  4054. this._setAssetInfo(file, assetInfoUpdateOrFunction(oldInfo), oldInfo);
  4055. } else {
  4056. this._setAssetInfo(
  4057. file,
  4058. cachedCleverMerge(oldInfo, assetInfoUpdateOrFunction),
  4059. oldInfo
  4060. );
  4061. }
  4062. }
  4063. }
  4064. renameAsset(file, newFile) {
  4065. const source = this.assets[file];
  4066. if (!source) {
  4067. throw new Error(
  4068. `Called Compilation.renameAsset for not existing filename ${file}`
  4069. );
  4070. }
  4071. if (this.assets[newFile]) {
  4072. if (!isSourceEqual(this.assets[file], source)) {
  4073. this.errors.push(
  4074. new WebpackError(
  4075. `Conflict: Called Compilation.renameAsset for already existing filename ${newFile} with different content`
  4076. )
  4077. );
  4078. }
  4079. }
  4080. const assetInfo = this.assetsInfo.get(file);
  4081. // Update related in all other assets
  4082. const relatedInInfo = this._assetsRelatedIn.get(file);
  4083. if (relatedInInfo) {
  4084. for (const [key, assets] of relatedInInfo) {
  4085. for (const name of assets) {
  4086. const info = this.assetsInfo.get(name);
  4087. if (!info) continue;
  4088. const related = info.related;
  4089. if (!related) continue;
  4090. const entry = related[key];
  4091. let newEntry;
  4092. if (Array.isArray(entry)) {
  4093. newEntry = entry.map(x => (x === file ? newFile : x));
  4094. } else if (entry === file) {
  4095. newEntry = newFile;
  4096. } else continue;
  4097. this.assetsInfo.set(name, {
  4098. ...info,
  4099. related: {
  4100. ...related,
  4101. [key]: newEntry
  4102. }
  4103. });
  4104. }
  4105. }
  4106. }
  4107. this._setAssetInfo(file, undefined, assetInfo);
  4108. this._setAssetInfo(newFile, assetInfo);
  4109. delete this.assets[file];
  4110. this.assets[newFile] = source;
  4111. for (const chunk of this.chunks) {
  4112. {
  4113. const size = chunk.files.size;
  4114. chunk.files.delete(file);
  4115. if (size !== chunk.files.size) {
  4116. chunk.files.add(newFile);
  4117. }
  4118. }
  4119. {
  4120. const size = chunk.auxiliaryFiles.size;
  4121. chunk.auxiliaryFiles.delete(file);
  4122. if (size !== chunk.auxiliaryFiles.size) {
  4123. chunk.auxiliaryFiles.add(newFile);
  4124. }
  4125. }
  4126. }
  4127. }
  4128. /**
  4129. * @param {string} file file name
  4130. */
  4131. deleteAsset(file) {
  4132. if (!this.assets[file]) {
  4133. return;
  4134. }
  4135. delete this.assets[file];
  4136. const assetInfo = this.assetsInfo.get(file);
  4137. this._setAssetInfo(file, undefined, assetInfo);
  4138. const related = assetInfo && assetInfo.related;
  4139. if (related) {
  4140. for (const key of Object.keys(related)) {
  4141. const checkUsedAndDelete = file => {
  4142. if (!this._assetsRelatedIn.has(file)) {
  4143. this.deleteAsset(file);
  4144. }
  4145. };
  4146. const items = related[key];
  4147. if (Array.isArray(items)) {
  4148. items.forEach(checkUsedAndDelete);
  4149. } else if (items) {
  4150. checkUsedAndDelete(items);
  4151. }
  4152. }
  4153. }
  4154. // TODO If this becomes a performance problem
  4155. // store a reverse mapping from asset to chunk
  4156. for (const chunk of this.chunks) {
  4157. chunk.files.delete(file);
  4158. chunk.auxiliaryFiles.delete(file);
  4159. }
  4160. }
  4161. getAssets() {
  4162. /** @type {Readonly<Asset>[]} */
  4163. const array = [];
  4164. for (const assetName of Object.keys(this.assets)) {
  4165. if (Object.prototype.hasOwnProperty.call(this.assets, assetName)) {
  4166. array.push({
  4167. name: assetName,
  4168. source: this.assets[assetName],
  4169. info: this.assetsInfo.get(assetName) || EMPTY_ASSET_INFO
  4170. });
  4171. }
  4172. }
  4173. return array;
  4174. }
  4175. /**
  4176. * @param {string} name the name of the asset
  4177. * @returns {Readonly<Asset> | undefined} the asset or undefined when not found
  4178. */
  4179. getAsset(name) {
  4180. if (!Object.prototype.hasOwnProperty.call(this.assets, name))
  4181. return undefined;
  4182. return {
  4183. name,
  4184. source: this.assets[name],
  4185. info: this.assetsInfo.get(name) || EMPTY_ASSET_INFO
  4186. };
  4187. }
  4188. clearAssets() {
  4189. for (const chunk of this.chunks) {
  4190. chunk.files.clear();
  4191. chunk.auxiliaryFiles.clear();
  4192. }
  4193. }
  4194. createModuleAssets() {
  4195. const { chunkGraph } = this;
  4196. for (const module of this.modules) {
  4197. if (module.buildInfo.assets) {
  4198. const assetsInfo = module.buildInfo.assetsInfo;
  4199. for (const assetName of Object.keys(module.buildInfo.assets)) {
  4200. const fileName = this.getPath(assetName, {
  4201. chunkGraph: this.chunkGraph,
  4202. module
  4203. });
  4204. for (const chunk of chunkGraph.getModuleChunksIterable(module)) {
  4205. chunk.auxiliaryFiles.add(fileName);
  4206. }
  4207. this.emitAsset(
  4208. fileName,
  4209. module.buildInfo.assets[assetName],
  4210. assetsInfo ? assetsInfo.get(assetName) : undefined
  4211. );
  4212. this.hooks.moduleAsset.call(module, fileName);
  4213. }
  4214. }
  4215. }
  4216. }
  4217. /**
  4218. * @param {RenderManifestOptions} options options object
  4219. * @returns {RenderManifestEntry[]} manifest entries
  4220. */
  4221. getRenderManifest(options) {
  4222. return this.hooks.renderManifest.call([], options);
  4223. }
  4224. /**
  4225. * @param {Callback} callback signals when the call finishes
  4226. * @returns {void}
  4227. */
  4228. createChunkAssets(callback) {
  4229. const outputOptions = this.outputOptions;
  4230. const cachedSourceMap = new WeakMap();
  4231. /** @type {Map<string, {hash: string, source: Source, chunk: Chunk}>} */
  4232. const alreadyWrittenFiles = new Map();
  4233. asyncLib.forEachLimit(
  4234. this.chunks,
  4235. 15,
  4236. (chunk, callback) => {
  4237. /** @type {RenderManifestEntry[]} */
  4238. let manifest;
  4239. try {
  4240. manifest = this.getRenderManifest({
  4241. chunk,
  4242. hash: this.hash,
  4243. fullHash: this.fullHash,
  4244. outputOptions,
  4245. codeGenerationResults: this.codeGenerationResults,
  4246. moduleTemplates: this.moduleTemplates,
  4247. dependencyTemplates: this.dependencyTemplates,
  4248. chunkGraph: this.chunkGraph,
  4249. moduleGraph: this.moduleGraph,
  4250. runtimeTemplate: this.runtimeTemplate
  4251. });
  4252. } catch (err) {
  4253. this.errors.push(new ChunkRenderError(chunk, "", err));
  4254. return callback();
  4255. }
  4256. asyncLib.forEach(
  4257. manifest,
  4258. (fileManifest, callback) => {
  4259. const ident = fileManifest.identifier;
  4260. const usedHash = fileManifest.hash;
  4261. const assetCacheItem = this._assetsCache.getItemCache(
  4262. ident,
  4263. usedHash
  4264. );
  4265. assetCacheItem.get((err, sourceFromCache) => {
  4266. /** @type {string | function(PathData, AssetInfo=): string} */
  4267. let filenameTemplate;
  4268. /** @type {string} */
  4269. let file;
  4270. /** @type {AssetInfo} */
  4271. let assetInfo;
  4272. let inTry = true;
  4273. const errorAndCallback = err => {
  4274. const filename =
  4275. file ||
  4276. (typeof file === "string"
  4277. ? file
  4278. : typeof filenameTemplate === "string"
  4279. ? filenameTemplate
  4280. : "");
  4281. this.errors.push(new ChunkRenderError(chunk, filename, err));
  4282. inTry = false;
  4283. return callback();
  4284. };
  4285. try {
  4286. if ("filename" in fileManifest) {
  4287. file = fileManifest.filename;
  4288. assetInfo = fileManifest.info;
  4289. } else {
  4290. filenameTemplate = fileManifest.filenameTemplate;
  4291. const pathAndInfo = this.getPathWithInfo(
  4292. filenameTemplate,
  4293. fileManifest.pathOptions
  4294. );
  4295. file = pathAndInfo.path;
  4296. assetInfo = fileManifest.info
  4297. ? {
  4298. ...pathAndInfo.info,
  4299. ...fileManifest.info
  4300. }
  4301. : pathAndInfo.info;
  4302. }
  4303. if (err) {
  4304. return errorAndCallback(err);
  4305. }
  4306. let source = sourceFromCache;
  4307. // check if the same filename was already written by another chunk
  4308. const alreadyWritten = alreadyWrittenFiles.get(file);
  4309. if (alreadyWritten !== undefined) {
  4310. if (alreadyWritten.hash !== usedHash) {
  4311. inTry = false;
  4312. return callback(
  4313. new WebpackError(
  4314. `Conflict: Multiple chunks emit assets to the same filename ${file}` +
  4315. ` (chunks ${alreadyWritten.chunk.id} and ${chunk.id})`
  4316. )
  4317. );
  4318. } else {
  4319. source = alreadyWritten.source;
  4320. }
  4321. } else if (!source) {
  4322. // render the asset
  4323. source = fileManifest.render();
  4324. // Ensure that source is a cached source to avoid additional cost because of repeated access
  4325. if (!(source instanceof CachedSource)) {
  4326. const cacheEntry = cachedSourceMap.get(source);
  4327. if (cacheEntry) {
  4328. source = cacheEntry;
  4329. } else {
  4330. const cachedSource = new CachedSource(source);
  4331. cachedSourceMap.set(source, cachedSource);
  4332. source = cachedSource;
  4333. }
  4334. }
  4335. }
  4336. this.emitAsset(file, source, assetInfo);
  4337. if (fileManifest.auxiliary) {
  4338. chunk.auxiliaryFiles.add(file);
  4339. } else {
  4340. chunk.files.add(file);
  4341. }
  4342. this.hooks.chunkAsset.call(chunk, file);
  4343. alreadyWrittenFiles.set(file, {
  4344. hash: usedHash,
  4345. source,
  4346. chunk
  4347. });
  4348. if (source !== sourceFromCache) {
  4349. assetCacheItem.store(source, err => {
  4350. if (err) return errorAndCallback(err);
  4351. inTry = false;
  4352. return callback();
  4353. });
  4354. } else {
  4355. inTry = false;
  4356. callback();
  4357. }
  4358. } catch (err) {
  4359. if (!inTry) throw err;
  4360. errorAndCallback(err);
  4361. }
  4362. });
  4363. },
  4364. callback
  4365. );
  4366. },
  4367. callback
  4368. );
  4369. }
  4370. /**
  4371. * @param {string | function(PathData, AssetInfo=): string} filename used to get asset path with hash
  4372. * @param {PathData} data context data
  4373. * @returns {string} interpolated path
  4374. */
  4375. getPath(filename, data = {}) {
  4376. if (!data.hash) {
  4377. data = {
  4378. hash: this.hash,
  4379. ...data
  4380. };
  4381. }
  4382. return this.getAssetPath(filename, data);
  4383. }
  4384. /**
  4385. * @param {string | function(PathData, AssetInfo=): string} filename used to get asset path with hash
  4386. * @param {PathData} data context data
  4387. * @returns {{ path: string, info: AssetInfo }} interpolated path and asset info
  4388. */
  4389. getPathWithInfo(filename, data = {}) {
  4390. if (!data.hash) {
  4391. data = {
  4392. hash: this.hash,
  4393. ...data
  4394. };
  4395. }
  4396. return this.getAssetPathWithInfo(filename, data);
  4397. }
  4398. /**
  4399. * @param {string | function(PathData, AssetInfo=): string} filename used to get asset path with hash
  4400. * @param {PathData} data context data
  4401. * @returns {string} interpolated path
  4402. */
  4403. getAssetPath(filename, data) {
  4404. return this.hooks.assetPath.call(
  4405. typeof filename === "function" ? filename(data) : filename,
  4406. data,
  4407. undefined
  4408. );
  4409. }
  4410. /**
  4411. * @param {string | function(PathData, AssetInfo=): string} filename used to get asset path with hash
  4412. * @param {PathData} data context data
  4413. * @returns {{ path: string, info: AssetInfo }} interpolated path and asset info
  4414. */
  4415. getAssetPathWithInfo(filename, data) {
  4416. const assetInfo = {};
  4417. // TODO webpack 5: refactor assetPath hook to receive { path, info } object
  4418. const newPath = this.hooks.assetPath.call(
  4419. typeof filename === "function" ? filename(data, assetInfo) : filename,
  4420. data,
  4421. assetInfo
  4422. );
  4423. return { path: newPath, info: assetInfo };
  4424. }
  4425. getWarnings() {
  4426. return this.hooks.processWarnings.call(this.warnings);
  4427. }
  4428. getErrors() {
  4429. return this.hooks.processErrors.call(this.errors);
  4430. }
  4431. /**
  4432. * This function allows you to run another instance of webpack inside of webpack however as
  4433. * a child with different settings and configurations (if desired) applied. It copies all hooks, plugins
  4434. * from parent (or top level compiler) and creates a child Compilation
  4435. *
  4436. * @param {string} name name of the child compiler
  4437. * @param {OutputOptions=} outputOptions // Need to convert config schema to types for this
  4438. * @param {Array<WebpackPluginInstance | WebpackPluginFunction>=} plugins webpack plugins that will be applied
  4439. * @returns {Compiler} creates a child Compiler instance
  4440. */
  4441. createChildCompiler(name, outputOptions, plugins) {
  4442. const idx = this.childrenCounters[name] || 0;
  4443. this.childrenCounters[name] = idx + 1;
  4444. return this.compiler.createChildCompiler(
  4445. this,
  4446. name,
  4447. idx,
  4448. outputOptions,
  4449. plugins
  4450. );
  4451. }
  4452. /**
  4453. * @param {Module} module the module
  4454. * @param {ExecuteModuleOptions} options options
  4455. * @param {ExecuteModuleCallback} callback callback
  4456. */
  4457. executeModule(module, options, callback) {
  4458. // Aggregate all referenced modules and ensure they are ready
  4459. const modules = new Set([module]);
  4460. processAsyncTree(
  4461. modules,
  4462. 10,
  4463. /**
  4464. * @param {Module} module the module
  4465. * @param {function(Module): void} push push more jobs
  4466. * @param {Callback} callback callback
  4467. * @returns {void}
  4468. */
  4469. (module, push, callback) => {
  4470. this.buildQueue.waitFor(module, err => {
  4471. if (err) return callback(err);
  4472. this.processDependenciesQueue.waitFor(module, err => {
  4473. if (err) return callback(err);
  4474. for (const { module: m } of this.moduleGraph.getOutgoingConnections(
  4475. module
  4476. )) {
  4477. const size = modules.size;
  4478. modules.add(m);
  4479. if (modules.size !== size) push(m);
  4480. }
  4481. callback();
  4482. });
  4483. });
  4484. },
  4485. err => {
  4486. if (err) return callback(err);
  4487. // Create new chunk graph, chunk and entrypoint for the build time execution
  4488. const chunkGraph = new ChunkGraph(
  4489. this.moduleGraph,
  4490. this.outputOptions.hashFunction
  4491. );
  4492. const runtime = "build time";
  4493. const { hashFunction, hashDigest, hashDigestLength } =
  4494. this.outputOptions;
  4495. const runtimeTemplate = this.runtimeTemplate;
  4496. const chunk = new Chunk("build time chunk", this._backCompat);
  4497. chunk.id = chunk.name;
  4498. chunk.ids = [chunk.id];
  4499. chunk.runtime = runtime;
  4500. const entrypoint = new Entrypoint({
  4501. runtime,
  4502. chunkLoading: false,
  4503. ...options.entryOptions
  4504. });
  4505. chunkGraph.connectChunkAndEntryModule(chunk, module, entrypoint);
  4506. connectChunkGroupAndChunk(entrypoint, chunk);
  4507. entrypoint.setRuntimeChunk(chunk);
  4508. entrypoint.setEntrypointChunk(chunk);
  4509. const chunks = new Set([chunk]);
  4510. // Assign ids to modules and modules to the chunk
  4511. for (const module of modules) {
  4512. const id = module.identifier();
  4513. chunkGraph.setModuleId(module, id);
  4514. chunkGraph.connectChunkAndModule(chunk, module);
  4515. }
  4516. /** @type {WebpackError[]} */
  4517. const errors = [];
  4518. // Hash modules
  4519. for (const module of modules) {
  4520. this._createModuleHash(
  4521. module,
  4522. chunkGraph,
  4523. runtime,
  4524. hashFunction,
  4525. runtimeTemplate,
  4526. hashDigest,
  4527. hashDigestLength,
  4528. errors
  4529. );
  4530. }
  4531. const codeGenerationResults = new CodeGenerationResults(
  4532. this.outputOptions.hashFunction
  4533. );
  4534. /**
  4535. * @param {Module} module the module
  4536. * @param {Callback} callback callback
  4537. * @returns {void}
  4538. */
  4539. const codeGen = (module, callback) => {
  4540. this._codeGenerationModule(
  4541. module,
  4542. runtime,
  4543. [runtime],
  4544. chunkGraph.getModuleHash(module, runtime),
  4545. this.dependencyTemplates,
  4546. chunkGraph,
  4547. this.moduleGraph,
  4548. runtimeTemplate,
  4549. errors,
  4550. codeGenerationResults,
  4551. (err, codeGenerated) => {
  4552. callback(err);
  4553. }
  4554. );
  4555. };
  4556. const reportErrors = () => {
  4557. if (errors.length > 0) {
  4558. errors.sort(
  4559. compareSelect(err => err.module, compareModulesByIdentifier)
  4560. );
  4561. for (const error of errors) {
  4562. this.errors.push(error);
  4563. }
  4564. errors.length = 0;
  4565. }
  4566. };
  4567. // Generate code for all aggregated modules
  4568. asyncLib.eachLimit(modules, 10, codeGen, err => {
  4569. if (err) return callback(err);
  4570. reportErrors();
  4571. // for backward-compat temporary set the chunk graph
  4572. // TODO webpack 6
  4573. const old = this.chunkGraph;
  4574. this.chunkGraph = chunkGraph;
  4575. this.processRuntimeRequirements({
  4576. chunkGraph,
  4577. modules,
  4578. chunks,
  4579. codeGenerationResults,
  4580. chunkGraphEntries: chunks
  4581. });
  4582. this.chunkGraph = old;
  4583. const runtimeModules =
  4584. chunkGraph.getChunkRuntimeModulesIterable(chunk);
  4585. // Hash runtime modules
  4586. for (const module of runtimeModules) {
  4587. modules.add(module);
  4588. this._createModuleHash(
  4589. module,
  4590. chunkGraph,
  4591. runtime,
  4592. hashFunction,
  4593. runtimeTemplate,
  4594. hashDigest,
  4595. hashDigestLength
  4596. );
  4597. }
  4598. // Generate code for all runtime modules
  4599. asyncLib.eachLimit(runtimeModules, 10, codeGen, err => {
  4600. if (err) return callback(err);
  4601. reportErrors();
  4602. /** @type {Map<Module, ExecuteModuleArgument>} */
  4603. const moduleArgumentsMap = new Map();
  4604. /** @type {Map<string, ExecuteModuleArgument>} */
  4605. const moduleArgumentsById = new Map();
  4606. /** @type {ExecuteModuleResult["fileDependencies"]} */
  4607. const fileDependencies = new LazySet();
  4608. /** @type {ExecuteModuleResult["contextDependencies"]} */
  4609. const contextDependencies = new LazySet();
  4610. /** @type {ExecuteModuleResult["missingDependencies"]} */
  4611. const missingDependencies = new LazySet();
  4612. /** @type {ExecuteModuleResult["buildDependencies"]} */
  4613. const buildDependencies = new LazySet();
  4614. /** @type {ExecuteModuleResult["assets"]} */
  4615. const assets = new Map();
  4616. let cacheable = true;
  4617. /** @type {ExecuteModuleContext} */
  4618. const context = {
  4619. assets,
  4620. __webpack_require__: undefined,
  4621. chunk,
  4622. chunkGraph
  4623. };
  4624. // Prepare execution
  4625. asyncLib.eachLimit(
  4626. modules,
  4627. 10,
  4628. (module, callback) => {
  4629. const codeGenerationResult = codeGenerationResults.get(
  4630. module,
  4631. runtime
  4632. );
  4633. /** @type {ExecuteModuleArgument} */
  4634. const moduleArgument = {
  4635. module,
  4636. codeGenerationResult,
  4637. preparedInfo: undefined,
  4638. moduleObject: undefined
  4639. };
  4640. moduleArgumentsMap.set(module, moduleArgument);
  4641. moduleArgumentsById.set(module.identifier(), moduleArgument);
  4642. module.addCacheDependencies(
  4643. fileDependencies,
  4644. contextDependencies,
  4645. missingDependencies,
  4646. buildDependencies
  4647. );
  4648. if (module.buildInfo.cacheable === false) {
  4649. cacheable = false;
  4650. }
  4651. if (module.buildInfo && module.buildInfo.assets) {
  4652. const { assets: moduleAssets, assetsInfo } = module.buildInfo;
  4653. for (const assetName of Object.keys(moduleAssets)) {
  4654. assets.set(assetName, {
  4655. source: moduleAssets[assetName],
  4656. info: assetsInfo ? assetsInfo.get(assetName) : undefined
  4657. });
  4658. }
  4659. }
  4660. this.hooks.prepareModuleExecution.callAsync(
  4661. moduleArgument,
  4662. context,
  4663. callback
  4664. );
  4665. },
  4666. err => {
  4667. if (err) return callback(err);
  4668. let exports;
  4669. try {
  4670. const {
  4671. strictModuleErrorHandling,
  4672. strictModuleExceptionHandling
  4673. } = this.outputOptions;
  4674. const __webpack_require__ = id => {
  4675. const cached = moduleCache[id];
  4676. if (cached !== undefined) {
  4677. if (cached.error) throw cached.error;
  4678. return cached.exports;
  4679. }
  4680. const moduleArgument = moduleArgumentsById.get(id);
  4681. return __webpack_require_module__(moduleArgument, id);
  4682. };
  4683. const interceptModuleExecution = (__webpack_require__[
  4684. RuntimeGlobals.interceptModuleExecution.replace(
  4685. "__webpack_require__.",
  4686. ""
  4687. )
  4688. ] = []);
  4689. const moduleCache = (__webpack_require__[
  4690. RuntimeGlobals.moduleCache.replace(
  4691. "__webpack_require__.",
  4692. ""
  4693. )
  4694. ] = {});
  4695. context.__webpack_require__ = __webpack_require__;
  4696. /**
  4697. * @param {ExecuteModuleArgument} moduleArgument the module argument
  4698. * @param {string=} id id
  4699. * @returns {any} exports
  4700. */
  4701. const __webpack_require_module__ = (moduleArgument, id) => {
  4702. var execOptions = {
  4703. id,
  4704. module: {
  4705. id,
  4706. exports: {},
  4707. loaded: false,
  4708. error: undefined
  4709. },
  4710. require: __webpack_require__
  4711. };
  4712. interceptModuleExecution.forEach(handler =>
  4713. handler(execOptions)
  4714. );
  4715. const module = moduleArgument.module;
  4716. this.buildTimeExecutedModules.add(module);
  4717. const moduleObject = execOptions.module;
  4718. moduleArgument.moduleObject = moduleObject;
  4719. try {
  4720. if (id) moduleCache[id] = moduleObject;
  4721. tryRunOrWebpackError(
  4722. () =>
  4723. this.hooks.executeModule.call(
  4724. moduleArgument,
  4725. context
  4726. ),
  4727. "Compilation.hooks.executeModule"
  4728. );
  4729. moduleObject.loaded = true;
  4730. return moduleObject.exports;
  4731. } catch (e) {
  4732. if (strictModuleExceptionHandling) {
  4733. if (id) delete moduleCache[id];
  4734. } else if (strictModuleErrorHandling) {
  4735. moduleObject.error = e;
  4736. }
  4737. if (!e.module) e.module = module;
  4738. throw e;
  4739. }
  4740. };
  4741. for (const runtimeModule of chunkGraph.getChunkRuntimeModulesInOrder(
  4742. chunk
  4743. )) {
  4744. __webpack_require_module__(
  4745. moduleArgumentsMap.get(runtimeModule)
  4746. );
  4747. }
  4748. exports = __webpack_require__(module.identifier());
  4749. } catch (e) {
  4750. const err = new WebpackError(
  4751. `Execution of module code from module graph (${module.readableIdentifier(
  4752. this.requestShortener
  4753. )}) failed: ${e.message}`
  4754. );
  4755. err.stack = e.stack;
  4756. err.module = e.module;
  4757. return callback(err);
  4758. }
  4759. callback(null, {
  4760. exports,
  4761. assets,
  4762. cacheable,
  4763. fileDependencies,
  4764. contextDependencies,
  4765. missingDependencies,
  4766. buildDependencies
  4767. });
  4768. }
  4769. );
  4770. });
  4771. });
  4772. }
  4773. );
  4774. }
  4775. checkConstraints() {
  4776. const chunkGraph = this.chunkGraph;
  4777. /** @type {Set<number|string>} */
  4778. const usedIds = new Set();
  4779. for (const module of this.modules) {
  4780. if (module.type === "runtime") continue;
  4781. const moduleId = chunkGraph.getModuleId(module);
  4782. if (moduleId === null) continue;
  4783. if (usedIds.has(moduleId)) {
  4784. throw new Error(`checkConstraints: duplicate module id ${moduleId}`);
  4785. }
  4786. usedIds.add(moduleId);
  4787. }
  4788. for (const chunk of this.chunks) {
  4789. for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
  4790. if (!this.modules.has(module)) {
  4791. throw new Error(
  4792. "checkConstraints: module in chunk but not in compilation " +
  4793. ` ${chunk.debugId} ${module.debugId}`
  4794. );
  4795. }
  4796. }
  4797. for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) {
  4798. if (!this.modules.has(module)) {
  4799. throw new Error(
  4800. "checkConstraints: entry module in chunk but not in compilation " +
  4801. ` ${chunk.debugId} ${module.debugId}`
  4802. );
  4803. }
  4804. }
  4805. }
  4806. for (const chunkGroup of this.chunkGroups) {
  4807. chunkGroup.checkConstraints();
  4808. }
  4809. }
  4810. }
  4811. /**
  4812. * @typedef {Object} FactorizeModuleOptions
  4813. * @property {ModuleProfile} currentProfile
  4814. * @property {ModuleFactory} factory
  4815. * @property {Dependency[]} dependencies
  4816. * @property {boolean=} factoryResult return full ModuleFactoryResult instead of only module
  4817. * @property {Module | null} originModule
  4818. * @property {Partial<ModuleFactoryCreateDataContextInfo>=} contextInfo
  4819. * @property {string=} context
  4820. */
  4821. /**
  4822. * @param {FactorizeModuleOptions} options options object
  4823. * @param {ModuleCallback | ModuleFactoryResultCallback} callback callback
  4824. * @returns {void}
  4825. */
  4826. // Workaround for typescript as it doesn't support function overloading in jsdoc within a class
  4827. Compilation.prototype.factorizeModule = /** @type {{
  4828. (options: FactorizeModuleOptions & { factoryResult?: false }, callback: ModuleCallback): void;
  4829. (options: FactorizeModuleOptions & { factoryResult: true }, callback: ModuleFactoryResultCallback): void;
  4830. }} */ (
  4831. function (options, callback) {
  4832. this.factorizeQueue.add(options, callback);
  4833. }
  4834. );
  4835. // Hide from typescript
  4836. const compilationPrototype = Compilation.prototype;
  4837. // TODO webpack 6 remove
  4838. Object.defineProperty(compilationPrototype, "modifyHash", {
  4839. writable: false,
  4840. enumerable: false,
  4841. configurable: false,
  4842. value: () => {
  4843. throw new Error(
  4844. "Compilation.modifyHash was removed in favor of Compilation.hooks.fullHash"
  4845. );
  4846. }
  4847. });
  4848. // TODO webpack 6 remove
  4849. Object.defineProperty(compilationPrototype, "cache", {
  4850. enumerable: false,
  4851. configurable: false,
  4852. get: util.deprecate(
  4853. /**
  4854. * @this {Compilation} the compilation
  4855. * @returns {Cache} the cache
  4856. */
  4857. function () {
  4858. return this.compiler.cache;
  4859. },
  4860. "Compilation.cache was removed in favor of Compilation.getCache()",
  4861. "DEP_WEBPACK_COMPILATION_CACHE"
  4862. ),
  4863. set: util.deprecate(
  4864. v => {},
  4865. "Compilation.cache was removed in favor of Compilation.getCache()",
  4866. "DEP_WEBPACK_COMPILATION_CACHE"
  4867. )
  4868. });
  4869. /**
  4870. * Add additional assets to the compilation.
  4871. */
  4872. Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL = -2000;
  4873. /**
  4874. * Basic preprocessing of assets.
  4875. */
  4876. Compilation.PROCESS_ASSETS_STAGE_PRE_PROCESS = -1000;
  4877. /**
  4878. * Derive new assets from existing assets.
  4879. * Existing assets should not be treated as complete.
  4880. */
  4881. Compilation.PROCESS_ASSETS_STAGE_DERIVED = -200;
  4882. /**
  4883. * Add additional sections to existing assets, like a banner or initialization code.
  4884. */
  4885. Compilation.PROCESS_ASSETS_STAGE_ADDITIONS = -100;
  4886. /**
  4887. * Optimize existing assets in a general way.
  4888. */
  4889. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE = 100;
  4890. /**
  4891. * Optimize the count of existing assets, e. g. by merging them.
  4892. * Only assets of the same type should be merged.
  4893. * For assets of different types see PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE.
  4894. */
  4895. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT = 200;
  4896. /**
  4897. * Optimize the compatibility of existing assets, e. g. add polyfills or vendor-prefixes.
  4898. */
  4899. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY = 300;
  4900. /**
  4901. * Optimize the size of existing assets, e. g. by minimizing or omitting whitespace.
  4902. */
  4903. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE = 400;
  4904. /**
  4905. * Add development tooling to assets, e. g. by extracting a SourceMap.
  4906. */
  4907. Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING = 500;
  4908. /**
  4909. * Optimize the count of existing assets, e. g. by inlining assets of into other assets.
  4910. * Only assets of different types should be inlined.
  4911. * For assets of the same type see PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT.
  4912. */
  4913. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE = 700;
  4914. /**
  4915. * Summarize the list of existing assets
  4916. * e. g. creating an assets manifest of Service Workers.
  4917. */
  4918. Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE = 1000;
  4919. /**
  4920. * Optimize the hashes of the assets, e. g. by generating real hashes of the asset content.
  4921. */
  4922. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_HASH = 2500;
  4923. /**
  4924. * Optimize the transfer of existing assets, e. g. by preparing a compressed (gzip) file as separate asset.
  4925. */
  4926. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER = 3000;
  4927. /**
  4928. * Analyse existing assets.
  4929. */
  4930. Compilation.PROCESS_ASSETS_STAGE_ANALYSE = 4000;
  4931. /**
  4932. * Creating assets for reporting purposes.
  4933. */
  4934. Compilation.PROCESS_ASSETS_STAGE_REPORT = 5000;
  4935. module.exports = Compilation;