STORES Tech Blog

こだわりを持ったお商売を支えるプラットフォーム「STORES」の開発チームによる技術ブログです。

こだわりを持ったお商売を支えるプラットフォーム「STORES」の開発チームによる技術ブログです。

社内UIライブラリの変遷

heyのSTORESでECの開発をしている@nkobaです。 この記事ではフロントエンドで使用しているUIライブラリについて発信していきます!

社内UIライブラリとは

STORESのECではSTORES.jp-Front-Commonというフロントエンドライブラリを作成しています。 その一部としてUIライブラリが含まれており、これを社内プロダクトで利用することで開発効率を向上させたり、ユーザーにとっての触り心地を担保しています。

基本的にSTORESのECではブランド、デザイン、使い心地などを表現するために、ほぼ全てのUIは自作しています。

社内UIライブラリで主に使用している技術は以下になります。

  • Vue.js
  • Storybook
  • REG-SUIT
  • Jest

コンポーネントライブラリの実際 f:id:daitasu:20200730192412p:plain

実際に使われているページ

f:id:daitasu:20200730192429p:plain

導入期

背景

私がフロントエンドチームに加わったのは2018年の末頃でした。 当時のプロジェクトでは、汎用的なコンポーネントは存在しておらず、必要最低限の粒度でコンポーネントが分割されていました。

新しい機能を追加するときは既存の類似UIを手動でコピーして持ってくるという作業が横行しており、今後開発していく上でこれがネックになるというのがチームの共通認識としてありました。

そこでプロジェクトが落ち着いた段階で、社内UIライブラリを作成するということでチームの認識が一致しました。

コンポーネントの原型は存在したが、個々にスタイルが適用されていた f:id:daitasu:20200730192455p:plain

ステークホルダーの巻き込み

UIライブラリを作るという決定はフロントエンドチームだけで下すことはできないため、デザイナー、PdM(プロダクトマネージャー)と相談してスコープ・時期を調整しました。

デザイナーの方と相談すると、「今あるUIを洗い出してみたが、共通のデザインルールから外れているものも多い。デザイナーとしても整理したいので、一緒にUIライブラリの構築に取り組みたい」という返事をいただきました。

PdMの方にも「今後の開発速度を上げるための長期的な投資はぜひやって欲しい」と快く承認をいただきました。

対象の洗い出し

開発する前にUIライブラリに含まれるコンポーネントはどこまでかを改めて定義する必要がありました。また、新しくリデザインするのか、現状のUIを最小限の変更に留めるのかという判断も求められました。

遠い未来の判断を現時点で下すのは難しいので、初めの1歩は直近で開発する画面で使うものを洗い出し、最小限のUIの変更で進めることをデザイナーとスコープを合わせました。

まずは、フロントエンドのエンジニアがコンポーネントの洗い出しと命名を行いました。 参考にしたのはVuetifyElementなどUIライブラリや、マテリアルデザインなどのデザインシステムでした。

現状のページを調査してよく使うUIを洗い出したところ、Atomic DesignのAtomsレベルが多いことがわかりました。 そのため、作成するUIコンポーネントはAtomsの粒度にすることにしました。

それらを整理して階層に落とし込んだのが以下です。

  • Forms
  • Images
  • Messagings
  • Dialogs
  • Navigations
  • Texts

これを元にデザイナーにこれまで使われている類似UIの調査とそのパターンの洗い出しをお願いしました。 エンジニアは現状のコードを確認しながら、洗い出されたパターンや状態についてフィードバックを返しました。

類似パターンの洗い出し f:id:daitasu:20200730192523p:plain

Slackで専用のチャンネルを作ってフィードバックを返しあう f:id:daitasu:20200730192546p:plain

コンポーネントAPI設計

当時の設計上の重要な意思決定は以下の3つでした。

  • エラーの表現をどうすべきか
  • 画面ごとに縦幅、横幅が違うコンポーネントのパターンの整理をどうすべきか
  • 文言の表示は引数で渡すか、要素(aタグやimgタグなど)を渡すべきか

一例を挙げれば、エラーの時には例えば引数として外から状態を渡すという方法も考えられますし、検証用の関数を外から渡して内部で完結させるという方法も考えられます。

結論を書くと、こうした設計上の判断はできる限り汎用的に作るという指針の元で意思決定しました。

汎用的でありすぎれば、UIライブラリとしての統一性が崩れるのは確かですが、一方で類似UIを調査した結果としてデザイン上の例外を許容した方が体験が良いというのも確かであり、私たちのチームはそれを認めることにしました。

上記の例で言えば、以下のような方法に統一しました。

  • エラーは引数として外から状態を渡すようにして検証の方法は使う側に任せる
  • コンポーネントのサイズは外から変えられるようにする
  • 文言の表示であっても要素を受け取れるようにする

コンポーネントのエラー表現

f:id:daitasu:20200730192609p:plain

コンポーネントのエラー実装 f:id:daitasu:20200730192629p:plain

他の細かい設計としてはバージョニングをどうするというものがありましたが、一般的なセマンティックバージョニングで落ち着きました(例: v11.0.6)。

コンポーネントの実装

コンポーネントごとにチケットを発行し、チーム内でコンポーネントごとに分担して作業を行いました。 大方針はこれまで書いてきた通りでしたが、以下の技術セットを使うことにしたため、いくつかの認識合わせが課題になりました。

  • Storybook
  • REG-SUIT
  • Jest

1つは何をどこまでテストで担保すべきかという問題です。REG-SUITとJestの両方のテストを使うので、重複がないようにしたいと考えました。

