Techtouch Developers Blog

テックタッチ株式会社の開発チームによるテックブログです

Material-UI v5を先取りする

adventCalendar-day24

この記事はテックタッチアドベントカレンダー24 日目の記事です。

テックタッチのフロントエンドエンジニアの taka です。 クリスマス・イブを満喫してしまったため投稿するのが遅れてしまいました(嘘)

今回は最もメジャーな React の UI ライブラリの一つであるMaterial-UIの次期バージョンである v5 を先取りしてみようと思います。 v5 は 来年 2021 年 4 月頃リリースされるようで、特にスタイリングに関して大きな変更があるようでした。

注)v5 はまだ α 版であるため、実際のリリース時には本記事の内容とは異なる可能性があることをご理解ください。

Material-UI とは

material-ui.com Material-UIとは、Material Designをベースとした React の UI ライブラリです。 Ant Designと肩を並べる、React で最も有名なライブラリの一つです。 デザインが良いとかコンポーネントが豊富とか Typescript をサポートしているとか、良い点はいっぱいあるのですが、個人的にはハイレベルでカスタマイズ可能な点が特に気に入っています。 例えばコンポーネントのデザインや振る舞いをカスタマイズしたい場合、大抵の UI ライブラリは 無理やり CSS を上書きしたり fork して大元のコードを書き換えたりしてあげないといけないところを、 Material-UI では API レベルでかなり細かくテーマが変更できたり、コンポーネント自体の振る舞いを変えられたり、内部のコンポーネント自体を置き換えられたり、ほとんど大元のコードを書き換えることなくカスタマイズを実現することができます。 最後のほうに詳しく書きますが、テックタッチでも Material-UI を使って細かいレベルでカスタマイズをして UI を実現しているので、このカスタマイズ性は非常に重宝しています。 他にもFigma や Sketch といったデザインツールでもリソースを利用できるので、 Material Design チックな UI をスピーディーに開発したいという方には Material-UI はとてもいいチョイスだと思います。

Material-UI v5 の新機能

そんな Material-UI ですが、更にカスタマイズ性を向上させる変更が v5 で入るようです。 また、style engine も変更になるようです。

Unstyled components

Angular MaterialCDK components (Component Development Kit)と同じようなもので、スタイルなしの振る舞いのみを定義したコンポーネントに分離して、それらも提供するようになるそうです。 既に useAutocompleteusePaginationといったものが Material-UI に存在しているのですが、それのコンポーネント版が今ある全てのコンポーネントに対して用意されるようになる感じですね。

今までもコンポーネントの各要素のクラス名がちゃんと API として定義され外から各々の要素をスタイリングすることができていましたが、Unstyled コンポーネントは更に components prop を受け付けるようになっており、この prop を経由して各々の要素を外から渡すこともできるようになるみたいです。 例えば、以下のような Slider のカスタマイズを考えます。 f:id:techtouch:20201225155517p:plain このようにSliderのつまみのコンポーネントを独自なものに置き換えたいという時は、

<Slider components={{Thumb: MyComponent}}>

のようにすることで実現可能になります。 ここまでハイレベルにカスタマイズ可能な UI ライブラリはなかなかないのではないでしょうか。 どんなものか気になる方は、Sliderコンポーネント API を覗いてみると良いでしょう。

Unstyled components の導入によって、Material-UI は UI を構築するためのマテリアルを提供するものであると言えるようになるので、Material-UI の長期的な維持が期待できるようです。 この変更はフロントエンド開発者の共感を呼び、フロントエンドコミュニティからますます質の高いコミットメントを得ることが期待できるそうです。

個人的に Unstyled コンポーネントは一番待ち望んでいたものです。 Material-UI をそのまま使わずにテーマやスタイルをカスタマイズしているユーザーは一定数あり、 そういった人々にとって、Material-UI が既に持っているスタイリングは不要なものであり、ただバンドルサイズを肥大化させてしまうだけでした。 Unstyled コンポーネントを使うとそういった問題が解決できるようになるのではないかと思います。

ちなみに この Unstyled コンポーネントですが、Slider コンポーネントが試験的に最初に Unstyled 化されたようで、他のコンポーネントも続々と Unstyled 化されようとしているところのようです。 その際はコミュニティにもコミットを求めるそうなので、OSS にコミットするチャンスかも!?

style engine の変更

