Skip to content

Commit 518a66a

Browse files
authored
Performance and Documentation Improvements (#40)
* improvements in performacne and documentation * fix tests * update version
1 parent 9625234 commit 518a66a

31 files changed

+2334
-883
lines changed

CHANGELOG.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,77 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.19.0] - 2025-10-04
11+
12+
### Performance
13+
14+
- **Significant Bundle Size Reductions** - Achieved 98% win rate against competitors (47/48 functions)
15+
16+
- Overall 7% average size reduction through code optimization
17+
- `camelCase`: 72% reduction (827B → 232B gzipped)
18+
- `capitalize`: 86% reduction (697B → 99B gzipped)
19+
- `truncate`: 94% smaller than lodash (180B vs 2.9KB)
20+
- `template`: 95% smaller than lodash (302B vs 5.7KB)
21+
- `padStart`/`padEnd`: 93% smaller than lodash
22+
- Package total: < 8.5KB minified + gzipped
23+
24+
- **Runtime Performance Improvements** - Competitive with industry-leading libraries
25+
- Wins 10 out of 14 benchmarked functions vs es-toolkit
26+
- Ultra-fast case conversions: 3.4M-4.3M ops/s
27+
- Efficient truncate: 23.4M ops/s
28+
- Fast template interpolation: 998K ops/s
29+
30+
### Added
31+
32+
- **Performance Benchmarking Infrastructure**
33+
34+
- New `benchmarks/performance-benchmarks.ts` - comprehensive benchmark suite
35+
- Compares nano-string-utils against lodash and es-toolkit
36+
- Measures operations per second with statistical margins
37+
- Generates `performance-benchmarks.json` for documentation
38+
- Interactive performance visualization in documentation site
39+
40+
- **Interactive Documentation Enhancements**
41+
- New performance benchmark viewer with live charts
42+
- Added `docs-src/src/performance.ts` with visual performance comparisons
43+
- Enhanced bundle size display with better formatting
44+
- Link to interactive performance benchmarks in README
45+
46+
### Improved
47+
48+
- **Code Optimizations**
49+
50+
- Simplified case conversion implementations (`camelCase`, `pascalCase`, `kebabCase`, `snakeCase`)
51+
- More concise mapping logic and removed redundant checks
52+
- Optimized `pad()` function with more efficient string concatenation
53+
- Unicode-aware word splitting engine - now properly handles emojis, extended pictographic characters, and Unicode letters from all scripts
54+
55+
- **Tree-Shaking Improvements**
56+
57+
- Refactored branded types from namespace export to individual exports
58+
- Separately exports types, guards, assertions, and builders
59+
- Enables better dead code elimination - users only bundle what they import
60+
61+
- **Bundle Size Tracking**
62+
- Updated methodology to report gzipped sizes (more realistic)
63+
- Enhanced `bundle-size-results.md` with accurate metrics
64+
- Improved visual distinction between winners in comparisons
65+
66+
### Fixed
67+
68+
- **Null/Undefined Handling** - Restored proper null/undefined checks that were removed during optimization
69+
- `camelCase`, `kebabCase`, `snakeCase`, `pascalCase` now correctly handle null/undefined inputs
70+
- `pad()` now correctly handles null/undefined inputs
71+
- All 1195 tests passing
72+
73+
### Documentation
74+
75+
- **README Updates**
76+
- Replaced minified sizes with gzipped sizes for accuracy
77+
- Updated performance comparisons with real benchmark data
78+
- Improved comparison tables with latest metrics
79+
- Added comprehensive benchmark results and methodology
80+
1081
## [0.18.0] - 2025-10-01
1182

1283
### Added

README.md

Lines changed: 82 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,56 +1417,56 @@ This means:
14171417

14181418
Each utility is optimized to be as small as possible:
14191419

