UNPKG

4.63 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const {
9 compareModulesByPreOrderIndexOrIdentifier
10} = require("../util/comparators");
11const createSchemaValidation = require("../util/create-schema-validation");
12const {
13 assignAscendingModuleIds,
14 getUsedModuleIdsAndModules
15} = require("./IdHelpers");
16
17/** @typedef {import("../../declarations/plugins/ids/OccurrenceModuleIdsPlugin").OccurrenceModuleIdsPluginOptions} OccurrenceModuleIdsPluginOptions */
18/** @typedef {import("../Compiler")} Compiler */
19/** @typedef {import("../Module")} Module */
20/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
21
22const 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
31class OccurrenceModuleIdsPlugin {
32 /**
33 * @param {OccurrenceModuleIdsPluginOptions=} options options object
34 */
35 constructor(options = {}) {
36 validate(options);
37 this.options = options;
38 }
39
40 /**
41 * Apply the plugin
42 * @param {Compiler} compiler the compiler instance
43 * @returns {void}
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 * @param {Module} module module
74 * @returns {number} count of occurs
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 * @param {Module} module module
91 * @returns {number} count of occurs
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
159module.exports = OccurrenceModuleIdsPlugin;