Help us understand the problem. What is going on with this article?

Reactでよく使う classnames を置き換えるライブラリ。その名も「clsx」

More than 1 year has passed since last update.

はじめに

みなさんReactでクラス名を動的に設定する場合どうしてますか?
ほとんどの人がclassnamesというライブラリを使っているのではないでしょうか。

ここ最近そのclassnamesを置き換えるようなライブラリが登場していたようなので紹介します。

classnames

まずライブラリの紹介の前に比較対象であるclassnamesについてですが
Reactを利用する人ならほぼ全員が知っているであろうライブラリです。
というか公式で推奨されてるんですね。

https://www.npmjs.com/package/classnames

紹介

ここからが本題

clsx

今回紹介するのは clsx というライブラリです。
https://www.npmjs.com/package/clsx

今のバージョンは1.0.4でメジャーリリースは2018/12/25。
つまり去年のクリスマス生まれのだいぶ新しいライブラリですね。:snowman2:
npmのインストールグラフを見る限り、今年の5月から爆発的に利用者が増えてきているライブラリです。

コンセプトはclassnamesより小さく高速な代替品とのこと。

どうやらあのmaterial-uiがバンドルサイズを小さくするためにこちらに移行したようで、
それが突然ダウンロード数が爆発した要因かと思われます。

https://material-ui.com/blog/material-ui-v4-is-out/

GitHub Star サイズ(minifed) サイズ(+gzip) 参考
classnames 10,781 588B 371B リンク
clsx 467 512B 306B リンク

バンドルサイズについてgzip時は306Bとclassnamesよりも18%(65B)ほど小さくなっております。

使い方

以下公式のコピペ

import clsx from 'clsx';

// Strings (variadic)
clsx('foo', true && 'bar', 'baz');
//=> 'foo bar baz'

// Objects
clsx({ foo:true, bar:false, baz:isTrue() });
//=> 'foo baz'

// Objects (variadic)
clsx({ foo:true }, { bar:false }, null, { '--foobar':'hello' });
//=> 'foo --foobar'

// Arrays
clsx(['foo', 0, false, 'bar']);
//=> 'foo bar'

// Arrays (variadic)
clsx(['foo'], ['', 0, false, 'bar'], [['baz', [['hello'], 'there']]]);
//=> 'foo bar baz hello there'

// Kitchen sink (with nesting)
clsx('foo', [1 && 'bar', { baz:false, bat:null }, ['hello', ['world']]], 'cya');
//=> 'foo bar hello world cya'

Usageの癖が強いぃ!
やりたいことはわかりますがUsageにしてはトリッキー過ぎてスッと入ってこない・・・
一言で言うとおそらくclassnamesの完全互換です。(普段使いする分には実証済み)

ベンチマーク


ベンチマーク結果(ちょっと長いので折りたたみます。)
# Strings
  classcat ≠   x  8,590,994 ops/sec ±0.27% (94 runs sampled)
  classnames   x  3,987,311 ops/sec ±1.68% (94 runs sampled)
  clsx         x 11,066,632 ops/sec ±0.23% (96 runs sampled)

# Objects
  classcat ≠   x 8,566,516 ops/sec ±0.42% (97 runs sampled)
  classnames   x 3,697,182 ops/sec ±1.31% (98 runs sampled)
  clsx         x 7,147,168 ops/sec ±0.30% (95 runs sampled)

# Arrays
  classcat ≠   x 7,538,840 ops/sec ±0.56% (95 runs sampled)
  classnames   x 1,697,776 ops/sec ±1.41% (97 runs sampled)
  clsx         x 7,922,225 ops/sec ±0.18% (95 runs sampled)

# Nested Arrays
  classcat ≠   x 6,462,158 ops/sec ±0.22% (97 runs sampled)
  classnames   x 1,201,570 ops/sec ±0.22% (96 runs sampled)
  clsx         x 6,132,222 ops/sec ±0.49% (95 runs sampled)

# Nested Arrays w/ Objects
  classcat ≠   x 6,277,187 ops/sec ±0.62% (93 runs sampled)
  classnames   x 1,613,328 ops/sec ±1.69% (96 runs sampled)
  clsx         x 5,156,844 ops/sec ±0.22% (95 runs sampled)

# Mixed
  classcat ≠   x 7,073,536 ops/sec ±0.26% (95 runs sampled)
  classnames   x 2,149,952 ops/sec ±1.24% (95 runs sampled)
  clsx         x 5,577,715 ops/sec ±0.20% (93 runs sampled)

# Mixed (Bad Data)
  classcat ≠   x 1,770,852 ops/sec ±0.14% (97 runs sampled)
  classnames   x 1,148,353 ops/sec ±0.54% (97 runs sampled)
  clsx         x 1,887,010 ops/sec ±0.14% (96 runs sampled)


今回の主役clsxですがclassnamesと比べた結果、差が大きいものでは5倍近くのパフォーマンスがでるようです。

ちなみに
ここでclasscatというライブラリが比較対象に含まれていますね。
こちらはコンセプトは同じ「打倒classnames」なのですがAPIの互換性がないライブラリなので
この記事では扱わないことにしています(興味がある方は調べてみてください)

まとめ

個人的な感想としては使ってみてもいいかな?という感じです。

が、正直なところ置き換えるメリットもそれほど大きくないですし、
なによりclassnamesに依存しているライブラリが山ほどあるので、
classnamesがデファクトスタンダードから引きずり降ろされることもないと思います。
(つまりタイトルは煽りです:sweat_smile:

ちなみにclassnamesのIssueに「clsxっていうのが最近出てきたけどこのままでよいのか?」といった物もあり、
ひょっとするとclassnamesの性能がこれからまた上がるかも知れませんね。

こうやって対抗ライブラリが出てきては比較して〜というのは面白いし学びもあるので、
みなさんも普段使っているライブラリに他の似たものがないか調べてみてはいかがでしょうか?


おしまい

taqm
1児のパパです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away