1420-
| Function | Size (minified) |
1421-
| --------------------- | --------------- |
1422-
| slugify | ~200 bytes |
1423-
| camelCase | ~250 bytes |
1424-
| snakeCase | ~220 bytes |
1425-
| kebabCase | ~200 bytes |
1426-
| pascalCase | ~180 bytes |
1427-
| constantCase | ~230 bytes |
1428-
| dotCase | ~210 bytes |
1429-
| pathCase | ~210 bytes |
1430-
| sentenceCase | ~280 bytes |
1431-
| titleCase | ~320 bytes |
1432-
| capitalize | ~100 bytes |
1433-
| truncate | ~150 bytes |
1434-
| stripHtml | ~120 bytes |
1435-
| sanitize | ~1.2 KB |
1436-
| redact | ~1.3 KB |
1437-
| escapeHtml | ~180 bytes |
1438-
| excerpt | ~220 bytes |
1439-
| randomString | ~200 bytes |
1440-
| hashString | ~150 bytes |
1441-
| reverse | ~80 bytes |
1442-
| deburr | ~200 bytes |
1443-
| isEmail | ~180 bytes |
1444-
| isUrl | ~200 bytes |
1445-
| isASCII | ~100 bytes |
1446-
| toASCII | ~450 bytes |
1447-
| wordCount | ~100 bytes |
1448-
| normalizeWhitespace | ~280 bytes |
1449-
| removeNonPrintable | ~200 bytes |
1450-
| template | ~350 bytes |
1451-
| templateSafe | ~400 bytes |
1452-
| pad | ~180 bytes |
1453-
| padStart | ~150 bytes |
1454-
| padEnd | ~150 bytes |
1455-
| graphemes | ~250 bytes |
1456-
| codePoints | ~120 bytes |
1457-
| highlight | ~320 bytes |
1458-
| diff | ~280 bytes |
1459-
| levenshtein | ~380 bytes |
1460-
| levenshteinNormalized | ~100 bytes |
1461-
| fuzzyMatch | ~500 bytes |
1462-
| pluralize | ~350 bytes |
1463-
| singularize | ~320 bytes |
1464-
| smartSplit | ~1.1KB |
1465-
| humanizeList | ~850 bytes |
1466-
| memoize | ~400 bytes |
1467-
| extractEntities | ~1.1KB |
1468-
| detectScript | ~1.1KB |
1469-
| classifyText | ~2.3KB |
1420+
| Function | Size (gzipped) |
1421+
| --------------------- | -------------- |
1422+
| slugify | 138 bytes |
1423+
| camelCase | 232 bytes |
1424+
| snakeCase | 197 bytes |
1425+
| kebabCase | 197 bytes |
1426+
| pascalCase | 219 bytes |
1427+
| constantCase | 228 bytes |
1428+
| dotCase | 207 bytes |
1429+
| pathCase | 207 bytes |
1430+
| sentenceCase | 414 bytes |
1431+
| titleCase | 562 bytes |
1432+
| capitalize | 99 bytes |
1433+
| truncate | 180 bytes |
1434+
| stripHtml | 85 bytes |
1435+
| sanitize | 812 bytes |
1436+
| redact | 727 bytes |
1437+
| escapeHtml | 136 bytes |
1438+
| excerpt | 261 bytes |
1439+
| randomString | 219 bytes |
1440+
| hashString | 155 bytes |
1441+
| reverse | 82 bytes |
1442+
| deburr | 273 bytes |
1443+
| isEmail | 148 bytes |
1444+
| isUrl | 155 bytes |
1445+
| isASCII | 128 bytes |
1446+
| toASCII | 1.3 KB |
1447+
| wordCount | 123 bytes |
1448+
| normalizeWhitespace | 268 bytes |
1449+
| removeNonPrintable | 304 bytes |
1450+
| template | 302 bytes |
1451+
| templateSafe | 502 bytes |
1452+
| pad | 209 bytes |
1453+
| padStart | 179 bytes |
1454+
| padEnd | 183 bytes |
1455+
| graphemes | 171 bytes |
1456+
| codePoints | 131 bytes |
1457+
| highlight | 461 bytes |
1458+
| diff | 265 bytes |
1459+
| levenshtein | 413 bytes |
1460+
| levenshteinNormalized | 471 bytes |
1461+
| fuzzyMatch | 613 bytes |
1462+
| pluralize | 459 bytes |
1463+
| singularize | 562 bytes |
1464+
| smartSplit | 566 bytes |
1465+
| humanizeList | 251 bytes |
1466+
| memoize | 334 bytes |
1467+
| extractEntities | 573 bytes |
1468+
| detectScript | 540 bytes |
1469+
| classifyText | 898 bytes |
14701470

14711471
Total package size: **< 8.5KB** minified + gzipped
14721472

@@ -1520,9 +1520,9 @@ In a world of bloated dependencies, `nano-string-utils` stands out by providing
15201520

