0
# Configuration
1
2
Global configuration system for zip.js that controls web workers, compression codecs, and performance settings.
3
4
## configure() Function
5
6
The main configuration function that accepts a configuration object.
7
8
```typescript { .api }
9
function configure(configuration: Configuration): void;
10
```
11
12
### Usage
13
14
```javascript
15
import { configure } from "@zip.js/zip.js";
16
17
// Basic configuration
18
configure({
19
useWebWorkers: true,
20
maxWorkers: 4,
21
chunkSize: 1024 * 64, // 64KB chunks
22
level: 6 // Default compression level
23
});
24
```
25
26
## Configuration Interface
27
28
```typescript { .api }
29
interface Configuration extends WorkerConfiguration {
30
maxWorkers?: number;
31
terminateWorkerTimeout?: number;
32
workerScripts?: {
33
deflate?: string[];
34
inflate?: string[];
35
};
36
chunkSize?: number;
37
Deflate?: typeof ZipDeflate;
38
Inflate?: typeof ZipInflate;
39
CompressionStream?: typeof TransformStream;
40
DecompressionStream?: typeof TransformStream;
41
}
42
```
43
44
### Worker Configuration
45
46
#### maxWorkers
47
48
Maximum number of web workers used for parallel compression/decompression.
49
50
```javascript
51
configure({
52
maxWorkers: navigator.hardwareConcurrency || 4
53
});
54
```
55
56
- **Default**: `navigator.hardwareConcurrency` (number of CPU cores)
57
- **Range**: 1 to 16 (practical limit)
58
- **Effect**: More workers = better parallelization but more memory usage
59
60
#### terminateWorkerTimeout
61
62
Timeout in milliseconds before idle workers are terminated.
63
64
```javascript
65
configure({
66
terminateWorkerTimeout: 10000 // 10 seconds
67
});
68
```
69
70
- **Default**: 5000ms (5 seconds)
71
- **Effect**: Longer timeout keeps workers alive for reuse, shorter timeout saves memory
72
73
#### workerScripts
74
75
Custom URLs for worker scripts, useful for CDN deployments or CSP restrictions.
76
77
```javascript
78
configure({
79
workerScripts: {
80
deflate: ["https://cdn.example.com/zip-deflate-worker.js"],
81
inflate: ["https://cdn.example.com/zip-inflate-worker.js"]
82
}
83
});
84
85
// Multiple scripts (executed in order)
86
configure({
87
workerScripts: {
88
deflate: [
89
"https://cdn.example.com/base-worker.js",
90
"./custom-deflate-extensions.js"
91
]
92
}
93
});
94
```
95
96
### Performance Configuration
97
98
#### chunkSize
99
100
Size of data chunks processed at a time.
101
102
```javascript
103
configure({
104
chunkSize: 1024 * 128 // 128KB chunks
105
});
106
```
107
108
- **Default**: 524288 (512KB)
109
- **Smaller chunks**: Less memory usage, more frequent worker communication
110
- **Larger chunks**: Better performance, more memory usage
111
112
### Codec Configuration
113
114
#### Deflate/Inflate
115
116
Custom compression/decompression implementations.
117
118
```javascript
119
import { Deflate, Inflate } from "./custom-codecs.js";
120
121
configure({
122
Deflate: Deflate, // Custom compression
123
Inflate: Inflate // Custom decompression
124
});
125
```
126
127
#### CompressionStream/DecompressionStream
128
129
Custom stream implementations when native compression streams are not used.
130
131
```javascript
132
configure({
133
CompressionStream: CustomCompressionStream,
134
DecompressionStream: CustomDecompressionStream
135
});
136
```
137
138
## WorkerConfiguration Interface
139
140
Base configuration inherited by many options interfaces.
141
142
```typescript { .api }
143
interface WorkerConfiguration {
144
useWebWorkers?: boolean;
145
useCompressionStream?: boolean;
146
}
147
```
148
149
### useWebWorkers
150
151
Enable or disable web workers for background processing.
152
153
```javascript
154
// Disable web workers (synchronous processing)
155
configure({
156
useWebWorkers: false
157
});
158
159
// Enable web workers (default)
160
configure({
161
useWebWorkers: true
162
});
163
```
164
165
- **Default**: `true`
166
- **When disabled**: All processing happens on main thread (may block UI)
167
- **When enabled**: Processing happens in background workers
168
169
### useCompressionStream
170
171
Enable native browser compression streams when available.
172
173
```javascript
174
configure({
175
useCompressionStream: true // Use native streams
176
});
177
178
configure({
179
useCompressionStream: false // Use JavaScript implementation
180
});
181
```
182
183
- **Default**: `true`
184
- **Effect**: Native streams are faster but may not be available in all environments
185
186
## Advanced Configuration Examples
187
188
### High Performance Setup
189
190
```javascript
191
import { configure } from "@zip.js/zip.js";
192
193
// Optimize for speed with more resources
194
configure({
195
maxWorkers: Math.min(navigator.hardwareConcurrency, 8),
196
chunkSize: 1024 * 1024, // 1MB chunks for better throughput
197
useWebWorkers: true,
198
useCompressionStream: true,
199
terminateWorkerTimeout: 30000 // Keep workers alive longer
200
});
201
```
202
203
### Memory Constrained Setup
204
205
```javascript
206
// Optimize for lower memory usage
207
configure({
208
maxWorkers: 2, // Fewer workers
209
chunkSize: 1024 * 32, // 32KB chunks
210
useWebWorkers: true,
211
terminateWorkerTimeout: 1000 // Quick cleanup
212
});
213
```
214
215
### CSP-Compliant Setup
216
217
```javascript
218
// For environments with strict Content Security Policy
219
configure({
220
useWebWorkers: false, // Avoid blob URLs for workers
221
useCompressionStream: true // Rely on native streams
222
});
223
224
// Or use pre-deployed worker scripts
225
configure({
226
workerScripts: {
227
deflate: ["/static/js/zip-deflate-worker.js"],
228
inflate: ["/static/js/zip-inflate-worker.js"]
229
}
230
});
231
```
232
233
### Custom Codec Integration
234
235
```javascript
236
// Integrate with pako library
237
import pako from 'pako';
238
239
class PakoDeflate {
240
constructor() {
241
this.deflate = new pako.Deflate();
242
}
243
244
append(data) {
245
this.deflate.push(data, false);
246
return new Uint8Array(this.deflate.result);
247
}
248
249
flush() {
250
this.deflate.push(new Uint8Array(0), true);
251
return new Uint8Array(this.deflate.result);
252
}
253
}
254
255
class PakoInflate {
256
constructor() {
257
this.inflate = new pako.Inflate();
258
}
259
260
append(data) {
261
this.inflate.push(data, false);
262
return new Uint8Array(this.inflate.result);
263
}
264
265
flush() {
266
this.inflate.push(new Uint8Array(0), true);
267
}
268
}
269
270
configure({
271
Deflate: PakoDeflate,
272
Inflate: PakoInflate
273
});
274
```
275
276
### Environment-Specific Configuration
277
278
```javascript
279
function configureForEnvironment() {
280
// Detect environment
281
const isNode = typeof process !== 'undefined' && process.versions?.node;
282
const isDeno = typeof Deno !== 'undefined';
283
const isBrowser = typeof window !== 'undefined';
284
285
if (isNode) {
286
// Node.js configuration
287
configure({
288
useWebWorkers: false, // Node doesn't have web workers
289
useCompressionStream: false, // Use JavaScript implementation
290
maxWorkers: 1,
291
chunkSize: 1024 * 1024 // Larger chunks for server processing
292
});
293
} else if (isDeno) {
294
// Deno configuration
295
configure({
296
useWebWorkers: true,
297
useCompressionStream: true,
298
maxWorkers: 4,
299
chunkSize: 1024 * 512
300
});
301
} else if (isBrowser) {
302
// Browser configuration
303
const cores = navigator.hardwareConcurrency || 4;
304
configure({
305
useWebWorkers: true,
306
useCompressionStream: 'CompressionStream' in window,
307
maxWorkers: Math.min(cores, 6),
308
chunkSize: 1024 * 256 // Balance for web performance
309
});
310
}
311
}
312
313
configureForEnvironment();
314
```
315
316
### Dynamic Configuration
317
318
```javascript
319
class AdaptiveConfiguration {
320
constructor() {
321
this.performanceMetrics = {
322
avgCompressionTime: 0,
323
memoryUsage: 0,
324
workerUtilization: 0
325
};
326
}
327
328
updateMetrics(compressionTime, memoryUsed, workersUsed) {
329
this.performanceMetrics = {
330
avgCompressionTime: (this.performanceMetrics.avgCompressionTime + compressionTime) / 2,
331
memoryUsage: memoryUsed,
332
workerUtilization: workersUsed
333
};
334
335
this.adaptConfiguration();
336
}
337
338
adaptConfiguration() {
339
const { avgCompressionTime, memoryUsage, workerUtilization } = this.performanceMetrics;
340
341
let newConfig = {};
342
343
// If compression is slow but memory is fine, use more workers
344
if (avgCompressionTime > 5000 && memoryUsage < 100 * 1024 * 1024) { // 100MB
345
newConfig.maxWorkers = Math.min(8, (newConfig.maxWorkers || 4) + 1);
346
newConfig.chunkSize = 1024 * 1024; // Larger chunks
347
}
348
349
// If memory usage is high, reduce workers and chunk size
350
if (memoryUsage > 500 * 1024 * 1024) { // 500MB
351
newConfig.maxWorkers = Math.max(1, (newConfig.maxWorkers || 4) - 1);
352
newConfig.chunkSize = 1024 * 64; // Smaller chunks
353
newConfig.terminateWorkerTimeout = 1000; // Quick cleanup
354
}
355
356
// If workers are underutilized and performance is good, reduce workers
357
if (workerUtilization < 0.5 && avgCompressionTime < 2000) {
358
newConfig.maxWorkers = Math.max(2, Math.floor((newConfig.maxWorkers || 4) * 0.8));
359
}
360
361
if (Object.keys(newConfig).length > 0) {
362
console.log('Adapting zip.js configuration:', newConfig);
363
configure(newConfig);
364
}
365
}
366
}
367
368
const adaptiveConfig = new AdaptiveConfiguration();
369
370
// Use in ZIP operations
371
async function monitoredZipOperation() {
372
const startTime = Date.now();
373
const startMemory = performance.memory?.usedJSHeapSize || 0;
374
375
// Perform ZIP operation
376
const zipWriter = new ZipWriter(new BlobWriter());
377
await zipWriter.add("data.txt", new TextReader("Large data..."));
378
const result = await zipWriter.close();
379
380
const endTime = Date.now();
381
const endMemory = performance.memory?.usedJSHeapSize || 0;
382
383
adaptiveConfig.updateMetrics(
384
endTime - startTime,
385
endMemory - startMemory,
386
navigator.hardwareConcurrency || 4 // Simplified worker utilization
387
);
388
389
return result;
390
}
391
```
392
393
### Configuration Validation
394
395
```javascript
396
function validateConfiguration(config) {
397
const warnings = [];
398
const errors = [];
399
400
// Validate maxWorkers
401
if (config.maxWorkers !== undefined) {
402
if (config.maxWorkers < 1) {
403
errors.push("maxWorkers must be at least 1");
404
} else if (config.maxWorkers > 16) {
405
warnings.push("maxWorkers > 16 may cause performance issues");
406
}
407
}
408
409
// Validate chunkSize
410
if (config.chunkSize !== undefined) {
411
if (config.chunkSize < 1024) {
412
warnings.push("chunkSize < 1KB may cause performance issues");
413
} else if (config.chunkSize > 10 * 1024 * 1024) {
414
warnings.push("chunkSize > 10MB may cause memory issues");
415
}
416
}
417
418
// Validate terminateWorkerTimeout
419
if (config.terminateWorkerTimeout !== undefined) {
420
if (config.terminateWorkerTimeout < 100) {
421
warnings.push("terminateWorkerTimeout < 100ms may cause frequent worker recreation");
422
}
423
}
424
425
// Log issues
426
errors.forEach(error => console.error("Configuration error:", error));
427
warnings.forEach(warning => console.warn("Configuration warning:", warning));
428
429
if (errors.length > 0) {
430
throw new Error(`Invalid configuration: ${errors.join(", ")}`);
431
}
432
433
return { warnings, errors };
434
}
435
436
// Use before configuring
437
const config = {
438
maxWorkers: 8,
439
chunkSize: 1024 * 512,
440
terminateWorkerTimeout: 5000
441
};
442
443
const validation = validateConfiguration(config);
444
if (validation.errors.length === 0) {
445
configure(config);
446
}
447
```
448
449
## Utility Functions
450
451
### terminateWorkers()
452
453
Manually terminate all active workers.
454
455
```typescript { .api }
456
function terminateWorkers(): Promise<void>;
457
```
458
459
```javascript
460
import { terminateWorkers } from "@zip.js/zip.js";
461
462
// Clean up all workers immediately
463
await terminateWorkers();
464
465
// Useful before page unload or when switching contexts
466
window.addEventListener('beforeunload', () => {
467
terminateWorkers();
468
});
469
```
470
471
### initShimAsyncCodec()
472
473
Transform event-based third-party codec implementations into zip.js-compatible codecs.
474
475
```typescript { .api }
476
function initShimAsyncCodec(
477
library: EventBasedZipLibrary,
478
constructorOptions: unknown | null,
479
registerDataHandler: registerDataHandler
480
): ZipLibrary;
481
```
482
483
```javascript
484
import { initShimAsyncCodec, configure } from "@zip.js/zip.js";
485
486
// Example with a hypothetical async codec library
487
const asyncCodecs = initShimAsyncCodec(
488
AsyncCompressionLibrary, // Third-party library
489
{ level: 6 }, // Options passed to library constructors
490
(codec, onData) => {
491
// Register data handler
492
codec.on('data', onData);
493
}
494
);
495
496
configure({
497
Deflate: asyncCodecs.Deflate,
498
Inflate: asyncCodecs.Inflate
499
});
500
```
501
502
## Best Practices
503
504
### Production Configuration
505
506
```javascript
507
// Recommended production settings
508
configure({
509
maxWorkers: Math.min(navigator.hardwareConcurrency || 4, 6),
510
chunkSize: 1024 * 256, // 256KB - good balance
511
useWebWorkers: true,
512
useCompressionStream: true,
513
terminateWorkerTimeout: 10000 // 10 seconds
514
});
515
```
516
517
### Development Configuration
518
519
```javascript
520
// Development settings with more debugging
521
configure({
522
maxWorkers: 2, // Easier debugging
523
chunkSize: 1024 * 64, // Smaller chunks for testing
524
useWebWorkers: true,
525
terminateWorkerTimeout: 2000 // Quick cleanup
526
});
527
```
528
529
### Testing Configuration
530
531
```javascript
532
// Deterministic settings for testing
533
configure({
534
maxWorkers: 1, // Predictable behavior
535
chunkSize: 1024 * 32, // Small chunks
536
useWebWorkers: false, // Synchronous for easier testing
537
useCompressionStream: false
538
});
539
```
540
541
The configuration system provides fine-grained control over zip.js behavior, allowing optimization for different environments, performance requirements, and resource constraints.