mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			118 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| /*
 | |
| 	MIT License http://www.opensource.org/licenses/mit-license.php
 | |
| 	Author Tobias Koppers @sokra
 | |
| */
 | |
| "use strict";
 | |
| 
 | |
| class OccurrenceOrderPlugin {
 | |
| 	constructor(preferEntry) {
 | |
| 		if(preferEntry !== undefined && typeof preferEntry !== "boolean") {
 | |
| 			throw new Error("Argument should be a boolean.\nFor more info on this plugin, see https://webpack.js.org/plugins/");
 | |
| 		}
 | |
| 		this.preferEntry = preferEntry;
 | |
| 	}
 | |
| 	apply(compiler) {
 | |
| 		const preferEntry = this.preferEntry;
 | |
| 		compiler.hooks.compilation.tap("OccurrenceOrderPlugin", (compilation) => {
 | |
| 			compilation.hooks.optimizeModuleOrder.tap("OccurrenceOrderPlugin", (modules) => {
 | |
| 				const occursInInitialChunksMap = new Map();
 | |
| 				const occursInAllChunksMap = new Map();
 | |
| 
 | |
| 				const initialChunkChunkMap = new Map();
 | |
| 				const entryCountMap = new Map();
 | |
| 				modules.forEach(m => {
 | |
| 					let initial = 0;
 | |
| 					let entry = 0;
 | |
| 					m.forEachChunk(c => {
 | |
| 						if(c.canBeInitial()) initial++;
 | |
| 						if(c.entryModule === m) entry++;
 | |
| 					});
 | |
| 					initialChunkChunkMap.set(m, initial);
 | |
| 					entryCountMap.set(m, entry);
 | |
| 				});
 | |
| 
 | |
| 				const countOccursInEntry = (sum, r) => {
 | |
| 					if(!r.module) return sum;
 | |
| 					return sum + initialChunkChunkMap.get(r.module);
 | |
| 				};
 | |
| 				const countOccurs = (sum, r) => {
 | |
| 					if(!r.module) return sum;
 | |
| 					let factor = 1;
 | |
| 					if(typeof r.dependency.getNumberOfIdOccurrences === "function")
 | |
| 						factor = r.dependency.getNumberOfIdOccurrences();
 | |
| 					if(factor === 0) return sum;
 | |
| 					return sum + factor * r.module.getNumberOfChunks();
 | |
| 				};
 | |
| 
 | |
| 				if(preferEntry) {
 | |
| 					modules.forEach(m => {
 | |
| 						const result = m.reasons.reduce(countOccursInEntry, 0) + initialChunkChunkMap.get(m) + entryCountMap.get(m);
 | |
| 						occursInInitialChunksMap.set(m, result);
 | |
| 					});
 | |
| 				}
 | |
| 
 | |
| 				const originalOrder = new Map();
 | |
| 				let i = 0;
 | |
| 				modules.forEach(m => {
 | |
| 					const result = m.reasons.reduce(countOccurs, 0) + m.getNumberOfChunks() + entryCountMap.get(m);
 | |
| 					occursInAllChunksMap.set(m, result);
 | |
| 					originalOrder.set(m, i++);
 | |
| 				});
 | |
| 
 | |
| 				modules.sort((a, b) => {
 | |
| 					if(preferEntry) {
 | |
| 						const aEntryOccurs = occursInInitialChunksMap.get(a);
 | |
| 						const bEntryOccurs = occursInInitialChunksMap.get(b);
 | |
| 						if(aEntryOccurs > bEntryOccurs) return -1;
 | |
| 						if(aEntryOccurs < bEntryOccurs) return 1;
 | |
| 					}
 | |
| 					const aOccurs = occursInAllChunksMap.get(a);
 | |
| 					const bOccurs = occursInAllChunksMap.get(b);
 | |
| 					if(aOccurs > bOccurs) return -1;
 | |
| 					if(aOccurs < bOccurs) return 1;
 | |
| 					const orgA = originalOrder.get(a);
 | |
| 					const orgB = originalOrder.get(b);
 | |
| 					return orgB - orgA;
 | |
| 				});
 | |
| 			});
 | |
| 			compilation.hooks.optimizeChunkOrder.tap("OccurrenceOrderPlugin", (chunks) => {
 | |
| 				const occursInInitialChunksMap = new Map();
 | |
| 				const originalOrder = new Map();
 | |
| 
 | |
| 				let i = 0;
 | |
| 				chunks.forEach(c => {
 | |
| 					let occurs = 0;
 | |
| 					for(const chunkGroup of c.groupsIterable) {
 | |
| 						for(const parent of chunkGroup.parentsIterable) {
 | |
| 							if(parent.isInitial())
 | |
| 								occurs++;
 | |
| 						}
 | |
| 					}
 | |
| 					occursInInitialChunksMap.set(c, occurs);
 | |
| 					originalOrder.set(c, i++);
 | |
| 				});
 | |
| 
 | |
| 				const occurs = c => {
 | |
| 					return c.getNumberOfGroups();
 | |
| 				};
 | |
| 
 | |
| 				chunks.sort((a, b) => {
 | |
| 					const aEntryOccurs = occursInInitialChunksMap.get(a);
 | |
| 					const bEntryOccurs = occursInInitialChunksMap.get(b);
 | |
| 					if(aEntryOccurs > bEntryOccurs) return -1;
 | |
| 					if(aEntryOccurs < bEntryOccurs) return 1;
 | |
| 					const aOccurs = occurs(a);
 | |
| 					const bOccurs = occurs(b);
 | |
| 					if(aOccurs > bOccurs) return -1;
 | |
| 					if(aOccurs < bOccurs) return 1;
 | |
| 					const orgA = originalOrder.get(a);
 | |
| 					const orgB = originalOrder.get(b);
 | |
| 					return orgB - orgA;
 | |
| 				});
 | |
| 			});
 | |
| 		});
 | |
| 	}
 | |
| }
 | |
| 
 | |
| module.exports = OccurrenceOrderPlugin;
 |