ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 81

  1. Blog

scule vs change-case: 570 B vs 795 B Gzip

Aditya Challa·5 October 2026·4 min read

Hands-on
On this page
  1. What I tested
  2. How much smaller is scule?
  3. Do the outputs match on real identifiers?
  4. Is camelCase speed a reason to switch?
  5. Which one should you pick?
  6. Sources
  7. Related

I bundled the two common string-case helpers on this box: scule 1.3.0 came out at 570 bytes gzip for six converters, while change-case 5.4.4 came out at 795 bytes. On the same fixtures, camelCase took about 0.91 µs per call on scule versus about 1.26 µs on change-case (~1.4×).

Short answer: pick scule when you want a smaller unjs-style helper for kebab/snake/camel identifiers. Keep change-case when you need space-separated title/sentence/constant cases, or when your inputs are human phrases with spaces. No affiliate links in this post.

What I tested

  • Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 01:50 IST.
  • Versions: scule 1.3.0, change-case 5.4.4, Node 22.20.0, esbuild 0.28.2 browser ESM minify + gzip -9.
  • Inputs: 10 identifier-like fixtures (kebab, snake, camel, acronyms, CONSTANT_CASE). Speed: 500,000 calls per function, median of 9 rounds, two runs with library order reversed. Scripts in /workspace/bench-scule-change-case/.
  • Findings: core six-export gzip 570 B vs 795 B; camel-only 412 B vs 668 B. camelCase ~914 / 878 ns vs ~1,259 / 1,225 ns; kebab ~890 / 763 vs ~1,169 / 1,138; snake ~851 / 770 vs ~1,360 / 1,132; pascal ~866 / 859 vs ~1,253 / 1,255.
  • One surprise: scule does not split on spaces. camelCase("hello world") stays "hello world"; change-case returns "helloWorld". Acronyms and digits also diverge (XMLHttpRequest, user_id_42).
  • Not tested: browsers, locale-aware casing, non-ASCII scripts, or change-case's splitSeparateNumbers option matrix beyond the defaults.

How much smaller is scule?

Build (esbuild browser minify)Minifiedgzip -9
scule (6 converters)1,267 B570 B
change-case (7 converters)1,970 B795 B
scule camelCase only735 B412 B
change-case camelCase only1,285 B668 B

About 1.4× smaller gzip for a comparable core export set. Track client cost the same way as size-limit vs bundlesize. Other unjs helpers in the same size lane show up in pathe vs node:path and defu vs lodash.merge.

Do the outputs match on real identifiers?

Inputscule camelCasechange-case camelCase
foo-bar-bazfooBarBazfooBarBaz
Already_Mixed-casealreadyMixedCasealreadyMixedCase
hello worldhello world (unchanged)helloWorld
XMLHttpRequestxMLHttpRequestxmlHttpRequest
getHTTPResponsegetHTTPResponsegetHttpResponse
user_id_42userId42userId_42

Kebab and snake agree on delimiter-separated identifiers. Spaces, acronyms, and trailing digits do not. change-case also ships capitalCase, constantCase, sentenceCase, pathCase, and friends that scule does not. For broader lodash-style utility swaps, see es-toolkit vs lodash.

Is camelCase speed a reason to switch?

Call cost (500k, median of 9, 2 order-reversed runs, ns/op)sculechange-case
camelCase914 / 8781,259 / 1,225
kebabCase890 / 7631,169 / 1,138
snakeCase851 / 7701,360 / 1,132
pascalCase866 / 8591,253 / 1,255

scule won every converter I timed by roughly 1.3–1.6×. That matters for codegen loops and build plugins, not for a handful of className transforms. If your bottleneck is hashing keys instead of casing them, compare ohash vs object-hash. Config and path helpers in the same unjs stack sit next to yaml vs js-yaml and smol-toml vs @iarna/toml.

Which one should you pick?

SituationMy pick
Client bundle, kebab/snake/camel onlyscule
Nuxt / unjs stack already presentscule
Inputs are human phrases with spaceschange-case
Need CONSTANT_CASE, sentenceCase, pathCasechange-case
Must match change-case acronym/digit quirks in testsstay on change-case

Bottom line: scule 1.3.0 was 570 B gzip versus 795 B for change-case 5.4.4, and about 1.4× faster on camelCase on this box. Who should not switch: pipelines that feed space-separated titles into the converter, or suites pinned to change-case's acronym and digit rules. Dependency cleanup next door often pairs with knip vs depcheck.

How this was made: I installed both packages on the ShopperCove box, measured esbuild browser bundles, timed four converters in two order-reversed runs, and compared split/camel outputs on seven fixtures. The JSON results sit next to the scripts. The write-up was drafted with AI help and checked against that output.

Sources

  • https://github.com/unjs/scule
  • https://github.com/blakeembrey/change-case
  • https://www.npmjs.com/package/scule
  • https://www.npmjs.com/package/change-case

Related

  • https://www.shoppercove.com/blog/pathe-vs-node-path
  • https://www.shoppercove.com/blog/defu-vs-lodash-merge
  • https://www.shoppercove.com/blog/size-limit-vs-bundlesize
  • https://www.shoppercove.com/blog/es-toolkit-vs-lodash
  • https://www.shoppercove.com/blog/ohash-vs-object-hash
  • https://www.shoppercove.com/blog/yaml-vs-js-yaml
  • https://www.shoppercove.com/blog/smol-toml-vs-iarna-toml
  • https://www.shoppercove.com/blog/knip-vs-depcheck
sculechange-casejavascriptbundle sizeperformancestring conversioncamelcasekebabcase

Lab evidence

What I found running this

Hands-on on ShopperCove box 6 Oct 2026 ~01:50 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). scule 1.3.0 vs change-case 5.4.4, esbuild 0.28.2 browser ESM minify + gzip -9. Size: scule core 1,267/570 B vs change-case 1,970/795 B; camel-only 735/412 vs 1,285/668. Speed (500,000 calls, 9-round median, order-reversed, ns/op): camelCase scule 913.8 / 878.2 vs change-case 1,259.3 / 1,224.7; kebab 890.4 / 763.1 vs 1,168.6 / 1,137.7; snake 851.1 / 769.9 vs 1,360.0 / 1,132.1; pascal 865.6 / 859.1 vs 1,253.2 / 1,254.7. Behavior: scule leaves "hello world" unsplit; change-case → helloWorld; acronym/digit outputs differ on XMLHttpRequest, getHTTPResponse, user_id_42. Not tested: browsers, locale casing, non-ASCII, splitSeparateNumbers options. No affiliate.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 35

    cookie-es vs cookie: 2.3 KB vs 1.4 KB Gzip

    5 Oct 2026

  • Plate 28

    perfect-debounce vs lodash.debounce: 447 B vs 1.2 KB

    5 Oct 2026

  • Plate 38

    smol-toml vs @iarna/toml: 3x Faster on Deno Cargo

    5 Oct 2026

On this page

  1. What I tested
  2. How much smaller is scule?
  3. Do the outputs match on real identifiers?
  4. Is camelCase speed a reason to switch?
  5. Which one should you pick?
  6. Sources
  7. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove