またねMUI、ようこそshadcn/ui

noteに最近のSnack Timeのアップデートについて書いたんですが、そこで脱MUIをしたことについて書きました。

note.com

今回は、MUIを導入していた経緯から脱MUIに至る理由、そして脱MUIでの具体的な作業について紹介します。

TL;DR

  • 当時、Reactで書く場合にMUIを使った方が個人的には早かったので導入した
  • 以下の理由でやめたい気持ちがでてきた
    • MUIがボトルネックでアップデートできないライブラリが一部あった
    • Shadow DOMで埋め込んでいるが、全体的にもっさりとした動きになっている
  • MUIに依存する処理はなかったのでshadcn/uiに切り替えた

差分は以下になります。

github.com

MUIを導入した経緯

自分のサイトでもある zuki.dev といった自分だけで開発しているものでは、昔からMUIを使っていることが多く、開発する場合の速度は一番ありました。
そのため、CRXJSを使った開発する場合でもとりあえずMUIでやるかという気持ちで導入しました。

MUIを使っていて出てきた課題

MUIを使ったExtensionをリリースして、しばらく使っていたんですが、以下のような問題が出てきました。

  • 開発・運用面
    • MUIが原因でReact周辺のライブラリをアップデートできない
  • プロダクト面
    • Shadow DOMで埋め込んでいるとはいえ、なんかもっさりする

前者は特にいうこともありませんが、後者のもっさり感についてはMUIを使っている人たちは知っている、もしくは体感したことがあると思います。
MUIは非常に便利なUIライブラリな一方で動きも多くあり、全体的にもっさりしがちということがあります。
これがこの拡張でも出るようになりました。

また、この時期から自分の会社で開発しているWeb系はshadcn/uiを使うようになり始めてたので、思い切って切り替えようと思いました。

またねMUI、ようこそshadcn/ui

shadcn/uiに切り替えた形跡は、タグ同士の比較を見た方が差分がわかりやすいかと思います。

github.com

大まか流れとしては=以下のような流れでやっていました。

  1. shadcn/uiの導入とセットアップ
    • globals.cssなども用意
  2. ThemaProviderやCacheProviderを削除
  3. Popup,Options,Contentといったように順番に切り替える
  4. Shadow DOMとして埋め込んでいるsrc/content/index.tsxglobals.cssをViteの静的アセットのインポートを使って埋め込み

定型作業に関してはCursor Composerに進めてもらいつつ、並行して作業を進めていました。
それぞれに関してはコミットを見てもらった方が良いんですが、Shadow DOMで埋め込んでいるContent.tsxにTailwind CSSを使っているCSSを適用させるにはひと悶着ありました。

Shadow DOMでTailwind CSSを使う

Shadow DOMでTailwindを使っているCSSを読み込ませるには、Viteの静的アセットのインポートを使って、直接埋め込まないとうまく動作しませんでした。

import styles from "@/styles/globals.css?inline";

...

  createRoot(shadowContainer).render(
    <React.StrictMode>
      <style>{styles}</style>
      <Content initialTime={duration} close={deleteRoot} soundEnabled={soundEnabled} />
    </React.StrictMode>,
  );
});

深ぼってはいないので、実際には他の方法でもうまく動作させることはできるかもしれません。

リリース後

リリース用のzipファイルを確認すると、脱MUI前後で30KBほど容量が削減されました。

また、動作のもっさり感もなくなり大分使いやすくなりました。
そして、Tailwind CSSを導入したこともあり、カラーテーマの実装もTailwindの設定変更だけでよくなり、すぐにリリースすることができました。

さいごに

MUIは非常に便利な一方で、その分依存関係での課題や動作のもっさり感に課題が起きやすいです。
もし誰かの参考になれば幸いです。