1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | "use strict";
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | class FlagIncludedChunksPlugin {
|
13 | |
14 |
|
15 |
|
16 |
|
17 |
|
18 | apply(compiler) {
|
19 | compiler.hooks.compilation.tap("FlagIncludedChunksPlugin", compilation => {
|
20 | compilation.hooks.optimizeChunkIds.tap(
|
21 | "FlagIncludedChunksPlugin",
|
22 | chunks => {
|
23 | const chunkGraph = compilation.chunkGraph;
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | const moduleBits = new WeakMap();
|
38 | const modulesCount = compilation.modules.size;
|
39 |
|
40 |
|
41 | const modulo = 1 / Math.pow(1 / modulesCount, 1 / 31);
|
42 | const modulos = Array.from(
|
43 | { length: 31 },
|
44 | (x, i) => Math.pow(modulo, i) | 0
|
45 | );
|
46 |
|
47 |
|
48 | let i = 0;
|
49 | for (const module of compilation.modules) {
|
50 | let bit = 30;
|
51 | while (i % modulos[bit] !== 0) {
|
52 | bit--;
|
53 | }
|
54 | moduleBits.set(module, 1 << bit);
|
55 | i++;
|
56 | }
|
57 |
|
58 |
|
59 |
|
60 | const chunkModulesHash = new WeakMap();
|
61 | for (const chunk of chunks) {
|
62 | let hash = 0;
|
63 | for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
|
64 | hash |= moduleBits.get(module);
|
65 | }
|
66 | chunkModulesHash.set(chunk, hash);
|
67 | }
|
68 |
|
69 | for (const chunkA of chunks) {
|
70 | const chunkAHash = chunkModulesHash.get(chunkA);
|
71 | const chunkAModulesCount =
|
72 | chunkGraph.getNumberOfChunkModules(chunkA);
|
73 | if (chunkAModulesCount === 0) continue;
|
74 | let bestModule = undefined;
|
75 | for (const module of chunkGraph.getChunkModulesIterable(chunkA)) {
|
76 | if (
|
77 | bestModule === undefined ||
|
78 | chunkGraph.getNumberOfModuleChunks(bestModule) >
|
79 | chunkGraph.getNumberOfModuleChunks(module)
|
80 | )
|
81 | bestModule = module;
|
82 | }
|
83 | loopB: for (const chunkB of chunkGraph.getModuleChunksIterable(
|
84 | bestModule
|
85 | )) {
|
86 |
|
87 |
|
88 | if (chunkA === chunkB) continue;
|
89 |
|
90 | const chunkBModulesCount =
|
91 | chunkGraph.getNumberOfChunkModules(chunkB);
|
92 |
|
93 |
|
94 | if (chunkBModulesCount === 0) continue;
|
95 |
|
96 |
|
97 |
|
98 | if (chunkAModulesCount > chunkBModulesCount) continue;
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | const chunkBHash = chunkModulesHash.get(chunkB);
|
104 | if ((chunkBHash & chunkAHash) !== chunkAHash) continue;
|
105 |
|
106 |
|
107 | for (const m of chunkGraph.getChunkModulesIterable(chunkA)) {
|
108 | if (!chunkGraph.isModuleInChunk(m, chunkB)) continue loopB;
|
109 | }
|
110 | chunkB.ids.push(chunkA.id);
|
111 | }
|
112 | }
|
113 | }
|
114 | );
|
115 | });
|
116 | }
|
117 | }
|
118 | module.exports = FlagIncludedChunksPlugin;
|