結論から書くと、UIのビジュアルテストはREG-SUITの画像差分テストで行い、ロジカルなパターンのテストは Jestで行うということにしました。

画像差分テストをREG-SUITに任せることでテストを書くのがとても容易になりました。

PRに画像差分テストの結果が表示される f:id:daitasu:20200730192652p:plain

詳細な画像差分結果 f:id:daitasu:20200730192707p:plain

もう1つはStorybookにどんな情報記載すべきかという問題でした。 コンポーネントはそれなりの数になりそうだったので、誰が、いつStorybookを見るのかを改めて整理したいと考えました。

話し合いの結果、Storybookを見るのはフロントエンド開発者とデザイナーなので、そのどちらの立場から見てもわかりやすいことが大事という認識を共有しました。

そのためStorybookには、実際使われるユースケース(デザインのパターン)、開発者からみた注意点をドキュメントに記載しました。

網羅的なパターンを見やすく整理した f:id:daitasu:20200730192728p:plain

Storybook上の開発者用のドキュメント f:id:daitasu:20200730192742p:plain

拡大期

背景

UIライブラリを作ってしばらく経つと、STORESではUIライブラリが当たり前に使われるようになりました。 リポジトリを複数跨ぐことも発生し、それに伴っていくつかの問題も発生するようになりました。

不具合の発生

UIライブラリを作ってから数ヶ月ほどはその修正の作業が多く発生しました。

「今後の開発速度を上げるため」と語ってはいたものの、実際の複雑なユースケースに対応できていない場合は多く見られました。 ここはもっと別の使い方をしたいというケースもありましたし、純粋に検査できていないパターンもありました。

そのため、思った以上にUIライブラリに投入した工数が見積もり以上に多くなったのは事実です。保守費用を十分に考慮できていなかったのは大きな反省です。 品質が安定し始めたのは導入から半年ほど過ぎた後だったように記憶しています。

新たなユースケース

別のリポジトリでは静的なサイトを作りたいという要望があり、そこにもUIライブラリを導入したいという話が出てきました。

静的なサイトは当初考えていたユースケースではなかったため、専用の対応が必要になりました。

  • サーバーでHTMLを事前に構成するときの対応(SSR対応)
  • ブランディングのための特徴的なUIデザイン

特に後者のサーバーでレンダリングする場合は特有の作法があり、その点を守っていない部分の改修が必要になりました。一部の外部ライブラリもそうだったので、その対応も必要でした。

また静的なサイトはブランディングを意識するために、デザインが大きく違うものもあります。その点は上書きできるようにしました。

現在のサービストップ。テーマカラーが異なる上に、静的なサイトである f:id:daitasu:20200730192805p:plain

リニューアル期

背景

今後の機能開発を促進するために、管理画面を一括してリニューアルするというプロジェクトを最近まで行っていました。 詳細はこちらが詳しいです。

ダッシュボードの全ての画面、全てのUIを対象にした変更なので、当然UIライブラリも全てリデザインが求められました。

デザインシステムの導入

リニューアルのタイミングでカラーシステムを初めとしたデザインシステムを導入して作業することになりました。

導入期でも最低限の色を表現するカラーコードは揃えようという意識はありましたが、徹底した態度では行っていませんでした。

これを機に、色、余白、文字の大きさ、インタラクションなどデザインに関わる部分は全てシステム化して管理するようになりました。

色やサイズなどのルールが明文化された f:id:daitasu:20200730192829p:plain

これを機にコンポーネントのデザインはFigma上に一元化された f:id:daitasu:20200730192845p:plain

アクセシビリティの考慮

アクセシビリティの対応ができていると豪語するにはあまりにも物足りないものではありますが、hover、active、focusあたりの状態の考慮などをこのタイミングで始めました。

また導入期はキーボードだけでの操作ができないUIもいくつかありましたが、これを機にできる限り対応するようにしました。

それに加えて、Storybookのアドオンも導入して、問題をわかりやすくするなどの対応も始めました。 操作性への要望は多く頂いている状況であるため、この対応は今後も続けていきたいです。

上部中央のコンポーネントはactiveな状態。下部はStorybookのアドオンによる警告 f:id:daitasu:20200730192904p:plain

振り返り

これまで投資を続けてきたこともあり、現在では社内UIライブラリはフロントエンド開発の速度、ユーザーの体験を向上させる重要な基盤になりつつあります。 初期費用は想像よりも高くつきましたが、最近の開発ではそれ以上の恩恵を受けています。

社内UIライブラリを導入に携わったエンジニアとしては、ここまで大きなプロジェクトになるとは考慮できていなかったのが正直なところです。 スコープの判断はもとより、いくつかの設計判断、実装判断の誤りも最近は感じられるようになりました。

振り返ってみると、社内UIライブラリは多くのステークホルダーの要望の反映であり、また時間を追って変化していくものであると強く実感しております。

今後

時折、ドメイン上の競合であるShopifyのPolarisのデザインシステムその実装を眺めることがあり、それと比べると今でも道半ばという思いを感じています。

具体的にはStructure、Behaviorなどの横断的な関心であったり、アニメーション、アクセシビリティドキュメンテーションなどに多いに学ぶところがあるように思います。

社内UIライブラリに関わるフロントエンドエンジニアとして、今後のUIライブラリはどうあるべきかについて社内のステークホルダーとともに深く考えていきたいです。

最後に個人的な心象ですが、「STORES.jp-Front-Common」という命名はあまりにも淡白で味気ないので、いつか気持ちが盛り上がるような名前をつけてあげたいなと思っています。