TypeScriptでReactコンポーネントライブラリを構築する際に学んだ教訓
コンポーネントライブラリは大流行しています。Shopify、Salesforce、IBM、さらにはアメリカ合衆国政府も、他の組織やビジネスと同様にコンポーネントライブラリを構築しています。それらはブログ、ポッドキャスト、YouTubeチュートリアルの主題となり、残っているのはその件に関するケン・バーンズのドキュメンタリーだけです。
実際のところ、私はソフトウェアアーキテクトであり上級エンジニアでもあり、目下、顕著なアメリカ政府機関のUIの基盤となるReactコンポーネントライブラリの開発を率いています。私は、プロジェクト管理、コミュニケーション、アクセシビリティ、エンジニアリング、そして何百万人もの人々の生活に影響を与えるものを作るためのテストで得た教訓を皆さんと共有したいと考えています。そして、それ全ての浮き沈みをね。
じゃあ、コンポーネントライブラリって一体何がそんなに重要なの?
デザインシステム
コンポーネントライブラリはデザインシステムから始まります。Nielsen Norman Groupはデザインシステムをこのように定義しています:
デザインシステムは、再利用可能なコンポーネントとパターンを使用して大規模なデザインを管理するための完全な基準セットです。
デザインシステムは、ブランドの消費者にとって最高のUXを構成する基準と慣行を列挙しています。それは、サイロを壊し、コンウェイの法則からの衝動を避けるために、各チームがコミュニケーションに使用すべき命名法を表しています。カラーやタイポグラフィ、スペーシングに関する基本ルールなどがあります。これらの核心原則は、ボタンやデートピッカーのような明示的なものから、グリッドシステムのようなさりげないものまで、より大きなコンポーネントの基盤となります。
私たちのUXチームは、デザインシステムの開発と維持を行っています。ソフトウェアのように、それは進化し、バージョン管理され、協同作業です。UXデザイナー間とプログラムの他のアーキテクトやエンジニアとの間には、何が意味を成し、何が実現可能かについての会話があります。入れ子になったドロップダウンは必要ですか?自分たちだけの完璧なDatepicker
を作る時間がありますか?それとも、オープンソースのものをカスタマイズすることを試みますか?無効なボタンについてどう感じますか?それを使う意味があると思うなら、コントラスト比のような一般的な落とし穴をどう乗り越えるか?
このようなことです。私たちは、"原子"から"ページ"までのウェブインターフェイスを分解して、デザインシステムの目的を説明する共通の命名法としてアトミックデザインの言葉を使います。
コンポーネントライブラリを構築する上での挑戦、おそらく最も困難な部分はツールです。部分的にはUXチームの嗜好、部分的には私たちの仕事の機密性のための開発環境の制約のために、UXワイヤーフレームのバージョニングを自動化したり、エンジニアが構築に使えるアーティファクトに変換したりするためのツールを最適化することができていません。その結果、わかりにくいワイヤーフレームで作業しなければなりません。それらを閲覧するために、私たちのマシンにツールをインストールする必要がありますが、これはライセンスを増やし、開発者体験(DX)に負担をかけます。または、カスタムブラウザープラグインで何百もの静的アセットファイルを通り抜ける必要があります。どちらも最適な体験ではありません。その上、デザインシステムとコンポーネントライブラリの一貫性を追跡するのは手動のプロセスです。
きれいなものだとは言いませんが、全てが悪いわけでもありません。
コンポーネントライブラリの価値
デザインシステムは、実装の詳細から独立した一連のコア原則です。どの技術を選んでこれらの原則を実装し、実際のUIエンジニアにとって現実のものにするかは自由です。
私たちにとっては、それはReactです。私たちのReactコンポーネントはプログラムに多大な価値を生み出しています。
一貫性
私たちのコンポーネントライブラリは、開発チーム全体にわたってデザインシステムを適用します。コンポーネントを使用することで、UIが私たちのブランドと一致し、ユーザーに最高かつ最も直感的な体験を提供することがほぼ保証されます。開発者は、UXチームとして検証されたコンポーネントを使用していると確信でき、それによって彼らがデザインシステムの一貫性などの横断的な問題ではなく、自分たちのサービスの特定のユースケースに注力することができます。
ライブラリはまた、UXチームによる視覚テストを通過するUIの可能性を最大化します。これは重要です。違反は私たちの配信カデンスを遅くし、フィードバックを得る能力を低下させるからです。
アクセシビリティ
一貫性に関連するアクセシビリティは、私たちのコンポーネントライブラリでの最優先事項です。アクセシビリティのことを一般的に#a11yと言いますが、それは視覚障害者の能力を向上させるだけではありません。それはまた、聴覚、運動、器用さに困難を経験する人々を力づけることを意味します。それは_全員_を力づけることを意味します。
プログラムは契約によっても法律によっても、アクセシブルなUIを生み出すことを求められています。具体的には508コンプライアンスです。とはいえ、アクセシビリティは職業的義務以上のものです。それは私の個人的な優先事項です。私が作るすべてのものが、すべてのユーザーにとって直感的であることが非常に重要です。
私はこの点についてもうすぐ詳しく説明しますが、私たちのコンポーネントライブラリはアクセシビリティのために構築されています。開発チームは個々のコンポーネントのアクセシビリティを信頼でき、前述のように、自分のユースケースに焦点を当てることができます。もちろん、あなたはアクセシブルなドロップダウンやオートコンプリート、デートピッカーについて考えているかもしれませんが、私たちはセマンティックHTMLコンポーネントも提供しています。例えば、ライブラリにはSection
が登場し、あなたが想像する通りのsection
HTML要素を表しています。そして、SectionGrid
は、私たちのデザインシステムのグリッドを搭載したsection
要素です。
もちろん、コンポーネントライブラリは開発者を完全なアクセシビリティへの半分の道のりしか進められませんが、0から始める必要がないのは良いものです。
再利用性
私たちは、直感的なAPIを持つコンポーネントを提供するために非常に一生懸命働いていますが、その課題はあなたが思っているよりも厄介です。APIには、消費者がデザインシステムに違反しないように十分な意見を持たせる必要があります。しかし、コンポーネントが幅広いユースケースをサポートするために十分な自由を許すべきです。Button
コンポーネントについては、それほど簡単です。Card
やPage
などのレイアウトコンポーネントについては、もっと厳しいです。その結果の再利用性が、個々のチームとプログラム全体をはるかに効率的にしました。
また、できるだけ機能を少なくする努力をしています。コンポーネントのAPIは、開発チームが行動を提供するためのプロパティを提供します。明らかな例では、デベロッパーはonClick
動作をButton
コンポーネントに提供します。私たちは自身の状態を維持する必要があるより複雑なコンポーネントを持っていますが、可能な限り最小限に抑えようとしています。これにより、関心事の分離が実現し、コンポーネントのテストが非常に簡単になります。そして、十分なテスト可能性は、十分な再利用性につながります。
エンカプセレーション
この後、詳細に把握しますが、私たちはコンポーネントを一から構築しません。それどころか、既存のオープンソースコンポーネントをカスタマイズし、それらのAPIに自分たちのAPIをマッピングします。これは私たちの開発チームからコンポーネントの実装の詳細を抽象化します。例えば、私たちはreact-datepickerを独自のDatePicker
の基盤として使用しますが、私たちがそれを別のものと交換することに決めたとしても、消費者はそれを知る由もありません。
コンポーネントスタック
私が言ったように、私たちはReactと共にコンポーネントライブラリを構築しますが、それが推奨されるものですが、Facebookによるバックアップと、市場浸透、人気を鑑みて、リスクを嫌う政府顧客にとっても安全な選択です。
しかし、簡単な部分はReactです。コンポーネントスタックの他の部分を見ていきましょう。
TypeScript
コンポーネントライブラリの構築を始めた頃、私は2つの理由でTypeScriptを不可欠だと考えました。タイプセーフティを開発時とビルド時に強制することで、バグをはるかに速くキャッチでき、プロジェクト管理の観点からは遥かに安価です。さらに重要なのは、TypeScriptで私たちのAPIを構築することで、アプリケーション開発チームのライブラリ消費者をサポートする上で、IDEでのコード補完と_彼らの_ビルドでのタイプチェックを大いに助けになるということです。
また、いくつかのTypeScript APIがARIAの値を促進するために必要な場合もあると言及しておきます。他のプロパティからそれらを私たち自身で導き出せない場合です。
Chakra UI
先に触れたように、私たちのコンポーネントはオープンソースのコンポーネントに基づいて
こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/realneilc/lessons-learned-from-building-a-react-component-library-with-typescript-3bkb