0
# Caching and Performance
1
2
Performance optimization through caching and memory management utilities, including string interning and dual buffer caching.
3
4
## Capabilities
5
6
### CachedSource
7
8
Decorates a Source with caching for expensive operations like `source()`, `buffer()`, `size()`, `map()`, and `sourceAndMap()`. Provides significant performance improvements through memoization.
9
10
```typescript { .api }
11
/**
12
* Caches results of expensive Source operations
13
* @param source - Source to cache, or function returning Source
14
* @param cachedData - Optional pre-cached data
15
*/
16
class CachedSource extends Source {
17
constructor(source: Source | (() => Source), cachedData?: CachedData);
18
19
/** Returns cached data for serialization/persistence */
20
getCachedData(): CachedData;
21
22
/** Returns the original wrapped Source */
23
original(): Source;
24
25
/** Returns the original Source or the function that creates it */
26
originalLazy(): Source | (() => Source);
27
28
/** Streams chunks efficiently using cached data when possible */
29
streamChunks(
30
options: StreamChunksOptions,
31
onChunk: OnChunk,
32
onSource: OnSource,
33
onName: OnName
34
): GeneratedSourceInfo;
35
}
36
```
37
38
**Usage Examples:**
39
40
```javascript
41
const { CachedSource, SourceMapSource } = require("webpack-sources");
42
43
// Cache expensive source operations
44
const expensiveSource = new SourceMapSource(
45
largeSourceCode,
46
"large-file.js",
47
complexSourceMap
48
);
49
50
const cached = new CachedSource(expensiveSource);
51
52
// First call computes and caches
53
const content1 = cached.source(); // Slow - computes and caches
54
const size1 = cached.size(); // Fast - derived from cached source
55
56
// Subsequent calls use cache
57
const content2 = cached.source(); // Fast - from cache
58
const map = cached.map(); // Slow first time, fast after
59
60
// Lazy source creation
61
const lazyCached = new CachedSource(() => {
62
console.log("Creating source..."); // Only runs when needed
63
return new SourceMapSource(code, name, map);
64
});
65
66
// Source not created yet
67
const lazySize = lazyCached.size(); // Now source is created and cached
68
69
// Get cache data for persistence
70
const cacheData = cached.getCachedData();
71
// Later: new CachedSource(originalSource, cacheData)
72
```
73
74
### Cached Data Interface
75
76
Structure containing cached results for efficient Source recreation.
77
78
```typescript { .api }
79
/**
80
* Cached data structure for CachedSource serialization
81
*/
82
interface CachedData {
83
/** Whether source content is cached */
84
source?: boolean;
85
86
/** Cached buffer representation */
87
buffer: Buffer;
88
89
/** Cached size in bytes */
90
size?: number;
91
92
/** Cached source maps by options key */
93
maps: Map<string, BufferEntry>;
94
95
/** Cached hash components */
96
hash?: (string | Buffer)[];
97
}
98
99
/**
100
* Buffer entry for cached source maps
101
*/
102
interface BufferEntry {
103
/** Raw source map */
104
map?: RawSourceMap | null;
105
106
/** Buffered/optimized source map */
107
bufferedMap?: BufferedMap | null;
108
}
109
110
/**
111
* Optimized source map format with Buffer mappings
112
*/
113
interface BufferedMap {
114
/** Source map version */
115
version: number;
116
117
/** Source file names */
118
sources: string[];
119
120
/** Symbol names */
121
names: string[];
122
123
/** Optional source root */
124
sourceRoot?: string;
125
126
/** Source contents (may be Buffers for binary) */
127
sourcesContent?: ("" | Buffer)[];
128
129
/** Mappings as Buffer for efficiency */
130
mappings?: Buffer;
131
132
/** Generated file name */
133
file: string;
134
}
135
```
136
137
### String Buffer Utilities
138
139
Memory optimization utilities for string interning and dual string/buffer caching.
140
141
```typescript { .api }
142
/**
143
* String and buffer optimization utilities
144
*/
145
interface StringBufferUtils {
146
/** Enables dual string/buffer caching optimization */
147
enableDualStringBufferCaching(): void;
148
149
/** Disables dual string/buffer caching to save memory */
150
disableDualStringBufferCaching(): void;
151
152
/** Checks if dual caching is currently enabled */
153
isDualStringBufferCachingEnabled(): boolean;
154
155
/**
156
* Interns string to save memory when same strings repeat
157
* Only interns strings >= 128 characters when interning is active
158
*/
159
internString(str: string): string;
160
161
/** Starts a string interning range for memory optimization */
162
enterStringInterningRange(): void;
163
164
/** Ends string interning range and cleans up interned strings */
165
exitStringInterningRange(): void;
166
}
167
```
168
169
**Usage Examples:**
170
171
```javascript
172
const { util: { stringBufferUtils } } = require("webpack-sources");
173
174
// Check current caching state
175
console.log(stringBufferUtils.isDualStringBufferCachingEnabled()); // true (default)
176
177
// Disable dual caching to save memory
178
stringBufferUtils.disableDualStringBufferCaching();
179
console.log(stringBufferUtils.isDualStringBufferCachingEnabled()); // false
180
181
// Re-enable for performance
182
stringBufferUtils.enableDualStringBufferCaching();
183
184
// String interning for memory optimization
185
stringBufferUtils.enterStringInterningRange();
186
187
const longString = "a".repeat(200);
188
const interned1 = stringBufferUtils.internString(longString);
189
const interned2 = stringBufferUtils.internString(longString);
190
191
console.log(interned1 === interned2); // true - same reference
192
193
// Clean up interned strings
194
stringBufferUtils.exitStringInterningRange();
195
196
// Nested interning ranges
197
stringBufferUtils.enterStringInterningRange(); // Range 1
198
stringBufferUtils.enterStringInterningRange(); // Range 2 (nested)
199
stringBufferUtils.exitStringInterningRange(); // End range 2
200
stringBufferUtils.exitStringInterningRange(); // End range 1, cleanup happens
201
```
202
203
### Performance Best Practices
204
205
**Caching Strategy:**
206
207
```javascript
208
const { CachedSource, RawSource } = require("webpack-sources");
209
210
// For sources that will be accessed multiple times
211
const frequentlyUsed = new CachedSource(
212
new RawSource(largeContent)
213
);
214
215
// For expensive sources with complex operations
216
const expensiveSource = new CachedSource(() => {
217
// Expensive computation only happens when needed
218
return new SourceMapSource(
219
processLargeFile(),
220
"processed.js",
221
generateComplexSourceMap()
222
);
223
});
224
225
// Persist cache data across sessions
226
const cacheData = frequentlyUsed.getCachedData();
227
// Save cacheData to disk...
228
229
// Later, restore from cache
230
const restored = new CachedSource(originalSource, cacheData);
231
```
232
233
**Memory Optimization:**
234
235
```javascript
236
const { util: { stringBufferUtils } } = require("webpack-sources");
237
238
// For processing many similar sources
239
stringBufferUtils.enterStringInterningRange();
240
241
try {
242
// Process many sources with repeated content
243
const sources = files.map(file => {
244
const content = stringBufferUtils.internString(file.content);
245
return new RawSource(content);
246
});
247
248
// Work with sources...
249
250
} finally {
251
// Always clean up
252
stringBufferUtils.exitStringInterningRange();
253
}
254
255
// Disable dual caching in memory-constrained environments
256
if (process.env.LOW_MEMORY) {
257
stringBufferUtils.disableDualStringBufferCaching();
258
}
259
```
260
261
### Performance Considerations
262
263
- **CachedSource**: Best for sources accessed multiple times, especially with expensive operations
264
- **String Interning**: Effective when processing many sources with repeated content (>= 128 chars)
265
- **Dual Caching**: Improves performance but increases memory usage - disable in memory-constrained environments
266
- **Lazy Sources**: Use function-based CachedSource constructor to defer expensive source creation
267
- **Cache Persistence**: Save and restore CachedData for cross-session performance benefits