Blame view

node_modules/webpack/lib/optimize/OccurrenceOrderPlugin.js 3.02 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  /*
  	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.plugin("compilation", (compilation) => {
  			compilation.plugin("optimize-module-order", (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.isInitial()) 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;
  					return sum + 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);
  					});
  				}
  
  				modules.forEach(m => {
  					const result = m.reasons.reduce(countOccurs, 0) + m.getNumberOfChunks() + entryCountMap.get(m);
  					occursInAllChunksMap.set(m, result);
  				});
  
  				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;
  					if(a.index > b.index) return 1;
  					if(a.index < b.index) return -1;
  					return 0;
  				});
  			});
  			compilation.plugin("optimize-chunk-order", (chunks) => {
  				const occursInInitialChunksMap = new Map();
  
  				chunks.forEach(c => {
  					const result = c.parents.reduce((sum, p) => {
  						if(p.isInitial()) return sum + 1;
  						return sum;
  					}, 0);
  					return occursInInitialChunksMap.set(c, result);
  				});
  
  				function occurs(c) {
  					return c.blocks.length;
  				}
  
  				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;
  					return a.compareTo(b);
  				});
  			});
  		});
  	}
  }
  
  module.exports = OccurrenceOrderPlugin;