0
# Configuration System
1
2
Flexible configuration management supporting .minify.json files with directory traversal for CLI usage and direct options passing for programmatic usage.
3
4
## Capabilities
5
6
### .minify.json Configuration Files
7
8
The CLI automatically reads .minify.json configuration files from the current directory or parent directories. For programmatic usage, pass options directly to minify functions.
9
10
```javascript { .api }
11
interface MinifyConfiguration {
12
js?: JSConfiguration;
13
css?: CSSConfiguration;
14
html?: HTMLConfiguration;
15
img?: ImageConfiguration;
16
}
17
18
interface JSConfiguration {
19
type?: 'putout' | 'terser' | 'esbuild' | 'swc';
20
putout?: PutoutOptions;
21
terser?: TerserOptions;
22
esbuild?: ESBuildOptions;
23
swc?: SWCOptions;
24
}
25
26
interface CSSConfiguration {
27
type?: 'lightningcss' | 'clean-css';
28
'clean-css'?: CleanCSSOptions;
29
}
30
31
interface HTMLConfiguration extends HTMLMinifierOptions {}
32
33
interface ImageConfiguration {
34
maxSize?: number;
35
}
36
```
37
38
**Usage Examples:**
39
40
```javascript
41
import { minify } from "minify";
42
43
// Programmatic usage - pass options directly
44
const options = {
45
js: { type: 'terser', terser: { mangle: true } },
46
css: { type: 'clean-css' },
47
html: { removeComments: true }
48
};
49
50
const minified = await minify.js(source, options);
51
52
// CLI usage automatically loads .minify.json files
53
// No programmatic import needed for configuration files
54
```
55
56
## Configuration File Format
57
58
### .minify.json Structure
59
60
The configuration file uses JSON format with sections for each minifier type:
61
62
```json { .api }
63
{
64
"js": {
65
"type": "putout",
66
"putout": {
67
"quote": "'",
68
"mangle": true,
69
"mangleClassNames": true,
70
"removeUnusedVariables": true,
71
"removeConsole": false,
72
"removeUselessSpread": true
73
},
74
"terser": {
75
"mangle": true,
76
"compress": {
77
"drop_console": true
78
}
79
},
80
"esbuild": {
81
"minifyWhitespace": true,
82
"minifyIdentifiers": true,
83
"minifySyntax": true
84
},
85
"swc": {
86
"mangle": true,
87
"module": true
88
}
89
},
90
"css": {
91
"type": "clean-css",
92
"clean-css": {
93
"level": 2,
94
"compatibility": "*"
95
}
96
},
97
"html": {
98
"removeComments": true,
99
"removeCommentsFromCDATA": true,
100
"removeCDATASectionsFromCDATA": true,
101
"collapseWhitespace": true,
102
"collapseBooleanAttributes": true,
103
"removeAttributeQuotes": true,
104
"removeRedundantAttributes": true,
105
"useShortDoctype": true,
106
"removeEmptyAttributes": true,
107
"removeEmptyElements": false,
108
"removeOptionalTags": true,
109
"removeScriptTypeAttributes": true,
110
"removeStyleLinkTypeAttributes": true,
111
"minifyJS": true,
112
"minifyCSS": true
113
},
114
"img": {
115
"maxSize": 4096
116
}
117
}
118
```
119
120
## Directory Traversal
121
122
### Configuration File Discovery
123
124
The system walks up parent directories to find .minify.json files:
125
126
```javascript { .api }
127
interface DirectoryTraversal {
128
startDirectory: string; // Current working directory
129
searchPattern: string; // ".minify.json" filename
130
traversalOrder: string[]; // Directories checked in order
131
stopCondition: string; // Root directory or first file found
132
}
133
134
// Example traversal path:
135
// /project/src/components/ → /project/src/components/.minify.json
136
// /project/src/ → /project/src/.minify.json
137
// /project/ → /project/.minify.json
138
// / → /.minify.json
139
```
140
141
**Directory Traversal Examples:**
142
143
```javascript
144
// Project structure:
145
// /project/
146
// ├── .minify.json ← Root configuration
147
// ├── src/
148
// │ ├── .minify.json ← Source-specific overrides
149
// │ └── components/
150
// │ └── Button.js ← Uses src/.minify.json
151
152
// CLI working from /project/src/components/
153
minify Button.js
154
// Uses: /project/src/.minify.json
155
156
// CLI working from /project/
157
minify src/components/Button.js
158
// Uses: /project/.minify.json
159
160
// No configuration file found - uses defaults
161
// CLI working from /tmp/
162
minify /some/file.js
163
// Uses: built-in defaults
164
```
165
166
## Configuration Sections
167
168
### JavaScript Configuration
169
170
Configure JavaScript minifiers with type selection and options:
171
172
```json { .api }
173
{
174
"js": {
175
"type": "putout",
176
"putout": {
177
"quote": "'",
178
"mangle": true,
179
"mangleClassNames": true,
180
"removeUnusedVariables": true,
181
"removeConsole": false,
182
"removeUselessSpread": true
183
}
184
}
185
}
186
```
187
188
**JavaScript Configuration Examples:**
189
190
```json
191
// Putout configuration (default)
192
{
193
"js": {
194
"type": "putout",
195
"putout": {
196
"mangle": true,
197
"removeUnusedVariables": false,
198
"quote": "'"
199
}
200
}
201
}
202
203
// Terser configuration
204
{
205
"js": {
206
"type": "terser",
207
"terser": {
208
"mangle": {
209
"toplevel": true
210
},
211
"compress": {
212
"drop_console": true,
213
"drop_debugger": true,
214
"pure_funcs": ["console.log"]
215
}
216
}
217
}
218
}
219
220
// ESBuild configuration
221
{
222
"js": {
223
"type": "esbuild",
224
"esbuild": {
225
"minifyWhitespace": true,
226
"minifyIdentifiers": true,
227
"minifySyntax": true,
228
"target": ["es2020"]
229
}
230
}
231
}
232
233
// SWC configuration
234
{
235
"js": {
236
"type": "swc",
237
"swc": {
238
"mangle": true,
239
"module": true,
240
"compress": {
241
"unused": true
242
}
243
}
244
}
245
}
246
```
247
248
### CSS Configuration
249
250
Configure CSS minifiers with backend selection and optimization levels:
251
252
```json { .api }
253
{
254
"css": {
255
"type": "clean-css",
256
"clean-css": {
257
"level": {
258
"1": {
259
"specialComments": 0,
260
"removeWhitespace": true
261
},
262
"2": {
263
"mergeAdjacentRules": true,
264
"removeEmpty": true,
265
"removeDuplicateRules": true
266
}
267
},
268
"compatibility": {
269
"properties": {
270
"colors": false,
271
"ieFilters": true
272
}
273
}
274
}
275
}
276
}
277
```
278
279
**CSS Configuration Examples:**
280
281
```json
282
// LightningCSS (default - minimal configuration)
283
{
284
"css": {
285
"type": "lightningcss"
286
}
287
}
288
289
// Clean-CSS with optimization levels
290
{
291
"css": {
292
"type": "clean-css",
293
"clean-css": {
294
"level": 2,
295
"compatibility": "*",
296
"format": "beautify",
297
"sourceMap": true
298
}
299
}
300
}
301
302
// Clean-CSS with detailed options
303
{
304
"css": {
305
"type": "clean-css",
306
"clean-css": {
307
"level": {
308
"1": {
309
"cleanupCharsets": true,
310
"normalizeUrls": true,
311
"optimizeBackground": true,
312
"optimizeBorderRadius": true,
313
"optimizeFilter": true,
314
"optimizeFont": true,
315
"removeEmpty": true,
316
"removeWhitespace": true,
317
"specialComments": "all"
318
},
319
"2": {
320
"mergeAdjacentRules": true,
321
"mergeIntoShorthands": true,
322
"mergeMedia": true,
323
"removeDuplicateRules": true,
324
"removeUnusedAtRules": false
325
}
326
}
327
}
328
}
329
}
330
```
331
332
### HTML Configuration
333
334
Configure HTML minification with comprehensive optimization settings:
335
336
```json { .api }
337
{
338
"html": {
339
"removeComments": true,
340
"removeCommentsFromCDATA": true,
341
"removeCDATASectionsFromCDATA": true,
342
"collapseWhitespace": true,
343
"collapseBooleanAttributes": true,
344
"removeAttributeQuotes": true,
345
"removeRedundantAttributes": true,
346
"useShortDoctype": true,
347
"removeEmptyAttributes": true,
348
"removeEmptyElements": false,
349
"removeOptionalTags": true,
350
"removeScriptTypeAttributes": true,
351
"removeStyleLinkTypeAttributes": true,
352
"minifyJS": true,
353
"minifyCSS": true
354
}
355
}
356
```
357
358
**HTML Configuration Examples:**
359
360
```json
361
// Conservative HTML minification
362
{
363
"html": {
364
"removeComments": false,
365
"collapseWhitespace": true,
366
"removeEmptyElements": false,
367
"removeOptionalTags": false,
368
"minifyJS": false,
369
"minifyCSS": false
370
}
371
}
372
373
// Aggressive HTML minification
374
{
375
"html": {
376
"removeComments": true,
377
"collapseWhitespace": true,
378
"removeAttributeQuotes": true,
379
"removeRedundantAttributes": true,
380
"removeEmptyAttributes": true,
381
"removeOptionalTags": true,
382
"minifyJS": true,
383
"minifyCSS": true,
384
"useShortDoctype": true
385
}
386
}
387
388
// Template-friendly configuration
389
{
390
"html": {
391
"collapseWhitespace": true,
392
"removeComments": false,
393
"removeEmptyElements": false,
394
"ignoreCustomFragments": [
395
"<%[\\s\\S]*?%>",
396
"<\\?[\\s\\S]*?\\?>"
397
]
398
}
399
}
400
```
401
402
### Image Configuration
403
404
Configure image processing and base64 inlining thresholds:
405
406
```json { .api }
407
{
408
"img": {
409
"maxSize": 102400
410
}
411
}
412
```
413
414
**Image Configuration Examples:**
415
416
```json
417
// Conservative image inlining (small files only)
418
{
419
"img": {
420
"maxSize": 10000
421
}
422
}
423
424
// Aggressive image inlining
425
{
426
"img": {
427
"maxSize": 500000
428
}
429
}
430
431
// Disable image inlining
432
{
433
"img": {
434
"maxSize": 0
435
}
436
}
437
438
// Default behavior (100KB threshold)
439
{
440
"img": {
441
"maxSize": 102400
442
}
443
}
444
```
445
446
## Configuration Hierarchy
447
448
### Precedence Rules
449
450
Configuration sources are applied in order of precedence:
451
452
```javascript { .api }
453
interface ConfigurationPrecedence {
454
1: 'runtime-options'; // Highest: Options passed to minify functions
455
2: 'nearest-config-file'; // .minify.json in current/nearest parent directory
456
3: 'default-settings'; // Lowest: Built-in default configurations
457
}
458
459
// Example precedence resolution for programmatic usage:
460
const runtimeOptions = { js: { type: 'terser' } }; // Passed to function
461
462
const finalConfig = {
463
...builtInDefaults,
464
...runtimeOptions // Takes precedence
465
};
466
```
467
468
**Hierarchy Examples:**
469
470
```javascript
471
// Project with nested configuration
472
// /project/.minify.json:
473
{
474
"js": { "type": "putout" },
475
"css": { "type": "clean-css" }
476
}
477
478
// /project/src/.minify.json:
479
{
480
"js": { "type": "terser" } // Overrides parent
481
}
482
483
// CLI working from /project/src/ uses nearest config:
484
minify app.js
485
// Uses: { js: { type: "terser" }, css: { type: "clean-css" } }
486
487
// Programmatic usage ignores config files:
488
const result = await minify.js(source, {
489
js: { type: 'esbuild' } // Only uses passed options
490
});
491
```
492
493
## Error Handling
494
495
### Configuration Error Management
496
497
Robust error handling for configuration file issues:
498
499
```javascript { .api }
500
interface ConfigurationErrors {
501
fileNotFound: 'cli-uses-defaults'; // CLI continues with defaults
502
invalidJSON: 'cli-throws-parse-error'; // JSON syntax errors in CLI
503
filePermissions: 'cli-throws-access-error'; // File access denied in CLI
504
malformedOptions: 'validates-at-usage'; // Validation during minification
505
}
506
```
507
508
**Error Handling Examples:**
509
510
```bash
511
# Missing configuration file (CLI uses defaults)
512
minify app.js
513
# Uses built-in defaults, no error
514
515
# Invalid JSON syntax in .minify.json
516
# { "js": { type: "invalid" } // Missing closing brace
517
minify app.js
518
# CLI Error: JSON parse error in .minify.json
519
520
# File permission error
521
# .minify.json exists but is not readable
522
minify app.js
523
# CLI Error: EACCES - cannot read .minify.json
524
```
525
526
```javascript
527
// Invalid configuration options (caught during programmatic usage)
528
const invalidConfig = { js: { type: 'nonexistent-minifier' } };
529
try {
530
const result = await minify.js(source, invalidConfig);
531
} catch (error) {
532
console.log(error.message); // Invalid minifier type error
533
}
534
```
535
536
## Testing and Development
537
538
### Configuration Usage Patterns
539
540
Different approaches for various use cases:
541
542
```javascript { .api }
543
interface UsagePatterns {
544
programmatic: 'pass-options-directly';
545
cli: 'use-minify-json-files';
546
testing: 'pass-options-directly';
547
environment: 'conditional-configuration';
548
}
549
550
// Production vs Development example
551
const getConfig = (environment) => ({
552
js: {
553
type: environment === 'production' ? 'terser' : 'putout',
554
[environment === 'production' ? 'terser' : 'putout']: {
555
mangle: environment === 'production',
556
removeConsole: environment === 'production'
557
}
558
}
559
});
560
```
561
562
**Testing Integration Examples:**
563
564
```javascript
565
// Test configuration by passing options directly
566
import { minify } from 'minify';
567
568
describe('Configuration System', () => {
569
test('should use custom JS configuration', async () => {
570
const options = { js: { type: 'esbuild' } };
571
const result = await minify.js('function test() {}', options);
572
expect(result).toBeTruthy();
573
});
574
575
test('should use custom CSS configuration', async () => {
576
const options = { css: { type: 'clean-css' } };
577
const result = await minify.css('body { color: red; }', options);
578
expect(result).toBeTruthy();
579
});
580
});
581
582
// Development environment - different configs for dev vs prod
583
const isDev = process.env.NODE_ENV === 'development';
584
const devConfig = {
585
js: {
586
type: 'putout',
587
putout: { removeConsole: false } // Keep console in dev
588
}
589
};
590
const prodConfig = {
591
js: {
592
type: 'terser',
593
terser: { compress: { drop_console: true } }
594
}
595
};
596
597
const config = isDev ? devConfig : prodConfig;
598
const result = await minify.js(source, config);
599
```