Compilation.js 164 KB

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