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