1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | "use strict";
|
7 |
|
8 | const {
|
9 | compareModulesByPreOrderIndexOrIdentifier
|
10 | } = require("../util/comparators");
|
11 | const createSchemaValidation = require("../util/create-schema-validation");
|
12 | const {
|
13 | assignAscendingModuleIds,
|
14 | getUsedModuleIdsAndModules
|
15 | } = require("./IdHelpers");
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | const validate = createSchemaValidation(
|
23 | require("../../schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.js"),
|
24 | () => require("../../schemas/plugins/ids/OccurrenceModuleIdsPlugin.json"),
|
25 | {
|
26 | name: "Occurrence Order Module Ids Plugin",
|
27 | baseDataPath: "options"
|
28 | }
|
29 | );
|
30 |
|
31 | class OccurrenceModuleIdsPlugin {
|
32 | |
33 |
|
34 |
|
35 | constructor(options = {}) {
|
36 | validate(options);
|
37 | this.options = options;
|
38 | }
|
39 |
|
40 | |
41 |
|
42 |
|
43 |
|
44 |
|
45 | apply(compiler) {
|
46 | const prioritiseInitial = this.options.prioritiseInitial;
|
47 | compiler.hooks.compilation.tap("OccurrenceModuleIdsPlugin", compilation => {
|
48 | const moduleGraph = compilation.moduleGraph;
|
49 |
|
50 | compilation.hooks.moduleIds.tap("OccurrenceModuleIdsPlugin", () => {
|
51 | const chunkGraph = compilation.chunkGraph;
|
52 |
|
53 | const [usedIds, modulesInOccurrenceOrder] =
|
54 | getUsedModuleIdsAndModules(compilation);
|
55 |
|
56 | const occursInInitialChunksMap = new Map();
|
57 | const occursInAllChunksMap = new Map();
|
58 |
|
59 | const initialChunkChunkMap = new Map();
|
60 | const entryCountMap = new Map();
|
61 | for (const m of modulesInOccurrenceOrder) {
|
62 | let initial = 0;
|
63 | let entry = 0;
|
64 | for (const c of chunkGraph.getModuleChunksIterable(m)) {
|
65 | if (c.canBeInitial()) initial++;
|
66 | if (chunkGraph.isEntryModuleInChunk(m, c)) entry++;
|
67 | }
|
68 | initialChunkChunkMap.set(m, initial);
|
69 | entryCountMap.set(m, entry);
|
70 | }
|
71 |
|
72 | |
73 |
|
74 |
|
75 |
|
76 | const countOccursInEntry = module => {
|
77 | let sum = 0;
|
78 | for (const [
|
79 | originModule,
|
80 | connections
|
81 | ] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
|
82 | if (!originModule) continue;
|
83 | if (!connections.some(c => c.isTargetActive(undefined))) continue;
|
84 | sum += initialChunkChunkMap.get(originModule);
|
85 | }
|
86 | return sum;
|
87 | };
|
88 |
|
89 | |
90 |
|
91 |
|
92 |
|
93 | const countOccurs = module => {
|
94 | let sum = 0;
|
95 | for (const [
|
96 | originModule,
|
97 | connections
|
98 | ] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
|
99 | if (!originModule) continue;
|
100 | const chunkModules =
|
101 | chunkGraph.getNumberOfModuleChunks(originModule);
|
102 | for (const c of connections) {
|
103 | if (!c.isTargetActive(undefined)) continue;
|
104 | if (!c.dependency) continue;
|
105 | const factor = c.dependency.getNumberOfIdOccurrences();
|
106 | if (factor === 0) continue;
|
107 | sum += factor * chunkModules;
|
108 | }
|
109 | }
|
110 | return sum;
|
111 | };
|
112 |
|
113 | if (prioritiseInitial) {
|
114 | for (const m of modulesInOccurrenceOrder) {
|
115 | const result =
|
116 | countOccursInEntry(m) +
|
117 | initialChunkChunkMap.get(m) +
|
118 | entryCountMap.get(m);
|
119 | occursInInitialChunksMap.set(m, result);
|
120 | }
|
121 | }
|
122 |
|
123 | for (const m of modulesInOccurrenceOrder) {
|
124 | const result =
|
125 | countOccurs(m) +
|
126 | chunkGraph.getNumberOfModuleChunks(m) +
|
127 | entryCountMap.get(m);
|
128 | occursInAllChunksMap.set(m, result);
|
129 | }
|
130 |
|
131 | const naturalCompare = compareModulesByPreOrderIndexOrIdentifier(
|
132 | compilation.moduleGraph
|
133 | );
|
134 |
|
135 | modulesInOccurrenceOrder.sort((a, b) => {
|
136 | if (prioritiseInitial) {
|
137 | const aEntryOccurs = occursInInitialChunksMap.get(a);
|
138 | const bEntryOccurs = occursInInitialChunksMap.get(b);
|
139 | if (aEntryOccurs > bEntryOccurs) return -1;
|
140 | if (aEntryOccurs < bEntryOccurs) return 1;
|
141 | }
|
142 | const aOccurs = occursInAllChunksMap.get(a);
|
143 | const bOccurs = occursInAllChunksMap.get(b);
|
144 | if (aOccurs > bOccurs) return -1;
|
145 | if (aOccurs < bOccurs) return 1;
|
146 | return naturalCompare(a, b);
|
147 | });
|
148 |
|
149 | assignAscendingModuleIds(
|
150 | usedIds,
|
151 | modulesInOccurrenceOrder,
|
152 | compilation
|
153 | );
|
154 | });
|
155 | });
|
156 | }
|
157 | }
|
158 |
|
159 | module.exports = OccurrenceModuleIdsPlugin;
|