/
chunk-optimization.ts
138 lines (124 loc) · 3.51 KB
/
chunk-optimization.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import Chunk from './Chunk';
import ExternalModule from './ExternalModule';
import { OutputOptions } from './rollup/types';
/*
* Given a chunk list, perform optimizations on that chunk list
* to reduce the mumber of chunks. Mutates the chunks array.
*
* Manual chunks (with chunk.chunkAlias already set) are preserved
* Entry points are carefully preserved as well
*
*/
export function optimizeChunks(
chunks: Chunk[],
options: OutputOptions,
CHUNK_GROUPING_SIZE: number,
inputBase: string
): Chunk[] {
for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
const mainChunk = chunks[chunkIndex];
const execGroup: Chunk[] = [];
mainChunk.visitStaticDependenciesUntilCondition(dep => {
if (dep instanceof Chunk) {
execGroup.push(dep);
}
});
if (execGroup.length < 2) {
continue;
}
let execGroupIndex = 1;
let seekingFirstMergeCandidate = true;
let lastChunk: Chunk = undefined as any,
chunk = execGroup[0],
nextChunk = execGroup[1];
const isMergeCandidate = (chunk: Chunk) => {
if (chunk.facadeModule !== null || chunk.manualChunkAlias !== null) {
return false;
}
if (!nextChunk || nextChunk.facadeModule !== null) {
return false;
}
if (chunk.getRenderedSourceLength() > CHUNK_GROUPING_SIZE) {
return false;
}
// if (!chunk.isPure()) continue;
return true;
};
do {
if (seekingFirstMergeCandidate) {
if (isMergeCandidate(chunk)) {
seekingFirstMergeCandidate = false;
}
continue;
}
let remainingSize =
CHUNK_GROUPING_SIZE - lastChunk.getRenderedSourceLength() - chunk.getRenderedSourceLength();
if (remainingSize <= 0) {
if (!isMergeCandidate(chunk)) {
seekingFirstMergeCandidate = true;
}
continue;
}
// if (!chunk.isPure()) continue;
const chunkDependencies = new Set<Chunk | ExternalModule>();
chunk.visitStaticDependenciesUntilCondition(dep => chunkDependencies.add(dep));
const ignoreSizeChunks = new Set<Chunk | ExternalModule>([chunk, lastChunk]);
if (
lastChunk.visitStaticDependenciesUntilCondition(dep => {
if (dep === chunk || dep === lastChunk) {
return false;
}
if (chunkDependencies.has(dep)) {
return false;
}
if (dep instanceof ExternalModule) {
return true;
}
remainingSize -= dep.getRenderedSourceLength();
if (remainingSize <= 0) {
return true;
}
ignoreSizeChunks.add(dep);
})
) {
if (!isMergeCandidate(chunk)) {
seekingFirstMergeCandidate = true;
}
continue;
}
if (
chunk.visitStaticDependenciesUntilCondition(dep => {
if (ignoreSizeChunks.has(dep)) {
return false;
}
if (dep instanceof ExternalModule) {
return true;
}
remainingSize -= dep.getRenderedSourceLength();
if (remainingSize <= 0) {
return true;
}
})
) {
if (!isMergeCandidate(chunk)) {
seekingFirstMergeCandidate = true;
}
continue;
}
// within the size limit -> merge!
const optimizedChunkIndex = chunks.indexOf(chunk);
if (optimizedChunkIndex <= chunkIndex) chunkIndex--;
chunks.splice(optimizedChunkIndex, 1);
lastChunk.merge(chunk, chunks, options, inputBase);
execGroup.splice(--execGroupIndex, 1);
chunk = lastChunk;
// keep going to see if we can merge this with the next again
if (nextChunk && !isMergeCandidate(nextChunk)) {
seekingFirstMergeCandidate = true;
}
} while (
((lastChunk = chunk), (chunk = nextChunk), (nextChunk = execGroup[++execGroupIndex]), chunk)
);
}
return chunks;
}