|
1 |
| -# Minifier |
| 1 | +# Oxc Minifier |
2 | 2 |
|
3 |
| -A JavaScript minifier has three components: |
| 3 | +Next-generation JavaScript/TypeScript minifier achieving best-in-class compression. |
4 | 4 |
|
5 |
| -1. compressor |
6 |
| -2. mangler |
7 |
| -3. printer |
| 5 | +## Inspiration |
8 | 6 |
|
9 |
| -## Compressor |
| 7 | +- **Closure Compiler**: Advanced size optimizations |
| 8 | +- **Terser/UglifyJS**: Comprehensive battle-tested transforms |
| 9 | +- **esbuild**: Efficient algorithms and architecture |
| 10 | +- **SWC**: Modern Rust performance |
10 | 11 |
|
11 |
| -The compressor is responsible for rewriting statements and expressions for minimal text output. |
12 |
| -[Terser](https://github.com/terser/terser) is a good place to start for learning the fundamentals. |
| 12 | +## Key Features |
13 | 13 |
|
14 |
| -## Mangler |
| 14 | +- Maximum compression through exhaustive optimizations |
| 15 | +- 100% correctness with comprehensive testing |
| 16 | +- Fixed-point iteration for optimal size |
| 17 | +- Arena allocation for performance |
15 | 18 |
|
16 |
| -The mangler implementation is part of the `SymbolTable` residing in `oxc_semantic`. |
17 |
| -It is responsible for shortening variables. Its algorithm should be gzip friendly. |
| 19 | +## Current Performance |
18 | 20 |
|
19 |
| -The printer is also responsible for printing out the shortened variable names. |
| 21 | +See [`tasks/minsize`](../../tasks/minsize) for compression benchmarks. |
20 | 22 |
|
21 |
| -## Printer |
| 23 | +- Matching/beating esbuild on many libraries |
| 24 | +- Full test262, Babel, TypeScript conformance |
22 | 25 |
|
23 |
| -The printer is responsible for removing whitespace from the source text. |
| 26 | +## Usage |
24 | 27 |
|
25 |
| -### Assumptions |
| 28 | +```rust |
| 29 | +use oxc_minifier::{Minifier, MinifierOptions}; |
26 | 30 |
|
27 |
| -- [Properties of the global object defined in the ECMAScript spec](https://tc39.es/ecma262/multipage/global-object.html#sec-global-object) behaves the same as in the spec |
28 |
| - - Examples of properties: `Infinity`, `parseInt`, `Object`, `Promise.resolve` |
29 |
| - - Examples that breaks this assumption: `globalThis.Object = class MyObject {}` |
30 |
| -- The code does not rely on the `name` property of `Function` or `Class` |
31 |
| - - Examples that breaks this assumption: `function fn() {}; console.log(f.name === 'fn')` |
32 |
| -- [`document.all`](https://tc39.es/ecma262/multipage/additional-ecmascript-features-for-web-browsers.html#sec-IsHTMLDDA-internal-slot) is not used or behaves as a normal object |
33 |
| - - Examples that breaks this assumption: `console.log(typeof document.all === 'undefined')` |
34 |
| -- TDZ violation does not happen |
35 |
| - - Examples that breaks this assumption: `(() => { console.log(v); let v; })()` |
36 |
| -- `with` statement is not used |
37 |
| - - Examples that breaks this assumption: `with (Math) { console.log(PI); }` |
38 |
| -- `.toString()`, `.valueOf()`, `[Symbol.toPrimitive]()` are side-effect free |
39 |
| - - Examples that breaks this assumption: `{ toString() { console.log('sideeffect') } }` |
40 |
| -- Errors thrown when creating a String or an Array that exceeds the maximum length can disappear or moved |
41 |
| - - Examples that breaks this assumption: `try { new Array(Number(2n**53n)) } catch { console.log('log') }` |
42 |
| -- Extending a class does not have a side effect |
43 |
| - - Examples that breaks this assumption: `const v = []; class A extends v {}` |
| 31 | +let options = MinifierOptions::default(); |
| 32 | +let minifier = Minifier::new(options); |
| 33 | +let result = minifier.minify(&mut program); |
| 34 | +``` |
44 | 35 |
|
45 |
| -## Terser Tests |
| 36 | +## Testing Infrastructure |
46 | 37 |
|
47 |
| -The fixtures are copied from https://github.com/terser/terser/tree/v5.9.0/test/compress |
| 38 | +- `just minsize` - Track compression benchmarks |
| 39 | +- `cargo coverage` - Conformance tests (test262, Babel, TypeScript) |
| 40 | +- `tasks/e2e` - Real-world E2E testing |
| 41 | + |
| 42 | +## Development |
| 43 | + |
| 44 | +- `just test` - Run all tests |
| 45 | +- `cargo run -p oxc_minifier --example minifier` - Try the minifier |
| 46 | + |
| 47 | +## Key Dependencies |
| 48 | + |
| 49 | +- [`oxc_ecmascript`](../oxc_ecmascript) - ECMAScript operations and constant evaluation |
| 50 | +- [`oxc_semantic`](../oxc_semantic) - Scope and symbol analysis |
| 51 | +- [`oxc_mangler`](../oxc_mangler) - Variable renaming |
| 52 | + |
| 53 | +## Documentation |
| 54 | + |
| 55 | +- [Architecture](./docs/ARCHITECTURE.md) - Design and components |
| 56 | +- [Optimizations](./docs/OPTIMIZATIONS.md) - Complete optimization catalog |
| 57 | +- [Assumptions](./docs/ASSUMPTIONS.md) - Code assumptions for optimization |
| 58 | +- [Correctness](./docs/CORRECTNESS.md) - Testing and validation |
| 59 | +- [Roadmap](./docs/ROADMAP.md) - Development plan |
| 60 | +- [Claude Guide](./docs/CLAUDE.md) - AI assistant reference |
0 commit comments