clsx
clsx は、複数のクラス名を結合するためのライブラリです。
A tiny (239B) utility for constructing className strings conditionally. Also serves as a faster & smaller drop-in replacement for the classnames module.
clsx/lite
clsx/lite が v2.1.0 でリリースされました。 元々の clsx は 239b で軽量なのが売りだったはずですが、さらに減量されて 140b で使える clsx/lite が export されるようになったそうです。
This is a 140b version of clsx that is ideal for Tailwind and/or React contexts
https://github.com/lukeed/clsx/releases/tag/v2.1.0
公式の Release Note の例を引用します:
import { clsx } from "clsx";
import { clsx as lite } from "clsx/lite";
// strings-only usage is identical
clsx("foo", null, "bar", true && "baz"); //=> "foo bar baz"
lite("foo", null, "bar", true && "baz"); //=> "foo bar baz"
// clsx/lite ignores all non-strings
clsx("foo", { a: true, b: false, c: true }); //=> "foo a c"
lite("foo", { a: true, b: false, c: true }); //=> "foo"
例にある通り、clsx/lite
は、clsx
と比較して完全に互換性があるわけではありません。
文字列以外の引数は無視されます。
Tailwind CSS と使う
最近は Tailwind CSS を使って開発することが多く、その際に clsx も合わせて使用している。
よくある使用例は、以下のようなものです。
import { clsx } from "clsx";
function Button(props: { className?: string; color: "red" | "blue" }) {
return (
<button
className={clsx(
"rounded text-white",
{
"bg-red-700": props.color === "red",
"bg-blue-700": props.color === "blue",
},
props.className,
)}
>
{props.children}
</button>
);
}
前述の通り、clsx
は文字列以外の引数を無視するので、このままだと使えない。
下記のように変更することで、clsx/lite
を使うことができます。
import { clsx } from "clsx/lite";
function Button(props: { className?: string; color: "red" | "blue" }) {
return (
<button
className={clsx(
"rounded text-white",
props.color === "red" && "bg-red-700",
props.color === "blue" && "bg-blue-700",
props.className,
)}
>
{props.children}
</button>
);
}
これはこれで悪くなさそうだと思う。
とはいえ、実際のプロダクトではこのレベルの容量を気にすることもないので、無理に置き換えなくても良いかもしれないともぶっちゃけ思う。
某アニメの大好きな名言を引用して終わりにします。
1% か 2% か ---
600馬力の車にとってそれはわずかなコトかもしれない
だが、それをわずかと笑える者はチューニングを語る資格はナイ
TS Error でプチハマった
Next.js の TypeScript プロジェクトで、clsx/lite
を使おうとしたら、以下のようなエラーが出てしまった。
Cannot find module 'clsx/lite' or its corresponding type declarations.ts(2307)
tsconfig.json moduleResolution を Bundler に変更することで解決した。
- "moduleResolution": "node",
+ "moduleResolution": "Bundler",
clsx/lite の方定義は、package.json の exports で指定しているので、node だと無視されるらしい。
実際、設定値としても、Bundler
が正しそうな気がする(正直このあたりは詳しくないので自信がない)
詳細については、https://blog.s2n.tech/articles/dont-use-moduleresolution-node が参考になりました。