Compilation.js 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450
  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("async");
  7. const crypto = require("crypto");
  8. const Tapable = require("tapable");
  9. const EntryModuleNotFoundError = require("./EntryModuleNotFoundError");
  10. const ModuleNotFoundError = require("./ModuleNotFoundError");
  11. const ModuleDependencyWarning = require("./ModuleDependencyWarning");
  12. const ModuleDependencyError = require("./ModuleDependencyError");
  13. const Module = require("./Module");
  14. const Chunk = require("./Chunk");
  15. const Entrypoint = require("./Entrypoint");
  16. const MainTemplate = require("./MainTemplate");
  17. const ChunkTemplate = require("./ChunkTemplate");
  18. const HotUpdateChunkTemplate = require("./HotUpdateChunkTemplate");
  19. const ModuleTemplate = require("./ModuleTemplate");
  20. const Dependency = require("./Dependency");
  21. const ChunkRenderError = require("./ChunkRenderError");
  22. const AsyncDependencyToInitialChunkWarning = require("./AsyncDependencyToInitialChunkWarning");
  23. const CachedSource = require("webpack-sources").CachedSource;
  24. const Stats = require("./Stats");
  25. const Semaphore = require("./util/Semaphore");
  26. const Queue = require("./util/Queue");
  27. function byId(a, b) {
  28. if(a.id < b.id) return -1;
  29. if(a.id > b.id) return 1;
  30. return 0;
  31. }
  32. function byIndex(a, b) {
  33. if(a.index < b.index) return -1;
  34. if(a.index > b.index) return 1;
  35. return 0;
  36. }
  37. function iterationBlockVariable(variables, fn) {
  38. for(let indexVariable = 0; indexVariable < variables.length; indexVariable++) {
  39. const varDep = variables[indexVariable].dependencies;
  40. for(let indexVDep = 0; indexVDep < varDep.length; indexVDep++) {
  41. fn(varDep[indexVDep]);
  42. }
  43. }
  44. }
  45. function iterationOfArrayCallback(arr, fn) {
  46. for(let index = 0; index < arr.length; index++) {
  47. fn(arr[index]);
  48. }
  49. }
  50. class Compilation extends Tapable {
  51. constructor(compiler) {
  52. super();
  53. this.compiler = compiler;
  54. this.resolvers = compiler.resolvers;
  55. this.inputFileSystem = compiler.inputFileSystem;
  56. const options = this.options = compiler.options;
  57. this.outputOptions = options && options.output;
  58. this.bail = options && options.bail;
  59. this.profile = options && options.profile;
  60. this.performance = options && options.performance;
  61. this.mainTemplate = new MainTemplate(this.outputOptions);
  62. this.chunkTemplate = new ChunkTemplate(this.outputOptions);
  63. this.hotUpdateChunkTemplate = new HotUpdateChunkTemplate(this.outputOptions);
  64. this.moduleTemplate = new ModuleTemplate(this.outputOptions);
  65. this.semaphore = new Semaphore(options.parallelism || 100);
  66. this.entries = [];
  67. this.preparedChunks = [];
  68. this.entrypoints = {};
  69. this.chunks = [];
  70. this.namedChunks = {};
  71. this.modules = [];
  72. this._modules = {};
  73. this.cache = null;
  74. this.records = null;
  75. this.nextFreeModuleIndex = undefined;
  76. this.nextFreeModuleIndex2 = undefined;
  77. this.additionalChunkAssets = [];
  78. this.assets = {};
  79. this.errors = [];
  80. this.warnings = [];
  81. this.children = [];
  82. this.dependencyFactories = new Map();
  83. this.dependencyTemplates = new Map();
  84. this.dependencyTemplates.set("hash", "");
  85. this.childrenCounters = {};
  86. }
  87. getStats() {
  88. return new Stats(this);
  89. }
  90. templatesPlugin(name, fn) {
  91. this.mainTemplate.plugin(name, fn);
  92. this.chunkTemplate.plugin(name, fn);
  93. }
  94. addModule(module, cacheGroup) {
  95. const identifier = module.identifier();
  96. if(this._modules[identifier]) {
  97. return false;
  98. }
  99. const cacheName = (cacheGroup || "m") + identifier;
  100. if(this.cache && this.cache[cacheName]) {
  101. const cacheModule = this.cache[cacheName];
  102. let rebuild = true;
  103. if(!cacheModule.error && cacheModule.cacheable && this.fileTimestamps && this.contextTimestamps) {
  104. rebuild = cacheModule.needRebuild(this.fileTimestamps, this.contextTimestamps);
  105. }
  106. if(!rebuild) {
  107. cacheModule.disconnect();
  108. this._modules[identifier] = cacheModule;
  109. this.modules.push(cacheModule);
  110. cacheModule.errors.forEach(err => this.errors.push(err));
  111. cacheModule.warnings.forEach(err => this.warnings.push(err));
  112. return cacheModule;
  113. }
  114. }
  115. module.unbuild();
  116. this._modules[identifier] = module;
  117. if(this.cache) {
  118. this.cache[cacheName] = module;
  119. }
  120. this.modules.push(module);
  121. return true;
  122. }
  123. getModule(module) {
  124. const identifier = module.identifier();
  125. return this._modules[identifier];
  126. }
  127. findModule(identifier) {
  128. return this._modules[identifier];
  129. }
  130. buildModule(module, optional, origin, dependencies, thisCallback) {
  131. this.applyPlugins1("build-module", module);
  132. if(module.building) return module.building.push(thisCallback);
  133. const building = module.building = [thisCallback];
  134. function callback(err) {
  135. module.building = undefined;
  136. building.forEach(cb => cb(err));
  137. }
  138. module.build(this.options, this, this.resolvers.normal, this.inputFileSystem, (error) => {
  139. const errors = module.errors;
  140. for(let indexError = 0; indexError < errors.length; indexError++) {
  141. const err = errors[indexError];
  142. err.origin = origin;
  143. err.dependencies = dependencies;
  144. if(optional)
  145. this.warnings.push(err);
  146. else
  147. this.errors.push(err);
  148. }
  149. const warnings = module.warnings;
  150. for(let indexWarning = 0; indexWarning < warnings.length; indexWarning++) {
  151. const war = warnings[indexWarning];
  152. war.origin = origin;
  153. war.dependencies = dependencies;
  154. this.warnings.push(war);
  155. }
  156. module.dependencies.sort(Dependency.compare);
  157. if(error) {
  158. this.applyPlugins2("failed-module", module, error);
  159. return callback(error);
  160. }
  161. this.applyPlugins1("succeed-module", module);
  162. return callback();
  163. });
  164. }
  165. processModuleDependencies(module, callback) {
  166. const dependencies = [];
  167. function addDependency(dep) {
  168. for(let i = 0; i < dependencies.length; i++) {
  169. if(dep.isEqualResource(dependencies[i][0])) {
  170. return dependencies[i].push(dep);
  171. }
  172. }
  173. dependencies.push([dep]);
  174. }
  175. function addDependenciesBlock(block) {
  176. if(block.dependencies) {
  177. iterationOfArrayCallback(block.dependencies, addDependency);
  178. }
  179. if(block.blocks) {
  180. iterationOfArrayCallback(block.blocks, addDependenciesBlock);
  181. }
  182. if(block.variables) {
  183. iterationBlockVariable(block.variables, addDependency);
  184. }
  185. }
  186. addDependenciesBlock(module);
  187. this.addModuleDependencies(module, dependencies, this.bail, null, true, callback);
  188. }
  189. addModuleDependencies(module, dependencies, bail, cacheGroup, recursive, callback) {
  190. let _this = this;
  191. const start = _this.profile && Date.now();
  192. const factories = [];
  193. for(let i = 0; i < dependencies.length; i++) {
  194. const factory = _this.dependencyFactories.get(dependencies[i][0].constructor);
  195. if(!factory) {
  196. return callback(new Error(`No module factory available for dependency type: ${dependencies[i][0].constructor.name}`));
  197. }
  198. factories[i] = [factory, dependencies[i]];
  199. }
  200. asyncLib.forEach(factories, function iteratorFactory(item, callback) {
  201. const dependencies = item[1];
  202. const errorAndCallback = function errorAndCallback(err) {
  203. err.origin = module;
  204. _this.errors.push(err);
  205. if(bail) {
  206. callback(err);
  207. } else {
  208. callback();
  209. }
  210. };
  211. const warningAndCallback = function warningAndCallback(err) {
  212. err.origin = module;
  213. _this.warnings.push(err);
  214. callback();
  215. };
  216. const semaphore = _this.semaphore;
  217. semaphore.acquire(() => {
  218. if(_this === null) return semaphore.release();
  219. const factory = item[0];
  220. factory.create({
  221. contextInfo: {
  222. issuer: module.nameForCondition && module.nameForCondition(),
  223. compiler: _this.compiler.name
  224. },
  225. context: module.context,
  226. dependencies: dependencies
  227. }, function factoryCallback(err, dependentModule) {
  228. if(_this === null) return semaphore.release();
  229. let afterFactory;
  230. function isOptional() {
  231. return dependencies.filter(d => !d.optional).length === 0;
  232. }
  233. function errorOrWarningAndCallback(err) {
  234. if(isOptional()) {
  235. return warningAndCallback(err);
  236. } else {
  237. return errorAndCallback(err);
  238. }
  239. }
  240. function iterationDependencies(depend) {
  241. for(let index = 0; index < depend.length; index++) {
  242. const dep = depend[index];
  243. dep.module = dependentModule;
  244. dependentModule.addReason(module, dep);
  245. }
  246. }
  247. if(err) {
  248. semaphore.release();
  249. return errorOrWarningAndCallback(new ModuleNotFoundError(module, err, dependencies));
  250. }
  251. if(!dependentModule) {
  252. semaphore.release();
  253. return process.nextTick(callback);
  254. }
  255. if(_this.profile) {
  256. if(!dependentModule.profile) {
  257. dependentModule.profile = {};
  258. }
  259. afterFactory = Date.now();
  260. dependentModule.profile.factory = afterFactory - start;
  261. }
  262. dependentModule.issuer = module;
  263. const newModule = _this.addModule(dependentModule, cacheGroup);
  264. if(!newModule) { // from cache
  265. dependentModule = _this.getModule(dependentModule);
  266. if(dependentModule.optional) {
  267. dependentModule.optional = isOptional();
  268. }
  269. iterationDependencies(dependencies);
  270. if(_this.profile) {
  271. module.profile = module.profile || {};
  272. const time = Date.now() - start;
  273. if(!module.profile.dependencies || time > module.profile.dependencies) {
  274. module.profile.dependencies = time;
  275. }
  276. }
  277. semaphore.release();
  278. return process.nextTick(callback);
  279. }
  280. if(newModule instanceof Module) {
  281. if(_this.profile) {
  282. newModule.profile = dependentModule.profile;
  283. }
  284. newModule.optional = isOptional();
  285. newModule.issuer = dependentModule.issuer;
  286. dependentModule = newModule;
  287. iterationDependencies(dependencies);
  288. if(_this.profile) {
  289. const afterBuilding = Date.now();
  290. module.profile.building = afterBuilding - afterFactory;
  291. }
  292. semaphore.release();
  293. if(recursive) {
  294. return process.nextTick(_this.processModuleDependencies.bind(_this, dependentModule, callback));
  295. } else {
  296. return process.nextTick(callback);
  297. }
  298. }
  299. dependentModule.optional = isOptional();
  300. iterationDependencies(dependencies);
  301. _this.buildModule(dependentModule, isOptional(), module, dependencies, err => {
  302. if(_this === null) return semaphore.release();
  303. if(err) {
  304. semaphore.release();
  305. return errorOrWarningAndCallback(err);
  306. }
  307. if(_this.profile) {
  308. const afterBuilding = Date.now();
  309. dependentModule.profile.building = afterBuilding - afterFactory;
  310. }
  311. semaphore.release();
  312. if(recursive) {
  313. _this.processModuleDependencies(dependentModule, callback);
  314. } else {
  315. return callback();
  316. }
  317. });
  318. });
  319. });
  320. }, function finalCallbackAddModuleDependencies(err) {
  321. // In V8, the Error objects keep a reference to the functions on the stack. These warnings &
  322. // errors are created inside closures that keep a reference to the Compilation, so errors are
  323. // leaking the Compilation object. Setting _this to null workarounds the following issue in V8.
  324. // https://bugs.chromium.org/p/chromium/issues/detail?id=612191
  325. _this = null;
  326. if(err) {
  327. return callback(err);
  328. }
  329. return process.nextTick(callback);
  330. });
  331. }
  332. _addModuleChain(context, dependency, onModule, callback) {
  333. const start = this.profile && Date.now();
  334. const errorAndCallback = this.bail ? (err) => {
  335. callback(err);
  336. } : (err) => {
  337. err.dependencies = [dependency];
  338. this.errors.push(err);
  339. callback();
  340. };
  341. if(typeof dependency !== "object" || dependency === null || !dependency.constructor) {
  342. throw new Error("Parameter 'dependency' must be a Dependency");
  343. }
  344. const moduleFactory = this.dependencyFactories.get(dependency.constructor);
  345. if(!moduleFactory) {
  346. throw new Error(`No dependency factory available for this dependency type: ${dependency.constructor.name}`);
  347. }
  348. this.semaphore.acquire(() => {
  349. moduleFactory.create({
  350. contextInfo: {
  351. issuer: "",
  352. compiler: this.compiler.name
  353. },
  354. context: context,
  355. dependencies: [dependency]
  356. }, (err, module) => {
  357. if(err) {
  358. this.semaphore.release();
  359. return errorAndCallback(new EntryModuleNotFoundError(err));
  360. }
  361. let afterFactory;
  362. if(this.profile) {
  363. if(!module.profile) {
  364. module.profile = {};
  365. }
  366. afterFactory = Date.now();
  367. module.profile.factory = afterFactory - start;
  368. }
  369. const result = this.addModule(module);
  370. if(!result) {
  371. module = this.getModule(module);
  372. onModule(module);
  373. if(this.profile) {
  374. const afterBuilding = Date.now();
  375. module.profile.building = afterBuilding - afterFactory;
  376. }
  377. this.semaphore.release();
  378. return callback(null, module);
  379. }
  380. if(result instanceof Module) {
  381. if(this.profile) {
  382. result.profile = module.profile;
  383. }
  384. module = result;
  385. onModule(module);
  386. moduleReady.call(this);
  387. return;
  388. }
  389. onModule(module);
  390. this.buildModule(module, false, null, null, (err) => {
  391. if(err) {
  392. this.semaphore.release();
  393. return errorAndCallback(err);
  394. }
  395. if(this.profile) {
  396. const afterBuilding = Date.now();
  397. module.profile.building = afterBuilding - afterFactory;
  398. }
  399. moduleReady.call(this);
  400. });
  401. function moduleReady() {
  402. this.semaphore.release();
  403. this.processModuleDependencies(module, err => {
  404. if(err) {
  405. return callback(err);
  406. }
  407. return callback(null, module);
  408. });
  409. }
  410. });
  411. });
  412. }
  413. addEntry(context, entry, name, callback) {
  414. const slot = {
  415. name: name,
  416. module: null
  417. };
  418. this.preparedChunks.push(slot);
  419. this._addModuleChain(context, entry, (module) => {
  420. entry.module = module;
  421. this.entries.push(module);
  422. module.issuer = null;
  423. }, (err, module) => {
  424. if(err) {
  425. return callback(err);
  426. }
  427. if(module) {
  428. slot.module = module;
  429. } else {
  430. const idx = this.preparedChunks.indexOf(slot);
  431. this.preparedChunks.splice(idx, 1);
  432. }
  433. return callback(null, module);
  434. });
  435. }
  436. prefetch(context, dependency, callback) {
  437. this._addModuleChain(context, dependency, module => {
  438. module.prefetched = true;
  439. module.issuer = null;
  440. }, callback);
  441. }
  442. rebuildModule(module, thisCallback) {
  443. if(module.variables.length || module.blocks.length)
  444. throw new Error("Cannot rebuild a complex module with variables or blocks");
  445. if(module.rebuilding) {
  446. return module.rebuilding.push(thisCallback);
  447. }
  448. const rebuilding = module.rebuilding = [thisCallback];
  449. function callback(err) {
  450. module.rebuilding = undefined;
  451. rebuilding.forEach(cb => cb(err));
  452. }
  453. const deps = module.dependencies.slice();
  454. this.buildModule(module, false, module, null, (err) => {
  455. if(err) return callback(err);
  456. this.processModuleDependencies(module, (err) => {
  457. if(err) return callback(err);
  458. deps.forEach(d => {
  459. if(d.module && d.module.removeReason(module, d)) {
  460. module.forEachChunk(chunk => {
  461. if(!d.module.hasReasonForChunk(chunk)) {
  462. if(d.module.removeChunk(chunk)) {
  463. this.removeChunkFromDependencies(d.module, chunk);
  464. }
  465. }
  466. });
  467. }
  468. });
  469. callback();
  470. });
  471. });
  472. }
  473. finish() {
  474. const modules = this.modules;
  475. this.applyPlugins1("finish-modules", modules);
  476. for(let index = 0; index < modules.length; index++) {
  477. const module = modules[index];
  478. this.reportDependencyErrorsAndWarnings(module, [module]);
  479. }
  480. }
  481. unseal() {
  482. this.applyPlugins0("unseal");
  483. this.chunks.length = 0;
  484. this.namedChunks = {};
  485. this.additionalChunkAssets.length = 0;
  486. this.assets = {};
  487. this.modules.forEach(module => module.unseal());
  488. }
  489. seal(callback) {
  490. this.applyPlugins0("seal");
  491. this.nextFreeModuleIndex = 0;
  492. this.nextFreeModuleIndex2 = 0;
  493. this.preparedChunks.forEach(preparedChunk => {
  494. const module = preparedChunk.module;
  495. const chunk = this.addChunk(preparedChunk.name, module);
  496. const entrypoint = this.entrypoints[chunk.name] = new Entrypoint(chunk.name);
  497. entrypoint.unshiftChunk(chunk);
  498. chunk.addModule(module);
  499. module.addChunk(chunk);
  500. chunk.entryModule = module;
  501. this.assignIndex(module);
  502. this.assignDepth(module);
  503. });
  504. this.processDependenciesBlocksForChunks(this.chunks.slice());
  505. this.sortModules(this.modules);
  506. this.applyPlugins0("optimize");
  507. while(this.applyPluginsBailResult1("optimize-modules-basic", this.modules) ||
  508. this.applyPluginsBailResult1("optimize-modules", this.modules) ||
  509. this.applyPluginsBailResult1("optimize-modules-advanced", this.modules)) { /* empty */ }
  510. this.applyPlugins1("after-optimize-modules", this.modules);
  511. while(this.applyPluginsBailResult1("optimize-chunks-basic", this.chunks) ||
  512. this.applyPluginsBailResult1("optimize-chunks", this.chunks) ||
  513. this.applyPluginsBailResult1("optimize-chunks-advanced", this.chunks)) { /* empty */ }
  514. this.applyPlugins1("after-optimize-chunks", this.chunks);
  515. this.applyPluginsAsyncSeries("optimize-tree", this.chunks, this.modules, (err) => {
  516. if(err) {
  517. return callback(err);
  518. }
  519. this.applyPlugins2("after-optimize-tree", this.chunks, this.modules);
  520. while(this.applyPluginsBailResult("optimize-chunk-modules-basic", this.chunks, this.modules) ||
  521. this.applyPluginsBailResult("optimize-chunk-modules", this.chunks, this.modules) ||
  522. this.applyPluginsBailResult("optimize-chunk-modules-advanced", this.chunks, this.modules)) { /* empty */ }
  523. this.applyPlugins2("after-optimize-chunk-modules", this.chunks, this.modules);
  524. const shouldRecord = this.applyPluginsBailResult("should-record") !== false;
  525. this.applyPlugins2("revive-modules", this.modules, this.records);
  526. this.applyPlugins1("optimize-module-order", this.modules);
  527. this.applyPlugins1("advanced-optimize-module-order", this.modules);
  528. this.applyPlugins1("before-module-ids", this.modules);
  529. this.applyPlugins1("module-ids", this.modules);
  530. this.applyModuleIds();
  531. this.applyPlugins1("optimize-module-ids", this.modules);
  532. this.applyPlugins1("after-optimize-module-ids", this.modules);
  533. this.sortItemsWithModuleIds();
  534. this.applyPlugins2("revive-chunks", this.chunks, this.records);
  535. this.applyPlugins1("optimize-chunk-order", this.chunks);
  536. this.applyPlugins1("before-chunk-ids", this.chunks);
  537. this.applyChunkIds();
  538. this.applyPlugins1("optimize-chunk-ids", this.chunks);
  539. this.applyPlugins1("after-optimize-chunk-ids", this.chunks);
  540. this.sortItemsWithChunkIds();
  541. if(shouldRecord)
  542. this.applyPlugins2("record-modules", this.modules, this.records);
  543. if(shouldRecord)
  544. this.applyPlugins2("record-chunks", this.chunks, this.records);
  545. this.applyPlugins0("before-hash");
  546. this.createHash();
  547. this.applyPlugins0("after-hash");
  548. if(shouldRecord)
  549. this.applyPlugins1("record-hash", this.records);
  550. this.applyPlugins0("before-module-assets");
  551. this.createModuleAssets();
  552. if(this.applyPluginsBailResult("should-generate-chunk-assets") !== false) {
  553. this.applyPlugins0("before-chunk-assets");
  554. this.createChunkAssets();
  555. }
  556. this.applyPlugins1("additional-chunk-assets", this.chunks);
  557. this.summarizeDependencies();
  558. if(shouldRecord)
  559. this.applyPlugins2("record", this, this.records);
  560. this.applyPluginsAsync("additional-assets", err => {
  561. if(err) {
  562. return callback(err);
  563. }
  564. this.applyPluginsAsync("optimize-chunk-assets", this.chunks, err => {
  565. if(err) {
  566. return callback(err);
  567. }
  568. this.applyPlugins1("after-optimize-chunk-assets", this.chunks);
  569. this.applyPluginsAsync("optimize-assets", this.assets, err => {
  570. if(err) {
  571. return callback(err);
  572. }
  573. this.applyPlugins1("after-optimize-assets", this.assets);
  574. if(this.applyPluginsBailResult("need-additional-seal")) {
  575. this.unseal();
  576. return this.seal(callback);
  577. }
  578. return this.applyPluginsAsync("after-seal", callback);
  579. });
  580. });
  581. });
  582. });
  583. }
  584. sortModules(modules) {
  585. modules.sort(byIndex);
  586. }
  587. reportDependencyErrorsAndWarnings(module, blocks) {
  588. for(let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
  589. const block = blocks[indexBlock];
  590. const dependencies = block.dependencies;
  591. for(let indexDep = 0; indexDep < dependencies.length; indexDep++) {
  592. const d = dependencies[indexDep];
  593. const warnings = d.getWarnings();
  594. if(warnings) {
  595. for(let indexWar = 0; indexWar < warnings.length; indexWar++) {
  596. const w = warnings[indexWar];
  597. const warning = new ModuleDependencyWarning(module, w, d.loc);
  598. this.warnings.push(warning);
  599. }
  600. }
  601. const errors = d.getErrors();
  602. if(errors) {
  603. for(let indexErr = 0; indexErr < errors.length; indexErr++) {
  604. const e = errors[indexErr];
  605. const error = new ModuleDependencyError(module, e, d.loc);
  606. this.errors.push(error);
  607. }
  608. }
  609. }
  610. this.reportDependencyErrorsAndWarnings(module, block.blocks);
  611. }
  612. }
  613. addChunk(name, module, loc) {
  614. if(name) {
  615. if(Object.prototype.hasOwnProperty.call(this.namedChunks, name)) {
  616. const chunk = this.namedChunks[name];
  617. if(module) {
  618. chunk.addOrigin(module, loc);
  619. }
  620. return chunk;
  621. }
  622. }
  623. const chunk = new Chunk(name, module, loc);
  624. this.chunks.push(chunk);
  625. if(name) {
  626. this.namedChunks[name] = chunk;
  627. }
  628. return chunk;
  629. }
  630. assignIndex(module) {
  631. const _this = this;
  632. const queue = [() => {
  633. assignIndexToModule(module);
  634. }];
  635. const iteratorAllDependencies = d => {
  636. queue.push(() => assignIndexToDependency(d));
  637. };
  638. function assignIndexToModule(module) {
  639. // enter module
  640. if(typeof module.index !== "number") {
  641. module.index = _this.nextFreeModuleIndex++;
  642. // leave module
  643. queue.push(() => module.index2 = _this.nextFreeModuleIndex2++);
  644. // enter it as block
  645. assignIndexToDependencyBlock(module);
  646. }
  647. }
  648. function assignIndexToDependency(dependency) {
  649. if(dependency.module) {
  650. queue.push(() => assignIndexToModule(dependency.module));
  651. }
  652. }
  653. function assignIndexToDependencyBlock(block) {
  654. let allDependencies = [];
  655. function iteratorDependency(d) {
  656. allDependencies.push(d);
  657. }
  658. function iteratorBlock(b) {
  659. queue.push(() => assignIndexToDependencyBlock(b));
  660. }
  661. if(block.variables) {
  662. iterationBlockVariable(block.variables, iteratorDependency);
  663. }
  664. if(block.dependencies) {
  665. iterationOfArrayCallback(block.dependencies, iteratorDependency);
  666. }
  667. if(block.blocks) {
  668. const blocks = block.blocks;
  669. let indexBlock = blocks.length;
  670. while(indexBlock--) {
  671. iteratorBlock(blocks[indexBlock]);
  672. }
  673. }
  674. let indexAll = allDependencies.length;
  675. while(indexAll--) {
  676. iteratorAllDependencies(allDependencies[indexAll]);
  677. }
  678. }
  679. while(queue.length) {
  680. queue.pop()();
  681. }
  682. }
  683. assignDepth(module) {
  684. function assignDepthToModule(module, depth) {
  685. // enter module
  686. if(typeof module.depth === "number" && module.depth <= depth) return;
  687. module.depth = depth;
  688. // enter it as block
  689. assignDepthToDependencyBlock(module, depth + 1);
  690. }
  691. function assignDepthToDependency(dependency, depth) {
  692. if(dependency.module) {
  693. queue.push(() => assignDepthToModule(dependency.module, depth));
  694. }
  695. }
  696. function assignDepthToDependencyBlock(block, depth) {
  697. function iteratorDependency(d) {
  698. assignDepthToDependency(d, depth);
  699. }
  700. function iteratorBlock(b) {
  701. assignDepthToDependencyBlock(b, depth);
  702. }
  703. if(block.variables) {
  704. iterationBlockVariable(block.variables, iteratorDependency);
  705. }
  706. if(block.dependencies) {
  707. iterationOfArrayCallback(block.dependencies, iteratorDependency);
  708. }
  709. if(block.blocks) {
  710. iterationOfArrayCallback(block.blocks, iteratorBlock);
  711. }
  712. }
  713. const queue = [() => {
  714. assignDepthToModule(module, 0);
  715. }];
  716. while(queue.length) {
  717. queue.pop()();
  718. }
  719. }
  720. // This method creates the Chunk graph from the Module graph
  721. processDependenciesBlocksForChunks(inputChunks) {
  722. // Process is splitting into two parts:
  723. // Part one traverse the module graph and builds a very basic chunks graph
  724. // in chunkDependencies.
  725. // Part two traverse every possible way through the basic chunk graph and
  726. // tracks the available modules. While traversing it connects chunks with
  727. // eachother and Blocks with Chunks. It stops traversing when all modules
  728. // for a chunk are already available. So it doesn't connect unneeded chunks.
  729. const chunkDependencies = new Map(); // Map<Chunk, Array<{Module, Chunk}>>
  730. const allCreatedChunks = new Set();
  731. // PART ONE
  732. const blockChunks = new Map();
  733. // Start with the provided modules/chunks
  734. const queue = inputChunks.map(chunk => ({
  735. block: chunk.entryModule,
  736. chunk: chunk
  737. }));
  738. let block, chunk;
  739. // For each async Block in graph
  740. const iteratorBlock = b => {
  741. // 1. We create a chunk for this Block
  742. // but only once (blockChunks map)
  743. let c = blockChunks.get(b);
  744. if(c === undefined) {
  745. c = this.namedChunks[b.chunkName];
  746. if(c && c.isInitial()) {
  747. // TODO webpack 4: convert this to an error
  748. this.warnings.push(new AsyncDependencyToInitialChunkWarning(b.chunkName, b.module, b.loc));
  749. c = chunk;
  750. } else {
  751. c = this.addChunk(b.chunkName, b.module, b.loc);
  752. blockChunks.set(b, c);
  753. allCreatedChunks.add(c);
  754. // We initialize the chunks property
  755. // this is later filled with the chunk when needed
  756. b.chunks = [];
  757. }
  758. }
  759. // 2. We store the Block+Chunk mapping as dependency for the chunk
  760. let deps = chunkDependencies.get(chunk);
  761. if(!deps) chunkDependencies.set(chunk, deps = []);
  762. deps.push({
  763. block: b,
  764. chunk: c
  765. });
  766. // 3. We enqueue the DependenciesBlock for traversal
  767. queue.push({
  768. block: b,
  769. chunk: c
  770. });
  771. };
  772. // For each Dependency in the graph
  773. const iteratorDependency = d => {
  774. // We skip Dependencies without Module pointer
  775. if(!d.module) {
  776. return;
  777. }
  778. // We skip weak Dependencies
  779. if(d.weak) {
  780. return;
  781. }
  782. // We connect Module and Chunk when not already done
  783. if(chunk.addModule(d.module)) {
  784. d.module.addChunk(chunk);
  785. // And enqueue the Module for traversal
  786. queue.push({
  787. block: d.module,
  788. chunk
  789. });
  790. }
  791. };
  792. // Iterative traversal of the Module graph
  793. // Recursive would be simpler to write but could result in Stack Overflows
  794. while(queue.length) {
  795. const queueItem = queue.pop();
  796. block = queueItem.block;
  797. chunk = queueItem.chunk;
  798. // Traverse all variables, Dependencies and Blocks
  799. if(block.variables) {
  800. iterationBlockVariable(block.variables, iteratorDependency);
  801. }
  802. if(block.dependencies) {
  803. iterationOfArrayCallback(block.dependencies, iteratorDependency);
  804. }
  805. if(block.blocks) {
  806. iterationOfArrayCallback(block.blocks, iteratorBlock);
  807. }
  808. }
  809. // PART TWO
  810. let availableModules;
  811. let newAvailableModules;
  812. const queue2 = new Queue(inputChunks.map(chunk => ({
  813. chunk,
  814. availableModules: new Set()
  815. })));
  816. // Helper function to check if all modules of a chunk are available
  817. const areModulesAvailable = (chunk, availableModules) => {
  818. for(const module of chunk.modulesIterable) {
  819. if(!availableModules.has(module))
  820. return false;
  821. }
  822. return true;
  823. };
  824. // For each edge in the basic chunk graph
  825. const filterFn = dep => {
  826. // Filter egdes that are not needed because all modules are already available
  827. // This also filters circular dependencies in the chunks graph
  828. const depChunk = dep.chunk;
  829. if(areModulesAvailable(depChunk, newAvailableModules))
  830. return false; // break all modules are already available
  831. return true;
  832. };
  833. const minAvailableModulesMap = new Map();
  834. // Iterative traversing of the basic chunk graph
  835. while(queue2.length) {
  836. const queueItem = queue2.dequeue();
  837. chunk = queueItem.chunk;
  838. availableModules = queueItem.availableModules;
  839. // 1. Get minimal available modules
  840. // It doesn't make sense to traverse a chunk again with more available modules.
  841. // This step calculates the minimal available modules and skips traversal when
  842. // the list didn't shrink.
  843. let minAvailableModules = minAvailableModulesMap.get(chunk);
  844. if(minAvailableModules === undefined) {
  845. minAvailableModulesMap.set(chunk, new Set(availableModules));
  846. } else {
  847. let deletedModules = false;
  848. for(const m of minAvailableModules) {
  849. if(!availableModules.has(m)) {
  850. minAvailableModules.delete(m);
  851. deletedModules = true;
  852. }
  853. }
  854. if(!deletedModules)
  855. continue;
  856. availableModules = minAvailableModules;
  857. }
  858. // 2. Get the edges at this point of the graph
  859. const deps = chunkDependencies.get(chunk);
  860. if(!deps) continue;
  861. if(deps.length === 0) continue;
  862. // 3. Create a new Set of available modules at this points
  863. newAvailableModules = new Set(availableModules);
  864. for(const m of chunk.modulesIterable)
  865. newAvailableModules.add(m);
  866. // 4. Filter edges with available modules
  867. const filteredDeps = deps.filter(filterFn);
  868. // 5. Foreach remaining edge
  869. const nextChunks = new Set();
  870. for(let i = 0; i < filteredDeps.length; i++) {
  871. const dep = filteredDeps[i];
  872. const depChunk = dep.chunk;
  873. const depBlock = dep.block;
  874. // 6. Connnect block with chunk
  875. if(depChunk.addBlock(depBlock)) {
  876. depBlock.chunks.push(depChunk);
  877. }
  878. // 7. Connect chunk with parent
  879. if(chunk.addChunk(depChunk)) {
  880. depChunk.addParent(chunk);
  881. }
  882. nextChunks.add(depChunk);
  883. }
  884. // 8. Enqueue further traversal
  885. for(const nextChunk of nextChunks) {
  886. queue2.enqueue({
  887. chunk: nextChunk,
  888. availableModules: newAvailableModules
  889. });
  890. }
  891. }
  892. // Remove all unconnected chunks
  893. for(const chunk of allCreatedChunks) {
  894. if(chunk.parents.length === 0)
  895. chunk.remove("unconnected");
  896. }
  897. }
  898. removeChunkFromDependencies(block, chunk) {
  899. const iteratorDependency = d => {
  900. if(!d.module) {
  901. return;
  902. }
  903. if(!d.module.hasReasonForChunk(chunk)) {
  904. if(d.module.removeChunk(chunk)) {
  905. this.removeChunkFromDependencies(d.module, chunk);
  906. }
  907. }
  908. };
  909. const blocks = block.blocks;
  910. for(let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
  911. const chunks = blocks[indexBlock].chunks;
  912. for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  913. const blockChunk = chunks[indexChunk];
  914. chunk.removeChunk(blockChunk);
  915. blockChunk.removeParent(chunk);
  916. this.removeChunkFromDependencies(chunks, blockChunk);
  917. }
  918. }
  919. if(block.dependencies) {
  920. iterationOfArrayCallback(block.dependencies, iteratorDependency);
  921. }
  922. if(block.variables) {
  923. iterationBlockVariable(block.variables, iteratorDependency);
  924. }
  925. }
  926. applyModuleIds() {
  927. const unusedIds = [];
  928. let nextFreeModuleId = 0;
  929. const usedIds = [];
  930. // TODO consider Map when performance has improved https://gist.github.com/sokra/234c077e1299b7369461f1708519c392
  931. const usedIdMap = Object.create(null);
  932. if(this.usedModuleIds) {
  933. Object.keys(this.usedModuleIds).forEach(key => {
  934. const id = this.usedModuleIds[key];
  935. if(!usedIdMap[id]) {
  936. usedIds.push(id);
  937. usedIdMap[id] = true;
  938. }
  939. });
  940. }
  941. const modules1 = this.modules;
  942. for(let indexModule1 = 0; indexModule1 < modules1.length; indexModule1++) {
  943. const module1 = modules1[indexModule1];
  944. if(module1.id && !usedIdMap[module1.id]) {
  945. usedIds.push(module1.id);
  946. usedIdMap[module1.id] = true;
  947. }
  948. }
  949. if(usedIds.length > 0) {
  950. let usedIdMax = -1;
  951. for(let index = 0; index < usedIds.length; index++) {
  952. const usedIdKey = usedIds[index];
  953. if(typeof usedIdKey !== "number") {
  954. continue;
  955. }
  956. usedIdMax = Math.max(usedIdMax, usedIdKey);
  957. }
  958. let lengthFreeModules = nextFreeModuleId = usedIdMax + 1;
  959. while(lengthFreeModules--) {
  960. if(!usedIdMap[lengthFreeModules]) {
  961. unusedIds.push(lengthFreeModules);
  962. }
  963. }
  964. }
  965. const modules2 = this.modules;
  966. for(let indexModule2 = 0; indexModule2 < modules2.length; indexModule2++) {
  967. const module2 = modules2[indexModule2];
  968. if(module2.id === null) {
  969. if(unusedIds.length > 0)
  970. module2.id = unusedIds.pop();
  971. else
  972. module2.id = nextFreeModuleId++;
  973. }
  974. }
  975. }
  976. applyChunkIds() {
  977. const unusedIds = [];
  978. let nextFreeChunkId = 0;
  979. function getNextFreeChunkId(usedChunkIds) {
  980. const keyChunks = Object.keys(usedChunkIds);
  981. let result = -1;
  982. for(let index = 0; index < keyChunks.length; index++) {
  983. const usedIdKey = keyChunks[index];
  984. const usedIdValue = usedChunkIds[usedIdKey];
  985. if(typeof usedIdValue !== "number") {
  986. continue;
  987. }
  988. result = Math.max(result, usedIdValue);
  989. }
  990. return result;
  991. }
  992. if(this.usedChunkIds) {
  993. nextFreeChunkId = getNextFreeChunkId(this.usedChunkIds) + 1;
  994. let index = nextFreeChunkId;
  995. while(index--) {
  996. if(this.usedChunkIds[index] !== index) {
  997. unusedIds.push(index);
  998. }
  999. }
  1000. }
  1001. const chunks = this.chunks;
  1002. for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  1003. const chunk = chunks[indexChunk];
  1004. if(chunk.id === null) {
  1005. if(unusedIds.length > 0)
  1006. chunk.id = unusedIds.pop();
  1007. else
  1008. chunk.id = nextFreeChunkId++;
  1009. }
  1010. if(!chunk.ids) {
  1011. chunk.ids = [chunk.id];
  1012. }
  1013. }
  1014. }
  1015. sortItemsWithModuleIds() {
  1016. this.modules.sort(byId);
  1017. const modules = this.modules;
  1018. for(let indexModule = 0; indexModule < modules.length; indexModule++) {
  1019. modules[indexModule].sortItems(false);
  1020. }
  1021. const chunks = this.chunks;
  1022. for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  1023. chunks[indexChunk].sortItems();
  1024. }
  1025. }
  1026. sortItemsWithChunkIds() {
  1027. this.chunks.sort(byId);
  1028. for(let indexModule = 0; indexModule < this.modules.length; indexModule++) {
  1029. this.modules[indexModule].sortItems(true);
  1030. }
  1031. for(let indexChunk = 0; indexChunk < this.chunks.length; indexChunk++) {
  1032. this.chunks[indexChunk].sortItems();
  1033. }
  1034. const byMessage = (a, b) => {
  1035. const ma = `${a.message}`;
  1036. const mb = `${b.message}`;
  1037. if(ma < mb) return -1;
  1038. if(mb < ma) return 1;
  1039. return 0;
  1040. };
  1041. this.errors.sort(byMessage);
  1042. this.warnings.sort(byMessage);
  1043. }
  1044. summarizeDependencies() {
  1045. function filterDups(array) {
  1046. const newArray = [];
  1047. for(let i = 0; i < array.length; i++) {
  1048. if(i === 0 || array[i - 1] !== array[i])
  1049. newArray.push(array[i]);
  1050. }
  1051. return newArray;
  1052. }
  1053. this.fileDependencies = (this.compilationDependencies || []).slice();
  1054. this.contextDependencies = [];
  1055. this.missingDependencies = [];
  1056. for(let indexChildren = 0; indexChildren < this.children.length; indexChildren++) {
  1057. const child = this.children[indexChildren];
  1058. this.fileDependencies = this.fileDependencies.concat(child.fileDependencies);
  1059. this.contextDependencies = this.contextDependencies.concat(child.contextDependencies);
  1060. this.missingDependencies = this.missingDependencies.concat(child.missingDependencies);
  1061. }
  1062. for(let indexModule = 0; indexModule < this.modules.length; indexModule++) {
  1063. const module = this.modules[indexModule];
  1064. if(module.fileDependencies) {
  1065. const fileDependencies = module.fileDependencies;
  1066. for(let indexFileDep = 0; indexFileDep < fileDependencies.length; indexFileDep++) {
  1067. this.fileDependencies.push(fileDependencies[indexFileDep]);
  1068. }
  1069. }
  1070. if(module.contextDependencies) {
  1071. const contextDependencies = module.contextDependencies;
  1072. for(let indexContextDep = 0; indexContextDep < contextDependencies.length; indexContextDep++) {
  1073. this.contextDependencies.push(contextDependencies[indexContextDep]);
  1074. }
  1075. }
  1076. }
  1077. this.errors.forEach(error => {
  1078. if(Array.isArray(error.missing)) {
  1079. error.missing.forEach(item => this.missingDependencies.push(item));
  1080. }
  1081. });
  1082. this.fileDependencies.sort();
  1083. this.fileDependencies = filterDups(this.fileDependencies);
  1084. this.contextDependencies.sort();
  1085. this.contextDependencies = filterDups(this.contextDependencies);
  1086. this.missingDependencies.sort();
  1087. this.missingDependencies = filterDups(this.missingDependencies);
  1088. }
  1089. createHash() {
  1090. const outputOptions = this.outputOptions;
  1091. const hashFunction = outputOptions.hashFunction;
  1092. const hashDigest = outputOptions.hashDigest;
  1093. const hashDigestLength = outputOptions.hashDigestLength;
  1094. const hash = crypto.createHash(hashFunction);
  1095. if(outputOptions.hashSalt)
  1096. hash.update(outputOptions.hashSalt);
  1097. this.mainTemplate.updateHash(hash);
  1098. this.chunkTemplate.updateHash(hash);
  1099. this.moduleTemplate.updateHash(hash);
  1100. this.children.forEach(function(child) {
  1101. hash.update(child.hash);
  1102. });
  1103. this.warnings.forEach(function(warning) {
  1104. hash.update(`${warning.message}`);
  1105. });
  1106. this.errors.forEach(function(error) {
  1107. hash.update(`${error.message}`);
  1108. });
  1109. // clone needed as sort below is inplace mutation
  1110. const chunks = this.chunks.slice();
  1111. /**
  1112. * sort here will bring all "falsy" values to the beginning
  1113. * this is needed as the "hasRuntime()" chunks are dependent on the
  1114. * hashes of the non-runtime chunks.
  1115. */
  1116. chunks.sort((a, b) => {
  1117. const aEntry = a.hasRuntime();
  1118. const bEntry = b.hasRuntime();
  1119. if(aEntry && !bEntry) return 1;
  1120. if(!aEntry && bEntry) return -1;
  1121. return 0;
  1122. });
  1123. for(let i = 0; i < chunks.length; i++) {
  1124. const chunk = chunks[i];
  1125. const chunkHash = crypto.createHash(hashFunction);
  1126. if(outputOptions.hashSalt)
  1127. chunkHash.update(outputOptions.hashSalt);
  1128. chunk.updateHash(chunkHash);
  1129. if(chunk.hasRuntime()) {
  1130. this.mainTemplate.updateHashForChunk(chunkHash, chunk);
  1131. } else {
  1132. this.chunkTemplate.updateHashForChunk(chunkHash, chunk);
  1133. }
  1134. this.applyPlugins2("chunk-hash", chunk, chunkHash);
  1135. chunk.hash = chunkHash.digest(hashDigest);
  1136. hash.update(chunk.hash);
  1137. chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
  1138. }
  1139. this.fullHash = hash.digest(hashDigest);
  1140. this.hash = this.fullHash.substr(0, hashDigestLength);
  1141. }
  1142. modifyHash(update) {
  1143. const outputOptions = this.outputOptions;
  1144. const hashFunction = outputOptions.hashFunction;
  1145. const hashDigest = outputOptions.hashDigest;
  1146. const hashDigestLength = outputOptions.hashDigestLength;
  1147. const hash = crypto.createHash(hashFunction);
  1148. hash.update(this.fullHash);
  1149. hash.update(update);
  1150. this.fullHash = hash.digest(hashDigest);
  1151. this.hash = this.fullHash.substr(0, hashDigestLength);
  1152. }
  1153. createModuleAssets() {
  1154. for(let i = 0; i < this.modules.length; i++) {
  1155. const module = this.modules[i];
  1156. if(module.assets) {
  1157. Object.keys(module.assets).forEach((assetName) => {
  1158. const fileName = this.getPath(assetName);
  1159. this.assets[fileName] = module.assets[assetName];
  1160. this.applyPlugins2("module-asset", module, fileName);
  1161. });
  1162. }
  1163. }
  1164. }
  1165. createChunkAssets() {
  1166. const outputOptions = this.outputOptions;
  1167. const filename = outputOptions.filename;
  1168. const chunkFilename = outputOptions.chunkFilename;
  1169. for(let i = 0; i < this.chunks.length; i++) {
  1170. const chunk = this.chunks[i];
  1171. chunk.files = [];
  1172. const chunkHash = chunk.hash;
  1173. let source;
  1174. let file;
  1175. const filenameTemplate = chunk.filenameTemplate ? chunk.filenameTemplate :
  1176. chunk.isInitial() ? filename :
  1177. chunkFilename;
  1178. try {
  1179. const useChunkHash = !chunk.hasRuntime() || (this.mainTemplate.useChunkHash && this.mainTemplate.useChunkHash(chunk));
  1180. const usedHash = useChunkHash ? chunkHash : this.fullHash;
  1181. const cacheName = "c" + chunk.id;
  1182. if(this.cache && this.cache[cacheName] && this.cache[cacheName].hash === usedHash) {
  1183. source = this.cache[cacheName].source;
  1184. } else {
  1185. if(chunk.hasRuntime()) {
  1186. source = this.mainTemplate.render(this.hash, chunk, this.moduleTemplate, this.dependencyTemplates);
  1187. } else {
  1188. source = this.chunkTemplate.render(chunk, this.moduleTemplate, this.dependencyTemplates);
  1189. }
  1190. if(this.cache) {
  1191. this.cache[cacheName] = {
  1192. hash: usedHash,
  1193. source: source = (source instanceof CachedSource ? source : new CachedSource(source))
  1194. };
  1195. }
  1196. }
  1197. file = this.getPath(filenameTemplate, {
  1198. noChunkHash: !useChunkHash,
  1199. chunk
  1200. });
  1201. if(this.assets[file])
  1202. throw new Error(`Conflict: Multiple assets emit to the same filename ${file}`);
  1203. this.assets[file] = source;
  1204. chunk.files.push(file);
  1205. this.applyPlugins2("chunk-asset", chunk, file);
  1206. } catch(err) {
  1207. this.errors.push(new ChunkRenderError(chunk, file || filenameTemplate, err));
  1208. }
  1209. }
  1210. }
  1211. getPath(filename, data) {
  1212. data = data || {};
  1213. data.hash = data.hash || this.hash;
  1214. return this.mainTemplate.applyPluginsWaterfall("asset-path", filename, data);
  1215. }
  1216. createChildCompiler(name, outputOptions, plugins) {
  1217. const idx = (this.childrenCounters[name] || 0);
  1218. this.childrenCounters[name] = idx + 1;
  1219. return this.compiler.createChildCompiler(this, name, idx, outputOptions, plugins);
  1220. }
  1221. checkConstraints() {
  1222. const usedIds = {};
  1223. const modules = this.modules;
  1224. for(let indexModule = 0; indexModule < modules.length; indexModule++) {
  1225. const moduleId = modules[indexModule].id;
  1226. if(usedIds[moduleId])
  1227. throw new Error(`checkConstraints: duplicate module id ${moduleId}`);
  1228. }
  1229. const chunks = this.chunks;
  1230. for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
  1231. const chunk = chunks[indexChunk];
  1232. if(chunks.indexOf(chunk) !== indexChunk)
  1233. throw new Error(`checkConstraints: duplicate chunk in compilation ${chunk.debugId}`);
  1234. chunk.checkConstraints();
  1235. }
  1236. }
  1237. }
  1238. module.exports = Compilation;