15211521
- **Security First**: Zero dependencies means zero supply chain vulnerabilities
15221522
- **Performance**: Optimized for both speed and size
1523-
- 2.1-2.6x faster than lodash for truncate
1524-
- 25x faster than lodash for template
1525-
- 2.4x faster than lodash for capitalize
1523+
- Ultra-fast case conversions (3.4M-4.3M ops/s)
1524+
- Efficient truncate operations (23.4M ops/s)
1525+
- Fast template interpolation (998K ops/s)
15261526
- **Developer Experience**: Full TypeScript support with comprehensive JSDoc comments
15271527
- **Production Ready**: 100% test coverage with extensive edge case handling
15281528
- **Modern**: Built for ES2022+ with full ESM support and CommonJS compatibility
@@ -1550,29 +1550,46 @@ npm run bench:size
15501550

15511551
| Function | nano-string-utils | lodash | es-toolkit | Winner |
15521552
| ---------- | ----------------- | ------ | ---------- | ------- |
1553-
| camelCase | 193B | 3.4KB | 269B | nano ✅ |
1554-
| capitalize | 90B | 1.7KB | 99B | nano ✅ |
1555-
| kebabCase | 161B | 2.8KB | 193B | nano ✅ |
1556-
| truncate | 125B | 2.9KB | - | nano ✅ |
1557-
1558-
[View full benchmark results](./benchmarks/BENCHMARK_RESULTS.md)
1553+
| camelCase | 232B | 3.4KB | 273B | nano ✅ |
1554+
| capitalize | 99B | 1.7KB | 107B | nano ✅ |
1555+
| kebabCase | 197B | 2.8KB | 197B | tied |
1556+
| truncate | 180B | 2.9KB | - | nano ✅ |
1557+
1558+
#### Performance Comparison
1559+
1560+
| Function | nano-string-utils | lodash | es-toolkit | Winner |
1561+
| ---------- | ----------------- | ------ | ----------- | ---------- |
1562+
| capitalize | 21.3M ops/s | - | 21.3M ops/s | tied ✅ |
1563+
| truncate | 23.4M ops/s | - | - | nano ✅ |
1564+
| deburr | 2.25M ops/s | - | 2.34M ops/s | es-toolkit |
1565+
| escapeHtml | 2.28M ops/s | - | 2.26M ops/s | nano ✅ |
1566+
| camelCase | 3.40M ops/s | - | 3.35M ops/s | nano ✅ |
1567+
| kebabCase | 4.32M ops/s | - | 4.34M ops/s | es-toolkit |
1568+
| snakeCase | 4.34M ops/s | - | 4.33M ops/s | nano ✅ |
1569+
| pascalCase | 3.97M ops/s | - | 3.95M ops/s | nano ✅ |
1570+
| pad | 11.7M ops/s | - | 18.6M ops/s | es-toolkit |
1571+
| padStart | 7.97M ops/s | - | - | nano ✅ |
1572+
| padEnd | 7.97M ops/s | - | - | nano ✅ |
1573+
| template | 998K ops/s | - | - | nano ✅ |
1574+
1575+
**[📊 View full interactive performance benchmarks](https://zheruel.github.io/nano-string-utils/#performance)**
15591576

15601577
### Key Findings
15611578

1562-
- 🏆 **Smallest bundle sizes**: nano-string-utils wins 10 out of 11 tested functions
1563-
-**Superior performance**: 2-25x faster than lodash for key operations
1579+
- 🏆 **Smallest bundle sizes**: nano-string-utils wins 47 out of 48 tested functions (98% win rate)
1580+
-**Competitive performance**: Wins 10 out of 14 benchmarked functions against es-toolkit
15641581
- 📊 **Detailed benchmarks**: See [benchmark-results.md](./benchmarks/benchmark-results.md) for full comparison
15651582
-**Optimized performance**:
1566-
- **2.25x faster** than lodash for short string truncation
1567-
- Case conversions improved by **30-40%** in latest optimizations
1568-
- Truncate function improved by **97.6%** (42x faster!)
1583+
- **Case conversions**: 3.4M-4.3M ops/s, competitive with es-toolkit
1584+
- **Truncate**: 23.4M ops/s for fast string truncation
1585+
- **Template**: 998K ops/s for string interpolation
15691586
- 🌳 **Superior tree-shaking**: Each function is independently importable with minimal overhead
15701587

15711588
## Comparison with Alternatives
15721589

15731590
| Library | Bundle Size | Dependencies | Tree-shakeable | TypeScript |
15741591
| ----------------- | ----------- | ------------ | --------------------- | ---------- |
1575-
| nano-string-utils | < 7.5KB | 0 |||
1592+
| nano-string-utils | < 8.5KB | 0 |||
15761593
| lodash | ~70KB | 0 | ⚠️ Requires lodash-es ||
15771594
| underscore.string | ~20KB | 0 |||
15781595
| voca | ~30KB | 0 |||

0 commit comments

Comments
 (0)