スタイリングのコアライブラリであり続けた JSSemotion に変わるというとても大きな変更があります。 JSS は React 界隈では styled-components や emotion にいくつかの点(コミュニティでの人気をはじめ、パフォーマンス面や strict mode のサポート、動的スタイル、クラス名ミスマッチのバグなどなど)で劣っているというのが現状です。 当初は styled-components に置き換える予定だったそうですが、いろいろと調査を続けていくと、シェアは styled-components ですが、機能面では Concurrent Mode のサポートは emotion の方が優れているそうなので、emotion を採用する流れになったようです。 ただ、現段階では emotion になるとは言っていますが、emotion だけでなく styled-components にも簡単に切り替えられるようになる想定とのことです。 これは styled API でこれらの差分を吸収することで実現できるようになるそうです。

完全な strict mode のサポート

今まで style 系のサポートが不十分だったみたいですが、style engine が変わることで完全に対応できるようになるようです。

コアコンポーネントで @material-ui/system の prop が利用可能に

今までは Box コンポーネントでしかサポートされていなかったのですが、 Tailwind や styled-system のフィードバックから、コアコンポーネントで style の prop が以下のように利用できるようになります。

<Box
  sx={{
    bgcolor: 'background.paper',
    boxShadow: 1,
    borderRadius: 1,
    p: 2,
    minWidth: 300,
  }}
>

詳しくはこちらに書かれています。 Material-UI System - Material-UI

動的なテーマやカラーバリエーションが利用可能に

JSS では動的なスタイルがパフォーマンスの問題で難しかったそうですが、v5 では style engine が変わるのでこれらにも対応できるようになるそうです。

<Typography textAlign={{ xs: 'left', md: 'center' }} />
<Button mt={3}>

その他

他にも、今まで labにあったコンポーネントが coreに正式に取り込まれることになったり、 色々と Deprecation や Breaking changes があるようです。 ちなみに、我らが Internet Explorer11 のサポートは v6 まで行うそうです。

v5 の変更点、新しいスタイリングについてもっと詳しく知りたい方は [RFC] Material-UI v5 🚀 · Issue #20012 · mui-org/material-ui · GitHub[RFC] v5 styling solution 💅 · Issue #22342 · mui-org/material-ui · GitHub を参照してみてください。

余談:テックタッチでの Material-UI の運用

テックタッチでは Material-UI を使ってフロントエンドを構築しています。 テックタッチの UI は Material Design チックではあるのですが、色だけでなく各コンポーネントの font-size や border-radius、padding などなど、異なるところは少なくありません。 なので、Material-UI のテーマを変更したり API を通してスタイルを変更したり、時にはコンポーネントをラップしてスタイルや振る舞いを変えてあげたりしています。 カスタマイズ性は非常に高いのですが、既存のコンポーネントがどうなっているかをちゃんと理解した上で変更していかないといけないので、結構大変ではあります。 時には GitHub を覗いて元のコードがどうなっているかも参照した上で実装することもあります。

「なんでそんなことまでして Material-UI を使っているの?スクラッチで作ればいいじゃん」という声が聞こえてきそうですが、 ハイクオリティなデザインシステムや UI コンポーネントを 1 から構築するのは少人数では難しく、また相当なスキルを必要とすると思っています。 以前のプロジェクトではほとんどのコンポーネントを 1 から作っていましたが、ちゃんとしたデザインシステムや UI コンポーネントは構築できておらず、 バグも何度も直しましたし、未だに解決できていないバグもいくつかあります。 Material-UI はコミッターが 2000 人以上もいることもあり、今の所バグもほとんど出てきていません(shadow dom 関連でちょこちょこある程度)。

また、正直なところ Material-UI を使いこなしているというよりは、Material-UI を通して UI 設計について学ばさせてもらっているという感じが強いです。 テーマやレイアウトはどうやって実現しているのか、各コンポーネントはエッジケースを含めどういったユースケースを考慮してどうやって作られているのか、 アクセシビリティはどうやって実現しているのか、オーバーレイする系のコンポーネントの上下関係はどうやって制御しているのか、などなど。

おわりに

今回は Material-UI v5 での大きな変更点についてピックアップしました。 Unstyled コンポーネントは long term でメンテナンスし続けていく上ではとても重要な変更だと感じました。 また style engine が変わるのはとても大きな変更で、これにより改善される点が多い印象でした。 個人的には styled-components や emotion が好きなので、この変更は嬉しいですね。 一方で、この変更によって既存のプロダクトが大きく壊れてしまわないかは懸念としてありますので、早く v5 に上げたいという気持ち半分、怖さ半分といったところです。

明日(今日)は jun がテックタッチアドベントカレンダーの最後を締めくくります!どうぞお楽しみに。