UNPKG

4.65 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 { assignAscendingModuleIds } = require("./IdHelpers");
13
14/** @typedef {import("../../declarations/plugins/ids/OccurrenceModuleIdsPlugin").OccurrenceModuleIdsPluginOptions} OccurrenceModuleIdsPluginOptions */
15/** @typedef {import("../Compiler")} Compiler */
16/** @typedef {import("../Module")} Module */
17/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
18
19const 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
28class OccurrenceModuleIdsPlugin {
29 /**
30 * @param {OccurrenceModuleIdsPluginOptions=} options options object
31 */
32 constructor(options = {}) {
33 validate(options);
34 this.options = options;
35 }
36
37 /**
38 * Apply the plugin
39 * @param {Compiler} compiler the compiler instance
40 * @returns {void}
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 * @param {Module} module module
75 * @returns {number} count of occurs
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 * @param {Module} module module
92 * @returns {number} count of occurs
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
156module.exports = OccurrenceModuleIdsPlugin;