skip to content
me nonoakij

[clsx] clsx/lite を使えば 140b だよ

/ 4 min read

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 が参考になりました。

Reference