「Design Systems」輪読会まとめ

はじめに

WEBサイトのページを効率よく開発したり、ブランド毀損なく拡張していくためには、 そのページで使われているパーツ(ボタンや、色、フォントなど)を繰り返し使い回せるように管理しておくことが重要です。

ただ、その繰り返して使うパーツをどの粒度で作成、保存、共有、使用するかをプロジェクトメンバー間で決めておかないと、だんだんと崩壊していきます。

どのようなモチベーションでデザインし、それを変更、保存、共有、使用するかのルールを定めて明文化することを「デザインシステム」といいます。

今回、この「デザインシステム」について、具体的にどのようなことを明文化するべきかをデザイナーとフロントエンドエンジニア間で認識合わせるをするために「Design Systems」という本の輪読会を行いました。
この記事は本のまとめと感想の記事になります。

業務時間内で毎週1時間をつかって1章ずつ声に出して読みました。
全10章なので10週で終わります。(実際可能なペースです)

Design Systems ―デジタルプロダクトのためのデザインシステム実践ガイド

Design Systems ―デジタルプロダクトのためのデザインシステム実践ガイド

f:id:uggds:20190629235947j:plain
輪読会の様子

本のまとめ

デザインシステムとは
あるプロダクトのデザインに関するルールを定義し、そのルールに則ってプロダクトをデザインしていく仕組み

繰り返し要素を組み合わせてインタフェースを作成する

繰り返し要素の例

  • ユーザフロー
  • インタラクション
  • ボタン
  • テキストフィールド
  • アイコン
  • タイポグラフィ
  • リードテキスト
  • ...

デザインシステムでいうルールとはこれらの繰り返しの要素を
どのように作成、保存、共有、使用するかを記載したもの

繰り返し要素=デザインパターン

デザインシステムで整理、用意しておくもの

デザインパターンの種別

  • 機能パターン
    プロダクトの領域やコアな機能に基づいて決まるパターン
    ECサイトなら商品表示、絞込み機能、ショッピンカート、支払い機能)
    ユーザ行動に対する動詞になる
  • 認知パターン
    プロダクトのブランドに基づいて決まるパターン
    (口調、タイポグラフィ、色、アイコン、余白、レイアウト、形状)
    ユーザ行動に対する形容詞になる
  • ユーザーフローパターン
    ユーザーフロー(ユースケース)に基づいて決まるパターン
    (入力フォームの失敗メッセージや成功メッセージの出し方)
  • プロジェクト固有のUXパターン
    ABテストなどの計測に基づいて決まるパターン
    (入力フォームのファーストビューにはアクションボタンを入れる)

認知パターン補足
認知パターンがないと似たような機能になる
f:id:uggds:20190712093000p:plain f:id:uggds:20190712093016p:plain 認知パターンを使用することでユーザの関心をひき、行動を促したり、タスクを容易にしたり、達成感をコントロール感を与えることができる。

直感的に理解できるようになっているかが重要

共通言語
チームで作業している場合、プロダクトの開発に携わるメンバー間で言語を共有する必要がある。

「ボタン」とは?
クリックできる領域?
どこかにリンクされているページ上のインタラクティブな要素?
ユーザーデータを送信できるフォーム要素?

言語に関する取り決めについて話し合い、審査し、明文化することで共有言語を確立してからインターフェースについて考える。
それに加えて、ユーザー側がそれをどう解釈するかもさらに合わせて考える。

パターンライブラリ
デザインパターンを一覧化したもの、ツール

Webのデザインシステムでは以下を一覧化したものをさす

メンテナンスされ続けること必要

デザインシステムで明文化すべきこと

①プロダクトの目的と価値
Webサイトの対象ユーザーとその目的、ニーズ、動機を理解する。

②解決したい課題
デザインで何を解決しようとしているのかを明らかにしておく。

③デザイン原則
プロダクトの目的を表現する基盤となる原則を確立する。
プロダクト作成に関わる人々が価値に賛同し、その実現に尽力することが目的。

測定や数値化ができないので、定義は反復作業しながら徐々に作られていく。

良いデザイン原則の共通した特徴

  1. 真実で本質
    例えば「シンプル、便利、楽しい」という原則の場合、このプロダクトにおけるシンプルとは何か?などの答えが導かれていること
  2. 実用的かつ実行可能
    「シンプル、便利、楽しい」を明文化した場合、それが実行可能であること
  3. 視点(POV)がある
    「シンプル、便利、楽しい」のうち、どれを優先させるかはっきりさせるための視点があること
  4. 関連付けやすく、覚えやすい
    多くても覚えられないので、4~5点くらいに抑えていること

作り方の例

  • プロダクトの目的から作る
  • メンバーのすでにある共通認識から作る
  • ターゲットに注力して作る
  • 検証して原則を進化させる

④どうやって機能パターンを切り出すか
目的達成に向けて、主にどのような行動をユーザーに促したいかを考え、どの粒度でパターンを分割をするか。 (写真をアップしてもらう、いいねを押してもらう)

作り方の例

  • カスタマージャーニーから促したい行動のパターンマップを作る
  • インターフェースインベントリーを作成する

命名にはパターンを行為で捉える
「イメージヘッダー」「バナー」ではなく
 →「〇〇を宣伝する」
  →「広告看板」
   →「Billboard」という名称

パターンの中身を考える
 →どんな要素が必要か(見出し、CTA、目を引く画像)

パターンをスケールで比較する
 →パターンの大小が間違っていて行動の妨げになっていないか
 →PC用とスマホ用を考える

⑤どうやって認知パターンを切り出すか
誰にどのように認知して欲しいかについて考える。
(華やかで洗練されたもの?、真面目な雰囲気?、遊び心を盛り込む?)

さらに、それを実現する手段についても考える
(手書き風?イラスト?写真?ピンク一色?白黒?)

作り方の例

  • ムードボードを作成する
  • スタイルタイルを作成する
  • 要素コラージュを作成する
  • 反復と再調整

ブランドを守る時の注意点
一貫性のバランスをうまくとる
 →一貫性を守りすぎてブランドを崩さないように

ビジネス要件のバランスをうまくとる
 →ビジネス要件によってブランドにそぐわない要素をその場しのぎで入れてしまう
  →効果があった場合にブランドに合わせた変更がしずらい

⑥共通言語とデザインパターンの共有方法
上記で考えた機能パターンと認知パターンをどうやって、チームで共有するか

作り方の例

  • チームで命名する
  • 導入研修に取り入れる
  • 用語集を作る・維持する

感想

他社ではどうやっているかなど、想像以上に効果的でした。

本を読みながら、うちはこうだよね!とか、これができてないよね!とかが話せてとても効果的でした。

ここでまとめたことは、本のたった半分の「基本編」だけです。
「応用編」では実際にどうやって作るのかが具体的に記載されていて、一読の価値ありです。

実際どうやって進めたかは以下の記事にまとめました。
参考になれば幸いです。

ugap.hatenablog.com

フロントエンドエンジニアからはじめるデザインシステム

フロントエンドエンジニアの立場から「デザインシステム」をつくることができたので、その作成プロセスとできたデザインシステムをご紹介します。

「デザインシステム」とは

あるプロダクトのデザインに関するルールを定義し、そのルールに則ってプロダクトをデザインしていく仕組みのことです。

具体的には

  • どうやってデザインするか(フォントや色や配置などの決め方)
  • どうやって繰り返し使えるようにパーツを分割するか (ヘッダーやフッター、ボタンなどのパーツ分割の仕方)
  • 何を基準にそれを更新していくのか
  • どうやって関係者全員がそれを理解している状態にするか

これらを仕組み化したものです。

簡単な例だと、みなさんもパワポでプレゼン資料を作るとき、

「タイトルはこのフォントやサイズや色を使って」
「コンテンツはこのフォントサイズで」
「使うオブジェクトの角は丸くして」
「フッターにはこのロゴを置いて」

などを考えるのではないでしょうか。 それがページが変わる度に位置も余白もフォントも色も形もバラバラではまずいことはお分かりかと思います。

引き継いだパワポの体裁がバラバラで、地獄の修正作業をした人もいるのではないでしょうか。

こういうときに作成者全員がルールを守れるようにする仕組みをつくると思います。

会社のプレゼン資料ではブランド毀損がないようにテンプレートを作っている会社もありますよね。

ただ、テンプレートを使っていても、テンプレートにない表現をしたいときはどうしていますか?パワポのデフォルトのままだと、これまでの体裁に合わないのはわかっているけど、どうしたらよいかわからないのでデフォルトのまま貼り付けたことはないでしょうか。他にも画像の背景を透過にせず、白いままにして台無しにしていることはないでしょうか。
それがデザインの体裁崩壊の始まりです。

こういう時のためにデザインの方針を決めておき、それに則ってパーツをつくり、さらに他の人が使えるようにテンプレートに組み込むまでを仕組み化することが「デザインシステム」といえます。

Webサービス開発におけるデザインの保守は難しい

パワポの場合でも容易に崩壊してしまいますが、Webサービスの開発ではその規模も大きく、複数人で作業するため、そのルールを守り続けることはさらに難しいです。 また、デザインの崩壊に関しては、プレゼン資料の場合はそれほど社会的影響度は低いかもしれませんが、Webサービスの場合はその影響度は高く、ビジネスを揺るがす可能性もありあます。

そこで近年ではWebサービス開発の現場に「デザインシステム」を導入することが注目されています。 AirbnbやTEDなどの多くの企業はすでに「デザインシステム」を導入しています。

airbnb.design

だが「デザインシステム」をつくることも難しい

ならばデザインシステムをつくろうと思ったとき、デザイナーの方が頑張って原則からルールを定めてチームに展開することがあります。 しかし、Webサービス開発ではそれをフロントエンドエンジニアが「実装」し、コードを「管理」しなくてはなりません。

作成されたデザインがいかにルールに則っていても、フロントエンドエンジニアはどの粒度で、どう管理していいのかわからず頭を悩ませます。

そういった現状を踏まえ(たわけではないのですが)、今回フロントエンドエンジニアの立場からデザインシステムをつくることができたのでその作成プロセスとできたデザインシステムをご紹介します。

お話しの前提

  • サービスは昔からあり、ページは数十ページある
  • 体裁が揃っていないページが多くチーム内では改善したい意欲がある

開発フロー

開発フロー

  • ディレクター:4人〜7人
  • デザイナー: 2人
  • フロントエンドエンジニア:2人
進め方
  • デザイナーはページ単位でデザインカンプを作る
  • エンジニアはそれをコンポーネントに分割する
  • ルールに厳密ではなく、ルールに外れた場合は次の開発で修正しにいく

※カンプとは、サイトのイメージをすり合わせるために作成される完成見本図のこと。
コンポーネントとは、ボタンなどのページを構成するパーツのこと。

使用技術

  • Vue.js(もちろんReactでもよい)
    コンポーネント指向のJavaScriptフレームワーク
  • Storybook
    コンポーネントを一覧化するツール
  • Sketch
    WebページやアプリのUIなどをデザインするためのツール
  • Abstract
    デザイン作業を複数のデザイナーで同時に行ったり、デザインカンプを共有するためのツール

話さないこと

エンジニアからはじめたデザインシステム

コンポーネントの分割

はじまりはデザインシステム云々の前に、vueを使ったコンポーネント指向のUI開発をしていて、どういう風にコンポーネントを分割するのがよい粒度なのか?という疑問を解決することからでした。

そこで行き着いたのはAtomicDesignという考え方です。

ugap.hatenablog.com

Atomic Design はUIを構築するための方法論でしかないので、デザインや実装方法、運用方法は独自に考えました。
実際に導入してみるといくつか乗り越えなくてならないハードルが存在しましたが、今はその設計ルールを使ってうまく回っています。

どいう風にコンポーネントを分割したかについては以下の記事にまとめています。

ugap.hatenablog.com

これにより、コンポーネントの粒度に関してはフロントエンドエンジニアは迷わなくなりました。

コンポーネントの一覧化

今度はコンポーネントが増えてくると探すのが大変になりました。
そこで、Storybookを導入しました。

storybook.js.org

このツールは、デザインパターンおよびその使用方法についての原則やガイドラインを収集、格納、共有するツールです。
ReactやVue.jsを使用しているプロジェクトではおすすめです。

デザイナーを巻き込む

エンジニア内では、AtomicDesignの概念によってうまくコンポーネントを分けることができるようになりました。

ただ、デザイナーから渡されるデザインカンプをみると、担当のデザイナーさんによって微妙に違うパーツがあり、同じ目的でつかうものなのか、違う目的で使い分けが今後必要なのかなど、デザインの意図と目的がわからないことがありました。

例えば、ページによって異なる余白など。
f:id:uggds:20190630122738p:plain:w250

とりあえず言われたまま作っていると同じコンポーネントだがデザインが違うパターンが複数できあがっていくという課題が発生していました。

そこで、デザイナーさんを含めて課題の認識合わせを行うことにしました。

「Design Systems」輪読会

そもそも、私が何をやろうとしているか、何を目指しているのかをデザイナーとフロントエンドエンジニアに伝えたく、「Design Systems」という本を輪読しようともちかけました。

ugap.hatenablog.com

他社ではどうやっているかなど、やりたいこと以上のことが書かれていて私が熱弁するより効果的でした。

みんな賛同してくれ、業務時間内で毎週1時間をつかって1章ずつ声に出してよみました。

実際、毎週1時間1章ずつできました。
全10章なので10週で終わります。

本を読みながら、うちはこうだよね!とか、これができてないよね!とかが話せてとても効果的でした。

f:id:uggds:20190629235947j:plain:w300
輪読会の様子

「デザインシステム会」を発足

その後、輪読会をしていたメンバー(デザイナーとフロントエンドエンジニア)でデザインシステム会をつくりました。 輪読会で気づいたデザインシステムを導入する上でやらなければならないことを洗い出したり、新しいパーツについて話し合う会です。

具体的には

本の指南もあり、やらなきゃいけないことが割とスムーズにだせたかと思います。

もちろん、この会はいま続いております。

チャットの専用チャンネルを作る

チャット上にデザイナーとエンジニアでコンポーネントに関するやりとりをするための専用チャンネルをつくりました。
疑問に思ったらそこで会話をします。特に名称を決めるときによく使います。

ディレクターを巻き込む

デザイナーとエンジニアで育てたStorybookはそのメンバーがいなくなったあとでも更新されていなくてはなりません。
Storybookを利用したデザインシステムが関係者全員に溶け込んでもらう必要がありました。

なので、ディレクターにもStorybookをみる習慣をつけられないかと考えました。
「Storybookを見てください」ではダメなので、どう習慣化するかがポイントです。

もともとディレクターがつくったワイヤーフレームに以下のような課題がありました。

  • 他のページではこういう表現だが、ここは別の表現になっている
  • そのページに複数の表示パターンがあることが考慮されていない

デザイナーやフロントエンドエンジニアが指摘をすることが多いのですが、指摘し忘れた場合は後ろの工程で気づくことになり、デザインや実装を止めてしまうこともありました。

この課題を解決するのにStorybookを活用してもらうことを思いつきました。

Storybookにページに関する全ての情報を記載する

先ほどの問題は、ページにいまどのような施策があるのかが可視化できていないのが一番の原因だと思いました。
ただし、それはwikiとかではなく、デザインされたものの近くに書いていないとおそらく誰もみてくれません。

そこで、Storybookのnotesというaddonを導入しました。
storybook/addons/notes at next · storybookjs/storybook · GitHub

Storybookのv5では導入するとプレビューのすぐ横にタブが設けられ、その中は自由にマークアップすることができます。
f:id:uggds:20190630004041p:plain:w300

そして、そこにはページに関する全ての情報を記載するようにします。

例えば以下のような情報です。

  • URL
  • 使用目的
  • 表示パターン
  • ABテスト状況
  • 実装注意事項

また、ディレクターと話し、開発のフローも少し変更しました。

  1. 案件企画担当者はNotesの内容をコピー
  2. 自分の案件で更新があるところを加筆・修正する
  3. 要件が書かれたドキュメントに添付する
  4. エンジニアはStorybookを更新する
  5. テスト時にディレクターはStorybookが更新されていることも確認する

これによってディレクターは案件作成時にそのNotes(Storybook)をみる習慣ができ、 Storybookも常に最新の状態になるようになる仕組みができました。

副次効果として会話もStorybookにある言葉でされ始めます。デザイナーとエンジニア間では名称はすでに合わせているので後ろの工程もよりスムーズになります。

出来上がったデザインシステム

以下が現場の慣習に合わせてつくった「デザインシステム」です。

どうやってデザインするか

残念ながらデザインのコンセプト・原則を決めたり、デザインコンセプトからデザインする作業は完全にデザイナーさんにお任せしていて、 どうしてその色にしたのか、どうしてそのフォントサイズにしたのかなどの作成フローはまだ私の中で言語化できていません。(いずれできるようになりたい)

そういった意味ではデザイナーのスキルが高くないとデザインをシステム化するのは難しいと思いました。

フロントエンドエンジニアとしてはその決められたカラーやフォントサイズを定数として定義し、
それ以外のカラーやフォントサイズ、余白などを実装で使うことを原則禁止するということをやりました。
また、Storybookにカラーパレットを作ったり、そういった情報をいつでも見られるようにもしました。

どうやって繰り返し使えるようにパーツを分割するか

目的達成に向けて、どのような行動をユーザーに促したいかが焦点になります。
私は先述したAtomicDesignの考え方にこれらを落とし込んでおり、それを使って分割しています。

記事に書いたことを抜粋すると、以下のように分割しています。

Atoms(原子)
* リンクやボタンやフォームのパーツ単位など UI の最小要素
* 見た目に関することはこのモジュールで表現する
* PowerPointの一つの図形で表現できるもの
ラジオボタン・セレクトボックスなどのフォームは例外)
Molecules(分子)
* AtomsとMoleculesから構成されるグループで、比較的小さいコンポーネント
* 中身の文言や配置を変えることで使い回しが可能なもの
* 別のOrganismsを跨いで出現するもの、または、これから出現することがわかっているもの
* PowerPointの図形をグループ化して表現するもの
Organisms(生命体)
* AtomsとMoleculesから構成されるコンポーネント
* 広告のバナーのように、どのページに配置しても意味がわかる独立したコンポーネント
* デザイン上初めてでてくるもので、使い回すかどうか不明なもの。(未知の生命体)
* 使い方が限定的なもの。
* PowerPointの図形をグループ化して表現するもの。

ただ、これは一つの指標なので、デザインシステム会で話し合った結果、階層をかえることはありえます。

よく機能パターンの洗い出しには、「ユーザーの行動を分析して」とか「ユーザーストーリーマッピングをつくって」などがありますが、 開発スピードが遅くなってしまうし、時間もなかったのでやりませんでした。

いかに迷わず開発者が開発できるかが重要なポイントだと思います。

何を基準にそれを更新していくのか

ルールは厳密ではなく、間違えていたら次それを修正していくスタイルなのですが、
なるべくそうならないように下の2つの会議でレビューを行なっています。

  • レビュー会
    ディレクター/デザイナー/フロントエンドエンジニアの3者が集まってUIのレビューを行う。
    主に要件の筋がよいか、UI/UXに問題がないか、結果どうだったかを話す。

  • デザインシステム会
    以下を話し合う。

    • 新規のパーツがどういう機能か
    • つくったコンポーネントや重複はないか、名称は馴染んでいるか
    • 何をシンボル化するか、使い回す予定かどうかの確認
    • デザイナーのSketchとコンポーネントの粒度に同期がとれているか

この2つの会を通して更新を行っています。

どうやって関係者全員がそれを理解している状態にするか

開発のフローにStorybookを置くようにしました。
また、Storybookの更新が滞らないようにするように考えました。

①企画

  • StorybookのNotesにあることに目を通し表示パターンなどを確認する
  • Notesの更新を要件に加える

②デザイン

  • デザインコンセプトにそってデザイナーはページやパーツをデザインする
  • 完成したら担当ディレクターと担当エンジニアの両方に確認してもらう

③実装

④テスト

  • ディレクターとデザイナーが確認する
  • ディレクターはStorybookに書かれていることも確認する

関係者全員がStorybookに目を通すようにしました。
「あのページが見れなくなってる」など、ディレクターからエスカレーションがあるのは嬉しい悲鳴です。

まとめ

フロントエンドエンジニアからデザインシステムを考えてみたら意外とすんなりモノゴトが進んだと感じました。

結論として、デザインシステムを始めるならフロントエンドエンジニア側から考えるのがいいのでは?と思いました。

なぜかというと理由は2つあります。

1つ目は
「どうやって分割するか」はエンジニアが考える作業 になると思うからです。

デザイナーがコンポーネントを組み上げてページをデザインするのはとても難しいことだそうです。 デザイナーはページ全体から詳細を整えていく作業をするからです。
つまり、コンポーネント分割はデザインカンプを渡された後のエンジニアの担当になると思います。

今回はそこが先にクリアになっていたのがよかったのかなと思いました。
逆にクリアになっていないままデザインシステムをやろうとしても悩むことになると感じました。

2つ目は
いまある実装で急に「コンポーネント一覧ツールを用意せよ」と言われてもエンジニアは大変だからです。
コンポーネント一覧ツール(パターンライブラリ)なしではデザインシステムは難しいと言われていますが、使用技術によっては使える使えないがありツールの選定に時間がかかります。
しかも、それをメンテナンスされるように開発フローに取り込まないといけません。

今回はStorybookが使えるようにするために技術選択をしてきたところもあるので、何か実装手段を変える必要はありませんでしたが、
KSSSC5 StyoeGuideなど、これまでにいろいろ試した経緯があります。 自分たちの開発スタイルにあったものを選ぶまで時間がかかりました。

この2つがデザインシステムを始めるならフロントエンドエンジニア側から考えるのがいいのでは?と思っている理由です。


デザインシステム導入はコミュニケーションも活発になり「正しくものをつくっている」感があって、とても安心して開発ができるようになりました。
デザインがどうではなく、Webサービス開発において重要な仕組みではないでしょうか。

ここに書いたことはもちろん体制によって当てはまらないかもと思いますが、デザインシステム導入をお考えのプロジェクトの参考になれればと思います。

Atomic Designの実装例 〜Atomic Designを使ったコンポーネント指向のUI開発:Q〜

本稿は(序)(破)(Q)のシリーズの3番目の記事になります。

本稿では前回(破)で説明したAtomic Designを導入する際に工夫した点をふまえた実装例をJSフレームワークを使用する場合使用しない場合の2つの場合について紹介します。

シリーズ(序)ではAtomic Designの概要
シリーズ(破)ではAtomic Designの導入に際して工夫した点

について説明していますので、そちらをご覧ください。

実装例題材

下のサイトテンプレートを題材に実装していきます。

https://html5up.net/prologue

f:id:uggds:20180717000632p:plain

シチュエーションとしては、デザイナーからもらったデザインカンプをエンジニアが実装する想定で説明します。

コンポーネントの分割

エンジニアはデザインカンプをAtomic Designのコンポーネント単位に分割していきます。

コンポーネントの分割フロー図は(破)で以下のように定義しました。

f:id:uggds:20180717004055p:plain

まずは、ページをヘッダーやフッター、大きなセクションで分割します。
分割したコンポーネントはOrganismsになります。

f:id:uggds:20180716214347j:plain

それぞれをさらに分割していきます。 f:id:uggds:20180717001248j:plain f:id:uggds:20180717001410j:plain f:id:uggds:20180717001446j:plain f:id:uggds:20180717001504j:plain f:id:uggds:20180717001532j:plain

※「使いそう」という表現を使っていますが、実際は 「他のページやコンポーネント内で既に繰り返し使っている」または「これから繰り返し使うことがわかっている」状態でなければMoleculesに分類する必要はありません。迷ったらOrganismsにします。
今回、Moleculesに分類するコンポーネントが無くなってしまうためいくつかをMoleculesに分類しました。

実装

コンポーネント分割ができたら実装していきます。

フレームワークを使用する場合

f:id:uggds:20180722233533p:plain

今回実装で使用する主要な技術セットは以下になります。

  • nuxt: ^1.0.0
  • vue-styled-components: ^1.2.3"
  • @storybook/vue: ^3.4.8

筆者の事情によりNuxt.js を使用して実装していきますが、ReactでもVue.jsでも問題ありません。

Nuxt.js はユニバーサルな Vue.js アプリケーションを構築するためのコンポーネント指向のフレームワークです。
ここでは詳しい説明については割愛しますので公式ページを参照ください。

ja.nuxtjs.org

スタイリングにはstyled-componentsを導入しています。
Google TrendでCSS Modulesを抑えて近年急上昇している技術です。

これまでのスタイルリングはcssの定義をclass属性(className属性)とのマッピングによって行ってきましたが、styled-componentsはコンポーネントに「スタイル」の定義も持たせられるようにしたライブラリです。
これにより、コンポーネントをよりカプセル化しやすくなりました。

詳しくは公式ページで。(アイコンが印象的)
www.styled-components.com

Storybook は コンポーネント のスタイルガイドを作成するためのツールです。(破)で説明したように仕分けたコンポーネントは一覧化しないと開発がやりづらくなります。Stroybookはコンポーネントを一覧化するツールです。

https://storybook.js.org/

環境構築

まずは、Nuxtのプロジェクトテンプレートを構築します。

$ npm install -g vue-cli
$ mkdir AtomicDesignProject
$ cd AtomicDesignProject
$ vue init nuxt-community/starter-template src
$ cd src
$ yarn install

起動確認します。

$ yarn run dev

http://localhost:3000/

f:id:uggds:20180718213931p:plain

次にストーリーブックをインストールします。

$ npm i -g @storybook/cli
$ getstorybook

デフォルトではstoriesディレクトリ配下にxxx.story.jsファイルを作成していく設定ですが、vueファイルと同じディレクトリに作成する運用にしたいのと、storyファイルは一律stories.jsにしたいため、.storybook/config.js の中を以下のように書き直します。

 // automatically import all files ending in *.stories.js
-const req = require.context('../stories', true, /.stories.js$/);
+const req = require.context('../components', true, /stories.js$/);
 function loadStories() {
   req.keys().forEach(filename => req(filename));
 }

確認のため、Nuxt.jsプロジェクトを作成した時にサンプルとして作成されるAppLogo.vueファイルのストーリーファイルを作成してみます。

./src
├── README.md
├── assets
├── components
│   ├── AppLogo.vue
│   ├── stories.js     <--- 作成
│   └── README.md
├── layouts
├── middleware
├── node_modules
├── nuxt.config.js
├── package.json
├── pages
├── plugins
├── static
├── store
└── yarn.lock

stories.jsの中身は以下になります。

import { storiesOf } from '@storybook/vue'
import AppLogo from './AppLogo.vue'

storiesOf('AppLogo', module)
  .add('default', () => ({
    components: { AppLogo },
    template: `<AppLogo></AppLogo>`
  }))

起動して確認してみます。

$ yarn run storybook

http://localhost:6006/

f:id:uggds:20180718223730p:plain

左のタブにAppLogoコンポーネントのラベルが表示されています。
キャプチャではわかりませんがタブをクリックするとAppLogoに仕込んであるアニメーションが正常に作動します。

次にstyled-componentsをインストールします。

$ yarn add vue-styled-components

試しにAppLogo.vueをstyled-componentsでスタイリングしてみます。

-  <div class="VueToNuxtLogo">
-    <div class="Triangle Triangle--two"/>
-    <div class="Triangle Triangle--one"/>
-    <div class="Triangle Triangle--three"/>
-    <div class="Triangle Triangle--four"/>
-  </div>
+  <VueToNuxtLogo>
+    <TriangleTwo/>
+    <TriangleOne/>
+    <TriangleThree/>
+    <TriangleFour/>
+  </VueToNuxtLogo>

まずはマークアップ部分ですが、class属性をもつdiv要素ではなく全てコンポーネントのタグにしました。

- <style>
- .VueToNuxtLogo {
-   display: inline-block;
-   animation: turn 2s linear forwards 1s;
-   transform: rotateX(180deg);
-   position: relative;
-   overflow: hidden;
-   height: 180px;
-   width: 245px;
- }
- 
- .Triangle {
-   position: absolute;
-   top: 0;
-   left: 0;
-   width: 0;
-   height: 0;
- }
- 
- .Triangle--one {
-   border-left: 105px solid transparent;
-   border-right: 105px solid transparent;
-   border-bottom: 180px solid #41B883;
- }
- 
- .Triangle--two {
-   top: 30px;
-   left: 35px;
-   animation: goright 0.5s linear forwards 3.5s;
-   border-left: 87.5px solid transparent;
-   border-right: 87.5px solid transparent;
-   border-bottom: 150px solid #3B8070;
- }
- 
- .Triangle--three {
-   top: 60px;
-   left: 35px;
-   animation: goright 0.5s linear forwards 3.5s;
-   border-left: 70px solid transparent;
-   border-right: 70px solid transparent;
-   border-bottom: 120px solid #35495E;
- }
- 
- .Triangle--four {
-   top: 120px;
-   left: 70px;
-   animation: godown 0.5s linear forwards 3s;
-   border-left: 35px solid transparent;
-   border-right: 35px solid transparent;
-   border-bottom: 60px solid #fff;
- }
- 
- @keyframes turn {
-   100% {
-     transform: rotateX(0deg);
-   }
- }
- 
- @keyframes godown {
-   100% {
-     top: 180px;
-   }
- }
- 
- @keyframes goright {
-   100% {
-     left: 70px;
-   }
- }
- </style>
+ <script>
+ import styled from 'vue-styled-components'
+ 
+ const VueToNuxtLogo = styled.div`
+   display: inline-block;
+   animation: turn 2s linear forwards 1s;
+   transform: rotateX(180deg);
+   position: relative;
+   overflow: hidden;
+   height: 180px;
+   width: 245px;
+   @keyframes turn {
+     100% {
+       transform: rotateX(0deg);
+     }
+   }
+ `
+ const goright = `
+   @keyframes goright {
+     100% {
+       left: 70px;
+     }
+   }
+ `
+ const godown = `
+   @keyframes godown {
+     100% {
+       top: 180px;
+     }
+   }
+ `
+ const Triangle = styled.div`
+   position: absolute;
+   top: 0;
+   left: 0;
+   width: 0;
+   height: 0;
+ `
+ const TriangleOne = Triangle.extend`
+   border-left: 105px solid transparent;
+   border-right: 105px solid transparent;
+   border-bottom: 180px solid #41B883;
+ `
+ const TriangleTwo = Triangle.extend`
+   top: 30px;
+   left: 35px;
+   animation: goright 0.5s linear forwards 3.5s;
+   border-left: 87.5px solid transparent;
+   border-right: 87.5px solid transparent;
+   border-bottom: 150px solid #3B8070;
+   ${goright}
+ `
+ const TriangleThree = Triangle.extend`
+   top: 60px;
+   left: 35px;
+   animation: goright 0.5s linear forwards 3.5s;
+   border-left: 70px solid transparent;
+   border-right: 70px solid transparent;
+   border-bottom: 120px solid #35495E;
+   ${goright}
+ `
+ const TriangleFour = Triangle.extend`
+   top: 120px;
+   left: 70px;
+   animation: godown 0.5s linear forwards 3s;
+   border-left: 35px solid transparent;
+   border-right: 35px solid transparent;
+   border-bottom: 60px solid #fff;
+   ${godown}
+ `
+ 
+ export default {
+   components: {
+     VueToNuxtLogo,
+     TriangleOne,
+     TriangleTwo,
+     TriangleThree,
+     TriangleFour
+   }
+ }
+ </script>

次に<style>タグを全て削除し、代わりに<script>タグの中にTriangleOneTriangleFourといったスタイリングされたコンポーネントを作成しています。

styled-componentsを用いることでclass属性に対してスクレイピング的に行っていたスタイリングからコンポーネントに閉じ込める形で定義することができました。

※vue.jsにはスコープ付き CSSというスタイルをコンポーネントに閉じ込める方法がありますが、React でもstyled-componentsは使用することができるため、React <--> Vue に移行する場合に技術的差異が少なくすむ狙いもあってstyled-componentsを採用しています。

説明が長くなりましたが開発環境が整ったので、あとは先ほど仕分けしたAtomic Designコンポーネントを実装していくだけです。

完成後のcomponentsディレクトリは以下のようになりました。

./components/
├── atoms
│   ├── Button
│   │   ├── index.vue
│   │   └── stories.js
│   ├── InputText
│   │   ├── index.vue
│   │   └── stories.js
│   └── TextArea
│       ├── index.vue
│       └── stories.js
├── molecules
│   ├── Card
│   │   ├── index.vue
│   │   └── stories.js
│   ├── Profile
│   │   ├── index.vue
│   │   └── stories.js
│   └── Sns
│       ├── index.vue
│       └── stories.js
└── organisms
    ├── AboutMe
    │   ├── index.vue
    │   └── stories.js
    ├── Contact
    │   ├── index.vue
    │   └── stories.js
    ├── Footer
    │   ├── index.vue
    │   └── stories.js
    ├── Header
    │   ├── index.vue
    │   └── stories.js
    ├── Hero
    │   ├── index.vue
    │   └── stories.js
    ├── Main
    │   ├── index.vue
    │   └── stories.js
    ├── Menu
    │   ├── index.vue
    │   └── stories.js
    ├── MenuItem
    │   ├── index.vue
    │   └── stories.js
    ├── Portfolio
    │   ├── index.vue
    │   └── stories.js
    ├── PortfolioCards
    │   ├── index.vue
    │   └── stories.js
    └── Side
        ├── index.vue
        └── stories.js

Storybookは次のようになりました。
※Storybookにstorybook-addon-vue-infoというアドオンを適用しています。

f:id:uggds:20180719010530p:plain

Nuxt.jsとstyled-componentsとStorybookを使って、スタイルを閉じ込めたコンポーネントとそれらのコンポーネント一覧を作成することができました。

vueファイルとstoryファイルの両方を修正していく運用になります。

フレームワークを使用しない場合はどうする?

ReactやVue.jsといったコンポーネント指向のフレームワークを使用していない場合はこれまで通り、HTMLをマークアップし、class属性に対してCSSでスタイリングをしていくことになるかと思います。

現場によると思いますが、将来的にReactやVue.jsといったフレームワークを使用することになる可能性は十分あります。その場合でもスムーズに移行できるように共通のデザインシステムを使っておくべきかと考えます。

そのためには、Atomic Designを取り入れたCSS設計手法が必要になるのですが、目ぼしいものは見当たりません。
そこで、有名なCSS設計手法の一つであるFLOCSSをベースにAtomic Designの考え方を取り入れたCSS設計を考えました。

FLOCSS とは数あるCSS設計手法のひとつで、OOCSSやSMACSS、BEM、SuitCSSなどのメジャーな設計手法のいいとこどりをした国産の設計手法です。

https://github.com/hiloki/flocss

以下でそのAtomic DesignとFLOCSSを組み合わせたCSS設計手法について説明します。

Atomic Design + FLOCSS (AFLOCSS)

ファイル・ディレクトリ構成

下記のような構成とします。

./css/
├── foundation
├── layout
│   └── template
└── object
    ├── atoms
    ├── molecules
    └── organisms

Foundation

Reset.cssやNormalize.cssなどを用いたブラウザのデフォルトスタイルの初期化や、プロジェクトにおける基本的なスタイルを定義します。 ページの下地としての全体の背景や、基本的なタイポグラフィなどが該当します。 - FLOCSSより引用

Layout

ページを構成するヘッダーやメインのコンテンツエリア、サイドバーやフッターといったプロジェクト共通のコンテナーブロックのスタイルを定義します。 基本的には、ページ単位で唯一の存在である要素となるため、Layoutレイヤーの要素ではIDセレクタを採用することも可能です。 - FLOCSSより引用

Atomic DesignではTemplatesにあたるため、この階層にTemplateファイルを作成します。

Object
FLOCSSではプロジェクトにおける繰り返されるビジュアルパターンをすべてObjectと定義します。 AFLOCSSでのObjectでは、Object配下がAtoms, Molecules, Organismsの3つのレイヤーに分けられます。
Utilityはすべてmodifierで表現できると考えられるため原則なくなります。

命名規則

MindBEMding

BEM(MindBEMding)のシンタックスである、Block、Element、Modifierに分類して構成される規則を採用します。
Modifierの命名の派生パターンとして、JavaScriptで操作されるような「状態」を表すようなModifierについては、SMACSSのStateパターンの命名を拝借し、is-*プレフィックスを付与し、.is-activeというようにすることもできます。 このアイデアを採用する場合の原則として、.is-activeそのものにルールを持たせるのは禁止します。これは .is-activeそのものが持つルールが、 他のモジュールのModifierのスタイルを汚染してしまうのを防ぐためです 。
- FLOCSSより引用

プレフィックス
役割を明確にするためにプレフィックスをつけます。

  • Atoms - .a-*
  • Molecules - .m-*
  • Organisms- .o-*
  • Templates - .t-*

今回の題材ではapp.scssのようなファイルは次のようになりました。

// ==========================================================================
// Foundation
// ==========================================================================

@import "foundation/_reset";
@import "foundation/_base";

// ==========================================================================
// Layout
// ==========================================================================

@import "layout/_template";

// ==========================================================================
// Object
// ==========================================================================

// -----------------------------------------------------------------
// Atoms
// -----------------------------------------------------------------

@import "object/atoms/_button";
@import "object/atoms/_inputText";
@import "object/atoms/_textArea";

// -----------------------------------------------------------------
// Molecules
// -----------------------------------------------------------------

@import "object/project/_card";
@import "object/project/_profile";
@import "object/project/_sns";

// -----------------------------------------------------------------
// Organisms
// -----------------------------------------------------------------

@import "object/utility/_aboutMe";
@import "object/utility/_contact";
@import "object/utility/_footer";
@import "object/utility/_header";
@import "object/utility/_hero";
@import "object/utility/_main";
@import "object/utility/_menu";
@import "object/utility/_menuItem";
@import "object/utility/_portfolio";
@import "object/utility/_portfolioCards";
@import "object/utility/_side";
カスケーディングと詳細度

原則、以下を禁止事項とします。

  • モジュール間のカスケーディング
  • 他のモジュールを親とするセレクタを用いたカスケーディング
  • 同一レイヤーにおけるモジュール間のカスケーディング

そのレイヤーにおいて、特定のモジュールに依存することなく、モジュールとして独立して再利用できるべきであり、混在させることによって他の開発者が予想しない挙動になるべきではないためです。

// Atoms
.a-link .a-button {
  ...
}

// Molecules
.m-card .m-sns {
  ...
}

// Organisms
.o-hero .o-aboutMe {
  ...
}

例外として、レイヤー間におけるカスケーディング、例えば、MoleculesレイヤーがAtomsレイヤーのモジュールを変更することは許容します。
ただし、このような例であってもセレクタのカスケーディングをおこなう必要はなく、Modifierによって拡張することによって解決することができる場合があります。

コンポーネント一覧化

ReactやVue.jsフレームワークを使用しない場合はStorybookが使えません。
そのため、それに代わるコンポーネント一覧ツールが必要になります。

※最新版のStorybook v4.0.0-alpha.14ではフレームワークを使用しないStorybook for HTMLというものがサポートされていますが、sassのようなプリプロセッサとの併用に関するドキュメントが少ないため導入検討中です

そこでsc5というCSSスタイルガイドジェネレーターを使用します。

styleguide.sc5.io

スタイルガイドジェネレータは数多くあるのですが、sc5はCSSに決められたフォーマットでコメントを書くだけでスタイルガイドが生成できるため簡単に始められます。

インストールにはgulpが必要になります。

$ yarn add -D gulp gulp-sass styleguide

gulpfile.jsを作成します。

var gulp = require('gulp');
var styleguide = require('sc5-styleguide');
var sass = require('gulp-sass');
var outputPath = 'output';
 
gulp.task('styleguide:generate', function() {
  return gulp.src('*.scss')
    .pipe(styleguide.generate({
        title: 'My Styleguide',
        server: true,
        rootPath: outputPath,
        overviewPath: 'README.md'
      }))
    .pipe(gulp.dest(outputPath));
});
 
gulp.task('styleguide:applystyles', function() {
  return gulp.src('main.scss')
    .pipe(sass({
      errLogToConsole: true
    }))
    .pipe(styleguide.applyStyles())
    .pipe(gulp.dest(outputPath));
});
 
gulp.task('styleguide', ['styleguide:generate', 'styleguide:applystyles']);

scssファイルに以下のようなコメントを記述します。

// Button
//
// ボタン
//
// default - Default Button
// a-btn--accent - Accent Button
// a-btn--primary - Primary Button
//
// markup:
// <div class="a-btn {$modifiers}">{$modifiers}</div>
//
// Styleguide 1.1.0
.a-btn {
  ...
  &:hover {
    ...
  }
  &--accent {
    ...
  }
  &--primary {
    ...
  }
}

最後にpackage.jsonを修正します。

  "scripts": {
    ...
+    "styleguide": "gulp styleguide"
  },

実行します。

$ yarn run styleguide

http://localhost:3000/
ポート番号はオプションで変えられます。

f:id:uggds:20180722124115p:plain

scssファイルのコメントに記載した番号が階層を表しているので、
下のように採番してAtoms、Molecules、Organismsでカテゴライズしています。

// Atoms
// Styleguide 1.0.0

// Button
// ...
// Styleguide 1.1.0

// Molecules
//
// Styleguide 2.0.0

// Organisms
//
// Styleguide 2.0.0

このようにscssファイルの実装とそのコメントを修正していく運用になります。
スタイルガイドは実装とは別ファイルで管理されることが多くて更新が滞ってしまいがちですが、これなら実装と結びついているため更新が滞ることが少ないかと思います。

(Q)のまとめ

フレームワークを使用する場合と、使用しない場合の両方の実装方法について紹介しました。

やってみて感じたことはAtomic Designのコンポーネントの分け方(特にMoleculesとOrganisms)が定義されていればそれほど迷うことなく実装できると思いました。

デザイナーと協業して開発する方法については今回言及していませんが、一覧をつくっておくと協業がスムーズになります。
破綻する前に少なくても作って置くべきかと思います。

シリーズまとめ

これまでコンポーネント指向でUIを開発してきて、いろいろな手法を検討しましたが、どれもコンポーネントの単位が定まらず破綻していきました。

そのときAtomic Designというメンタルモデルに注目するようになり、この記事にまとめることになりました。

メンタルモデルとは認知心理学の用語で、「あることに出くわしたときに、それをどう解釈/判断し行動するか」について指標となるモデルのこと。

調べていくと実装に適用することは考えられていないことがわかりましたが、
現在の技術(Reactや Vue.js)やアイデア(FLOCSSなど)をベースに考えると十分実装可能な概念だと思いました。

どうしてもオレオレAtomic Designになりがちですが、どの現場でもなるべく使えるように考えたつもりです。どこかの現場の参考になれば幸いです。

今後について

シリーズは実は完結していません。
この方法で数年運用してみても破綻してないか、困ったことはないかを書いて完結になると思っています。

完結編はAtomic Designを使ったコンポーネント指向のUI開発:||(2020年公開予定)でご紹介しようと思います。

DevLOVE「Atomic Design ~堅牢で使いやすいUIを効率良く設計する〜」の参加レポ

2018-06-29 DevLOVE「Atomic Design ~堅牢で使いやすいUIを効率良く設計する〜」の参加レポートです。

著者の五藤さんご本人から書籍「Atomic Design ~堅牢で使いやすいUIを効率良く設計する〜」の解説と本には載っていないお話を聞けるイベントでした。

devlove.doorkeeper.jp

直近で書いたAtomic Designに関する弊社のブログはこの日に合わせてまとめたところもあり、独自で考えた観点や手順が五藤さんが携わってこられた現場と比べてどれくらい一致しているか、答え合わせのような気持ちで参加しました。

アトミックデザインを使ったコンポーネント指向のUI開発:序 - UGAP Engineer's Blog
アトミックデザインを使ったコンポーネント指向のUI開発:破 - UGAP Engineer's Blog

印象に残った話

結論としてかなり同じ考え方ができてたと感じ、自信につながりました。ただ、中には観点として足りてなかったことや本で紹介されていることの理解が足りていないことがあり、お話が聞けてよかったと思いました。

その中でも印象に残った話をピックアップします。

デザインデータの負債

デザインデータの負債というワードはエンジニアは聞きなじみのない言葉かと思います。

エンジニアの立場でアトミックデザインに注目していましたが、デザイナー側にも構造化されていないことが原因による問題があることがわかりました。

その一つに「デザインデータの負債」があります。

具体的にはPhotoshopなどのデザインツールでUIをレイヤー分けする際、そのレイヤーの名前や分け方が適当であるとそれを引き継いだデザイナーはまずレイヤーを理解することからはじめなくてはならないということです。

理解した後、同じことの繰り返しにならないようにリファクタしようとしても、今度はそのページ外での影響範囲が分からず手が出せない問題が引き起こされます。

故にデザイナー側でもデザインの作り方、なにか構造化の手段が必要になってくるというわけです。

アトミックデザインの責務の種類を揃える

アトミックデザインの構造化とその責務は本にまとめられた表と解説を読み、「なるほどそういう考え方もあるか」と思っていただけでしたが、その考えにいたるまでの過程を聞くと、とても論理的でさらに理解が深まりました。

デザインの構造化をする上で、まず他の構造化されたものに着目しており、例えば次のものをみると

責務でわけられた各レイヤーの依存の方向が1方向であることがわかります。そのことから、アトミックデザインもまずは責務の種類を整理する必要があると考えられたようです。

さらに、デザインの構造化の手がかりを、「ユーザーの行動プロセス」から探し出すことにし、まずはユーザーの行動プロセスを順番に並べてることをされていました。

順番 ユーザーの行動プロセス
1 プロダクトを知る
2 画面全体から情報を探す
3 興味を引くコンテンツを見つける
4 コンテンツに促されて行動する
5 全体を通してサービスに良い印象を抱く

その次に、各レイヤーのデザイン対象を配置していくとこうなります。

順番 ユーザーの行動プロセス デザイン対象
1 プロダクトを知る マーケティング/プロダクトそのもの
2 画面全体から情報を探す 画面全体のレイアウト
3 興味を引くコンテンツを見つける コンテンツの見せ方
4 コンテンツに促されて行動する 行動を阻害しない操作性
5 全体を通してサービスに良い印象を抱く デザインの統一性

最後に、Atomic Designの各レイヤーを配置すると、各レイヤーの関心ごと(責務)が明確になりました。

詳しくは本に書かれていますが、依存方向が1方向であることを保ちつつレイヤーが分かれていることがわかります。

順番 行動プロセス デザイン対象 レイヤー
1 プロダクトを知る プロダクトそのもの Pages
2 画面全体から情報を探す 画面レイアウト Temlates
3 興味を引くコンテンツを見つける コンテンツの見せ方 Organisms
4 コンテンツに促されて行動する 行動を阻害しない操作性 Molecules
5 全体を通してサービスに良い印象を抱く デザインの統一性 Atoms

本を読んだときは各レイヤーの責務を(表を横に)見て、なるほどと思っていただけでしたが、行動のプロセスを(表を縦に)整理することから始めたと知り、自分の中でこの表の納得感がさらに増しました。

UIデザインは複数人が関わっている

こちらはかなり共感できることでした。 デザインはデザイナーだけではなく、エンジニアを含めて複数人で関わっているというお話です。

ディレクター:機能要件・画面仕様
デザイなー:視覚情報・操作体験
エンジニア:実現

そのため、「構造化」というプロセスも全関係者が関わるべきプロセスであるとおっしゃっていました。

デザインカンプという手段は、ユーザが情報を見つけられるか確認できる手段としては有用ですが、構造化の面がおいてけぼりになるため、これまでのようにデザインカンプをデザイナーがつくってエンジニアが実装するフローは見直す必要があります。

なるべきフローは以下のようになると語られました。

構造化の指針を決める(関係者全員)

情報をデザイン(デザイナー)

構造をレビュー(関係者全員)

ソフトウェアを実装する(エンジニア)

ここで重要なのは「常にレビューするようにする」ということだそうです。

レビューするにはGithubのようにバージョン管理と差分比較ができることが望ましいということで以下のツールを紹介していました。

[参考]デザインデータのバージョン管理ができるAbstractを試してみた✌ | UXデザイン会社Standardのブログ

上のツールを使うと、デザインカンプ作成中に構造のレビューができるのと同時にデザインの工程もオープンになる利点があります。
(嫌がるデザイナーもいそうですが。。)

レビューコストは気にされていて、レビューを効率化するために、デザイナーがCSSやReactコンポーネントを修正してしまうことを是としたり、 オープン(モブ)・デザイニングといった、モブ・プラグラミングのように難しいところは一気にみんなで解決して情報伝達も効率化しまおうという取り組みもされたようです。

「構造化づくりはチーム一丸になってやる」を理想ではなく、ちゃんとみんなが行動できる形にされていてすごいなーと感じました。

会場から出た質問

完全にメモったわけではないので、ざっくり書いときます。

MoleculesとOrganismsの判別の仕方は?

チェアマンの市谷さんからの質問でした。
そのときどのサイトを例に取り上げていたか忘れてしまったのですが、例えば次のようなショッピングリストはどこがMolecules(分子)で、どこがOrganisms(有機体)なのかという質問です。

f:id:uggds:20180702001913p:plain

回答
Organisms(有機体)はスタンドアローンであるといえるのでパーツとして切り離しても意味がわかる単位がOrganisms(有機体)といえる。
例えば評価(星)だけが画面にあっても意味がわからないので、それはMolecules(分子)になる。
プロジェクトで共通認識であればどちらでもいいとも思う。

個人的な意見
私はOrganisms(有機体)を「広告バナーのようにどの別のページでもそのまま使えるもの」と定義しました。 下からフェードインしてきたり、フローティングしてたり、埋め込まれてたりと大小様々な広告がありますが、どの画面にでても意味が通じます。 また、広告には訴求する文章が必要です。そのため、Organisms(有機体)には画像でもいいんですが、訴求文が含まれているべきかなと思います。例外はありますが。

[参考] アトミックデザインを使ったコンポーネント指向のUI開発:破 - UGAP Engineer's Blog

ページ上部にあるような戻るボタンはどこに属すか?

回答
戻るだけだと意味がわからないので、どこかのコンテンツには属すはず

AmebaTVとは別のサービスを作る場合は作り直すか?

回答
なにも決まってないまま作りはじめることが多いが、Amebaの冠をつけるならAmebaブランドとは何かから考えるはず。使い回すかどうかはわからない。

Storybookと開発の差分が生まれがちなのだが、Storybookのメンテはどうしているか?

回答
レビューの中にStorybookが含まれているので、そういうことにはならない。差異がでてたら気づく。

デザインレビューはどういう観点でしているか

回答

再利用性はどうでもいい。 デザインカンプを作りきってしまうまえに、Reactでは難しいからこうしてほしいとかを伝えている。

最後に

今回お話を聞いて、スピーカーの五藤さんがエンジニアにも関わらずデザイナーのこともよくご存知で、すごいと思いました。

すると、実はもともとはデザイナー出身だったようです。

デザイナーとエンジニアはお互いのやっていることが見えず壁ができがちですが、お互いが知識に垣根を作らず、理解し合うことでUI開発現場の次のステップに進めるのではという考えを体現されている方だなと思いました。 とてもよい刺激になりました。

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

Atomic Designの導入に際して工夫したこと 〜Atomic Designを使ったコンポーネント指向のUI開発:破〜

本稿は(序)(破)(Q)のシリーズの2番目の記事(破)になります。

シリーズ(序)ではAtomic Designの概要 を、
シリーズ(Q)ではAtomic Designの実装例を説明していますので、そちらをご覧ください。

Atomic Design(アトミックデザイン)とは、UI(画面)をコンポーネント単位で設計し、それらを組み合わせて使い回し可能なUIを作成するための手法です。
Atomic Designの考えのものとUIコンポーネントを切り出していくことはいくつかの利点があります。

しかし、Atomic Design はUIを構築するための方法論でしかありません。
つまり、デザインや実装方法、運用方法は独自に考える必要があります。
実際に導入してみるといくつか乗り越えなくてならないハードルが存在することがわかりました。

本稿(破)ではそのハードルを乗り越えるために、どのような工夫したのかを紹介します。
同様に困っている現場の参考になれば幸いです。

本稿の対象読者

  • Atomic Designを導入してでた課題を他の現場がどう解決しているか気になる方

導入に際してやった3つのことについて説明します。

  1. コンポーネントの具体的な定義
  2. コンポーネント一覧の作成
  3. デザイナーとフロントエンドエンジニアの認識合わせ

導入に際してやったこと1:コンポーネントの具体的な定義

各階層のコンポーネントの仕分け方で悩むことが多かったため、具体的なコンポーネントの定義をして共有しました。
※以下でPowerPointという言葉が出てきますが、一旦まずは定義を紹介します。

Atoms(原子)

  • リンクやボタンやフォームのパーツ単位など UI の最小要素
  • 見た目に関することはこのモジュールで表現する
  • PowerPointの一つの図形で表現できるもの
    ラジオボタン・セレクトボックスなどのフォームは例外)

Molecules(分子)

  • AtomsとMoleculesから構成されるグループで、比較的小さいコンポーネント
  • 中身の文言や配置を変えることで使い回しが可能なもの
  • 別のOrganismsを跨いで出現するもの、または、これから出現することがわかっているもの
  • PowerPointの図形をグループ化して表現するもの

Organisms(生命体)

  • AtomsとMoleculesから構成されるコンポーネント
  • 広告のバナーのように、どのページに配置しても意味がわかる独立したコンポーネント
  • デザイン上初めてでてくるもので、比較的小さいコンポーネントだが使い回すかどうか不明なもの。 (未知の生命体
  • 幅を固定しないとデザイン通りにならない、使い方が限定的なもの。
  • PowerPointの図形をグループ化して表現するもの。

Atoms(原子)の説明

概念ではAtomsの粒度は、ラベル、入力フォーム、ボタンなどHTMLタグレベルになります。
しかし、実装していると、ラベル単位では粒度が細かすぎるように感じました。
粒度が細かすぎるとそれをコンポーネント一覧に登録することが手間だし、増えすぎてコードの見通しも悪くなります。

そこで、細かすぎずチーム全員が「これは最小単位のモジュールだ」と機械的に判別できる何かを探して辿りついたのがパワポの図形です。

download.png

スクリーンショット 2018-04-13 18.04.53.png

パワポの図形を使って以下のようにatoms(原子)を定義しました。

Components Definition
Atoms パワポの図形1つでつくれる単位
Molecules, Organisms パワポの図形をグループ化してつくる単位

この考えでいくと、例えば次のように仕分けすることができます。

Atoms(パワポの図形1つでつくれる) f:id:uggds:20180624213053p:plain

Molecules(パワポの図形をグループ化してつくる) f:id:uggds:20180624213107p:plain

上の例ではAtomsにもMoleculesにもbuttonがあります、これをつくることでボタンの中にアイコンをいれたボタンをつくりたい場合に、最小単位のアイコンを、最小単位であるはずのボタンが制御しなければはならないというジレンマを解消します。

またこれにより、Atomsのbuttonは内側にあるアイコンの位置などは指定せず、色やフォント、シャドウのみを表現することに専念し、最小構成に保つということを守りつつアイコンや他のUIパーツを組み合わせたボタンを作成することができます。

※注意点
図形をグループ化して作ったコンポーネントの中にあるプレーンな「タイトル」や「テキスト」はグループ化して作ったコンポーネントの要素にします。

たとえば、上の図のcardは2つの図形でできているためMoleculesにしますが、 グループ化した後の「タイトル」と「テキスト」はAtomsとして切り出すのではなく、cardの「タイトル」と「テキスト」になります。
そうしないと、結局Atomsの粒度が細かくなりすぎてしまうためです。

パワポの発想はチームの体制が関係しています。
UI/UXディレクションとビジュアルデザインをやる人が別だったため、下のようなフローで作業していました。

①UI/UXディレクターがパワポの図形を使ってワイヤーフレームを描く
②それを基にデザイナーがデザインカンプをつくる
③フロントエンドエンジニアがマークアップ

画面をつくるときの起点はUI/UXディレクターで、UI/UXディレクターは図形をグループ化したり、コピペしてワイヤーフレームを作成していました。
そこで、コンポーネントパワポの図形単位で考えるといいのではないかと思いつきました。

Molecules(分子)とOrganisms(生命体)の説明

Atomic Designの悩みどころにMoleculesとOrganismsの判別があります。

概念では「Moleculesは比較的単純で、Organismsは複雑で大きいコンポーネンント」であるとしていますが、判断できないコンポーネントが出現し、その都度悩みます。

そこで、まずOragnisms(生命体)について調べてた結果、独立したコンポーネントと考えるのがよいと感じました。 具体的には「広告バナーのようにどの別のページでもそのまま使えるもの」です。

下からフェードインしてきたり、フローティングしてたり、埋め込まれてたりと大小様々な広告がありますが、どの画面にでても意味が通じます。

さらに、広告には必ず訴求文が存在します。画像でもいいのですが、訴求文があるか、ヘッダーやフッターなどなくても意味がわかるコンポーネント、それを独立したコンポーネントとしました。

次に、Molecules(分子)は適当につくると無駄に膨れ上がってしまうので「Organismsを跨いで使われている、使われる可能性があるもの」としました。
親子コンポーネントの子コンポーネントに相当しますが、親から離れて別の親にも付いて行っちゃう子です。

最後に、Organismsの子コンポーネントとして切り出したが、今後別のOrganisms内で使われるかわからない場合(Moleculesにするか悩む場合)があります。
そんなときは、未知の生命体ということで、一旦Organismsにすることにしました。

安易にMoleculesにせず、一旦Organismsにして、Organismsを跨いで使うようなコンポーネントだとわかればMoleculesにリファクタします。
悩む時間がもったいないし、Moleculesにしても使わない可能性が高いからです。

ここまで説明した仕分け方法をフローチャートで表現すると以下のようになります。

f:id:uggds:20180717004055p:plain

導入に際してやったこと2:コンポーネント一覧の作成

コンポーネントを作りすぎると、探すのが大変になりました。
増えていくと、探すのをあきらめて新しいファイルを作成してしまうかもしれません。 デザイナーも忘れて新しくデザインしてしまうかもしれません。

この問題に対しては単純な話ですが、コンポーネント一覧を作成しました。

Atomic DesignのUIコンポーネントを一覧化に使えそうな3つのツールを紹介します。 どのツールを使うかはデザイナーの有無と使用しているフレームワークによって変わってきます。

本シリーズ(Q)では、Storybookを用いた具体的な開発例をご紹介したいと思います。

一覧化手順について、Atomic Designの考案・著者のBrad Frost 氏が Interface Inventory というものを提唱しています。

コンポーネントを分解してKeynote等でリスト化する手順を説明しているもので、コンポーネントがチーム共通の認識で正しく切り分けられているかを振り返りには有用かと思います。

ただ、開発前はKeynote等でもいいかもしれませんが、Web上で確認できるようしておいた方が使い勝手がよいかと思います。

上で紹介したツールはどれもWeb上で確認できるツールです。

導入に際してやったこと3:デザイナーとフロントエンドエンジニアで認識合わせ

デザイナーとフロントエンドエンジニアで進め方の認識合わせを行いました。
やったことは主に次の3つです。

  1. Atomic Designを導入する目的とコンポーネントの階層定義を共有
  2. 色、タイポグラフィ、余白は無限につくらず段階的に拡張できるようにしておく
  3. エンジニアからフィードバックする

①Atomic Designを導入する目的とコンポーネントの階層定義を共有
先述した定義をデザイナーとフロントエンドエンジニアで共有します。

UIがAtomic Desingの考え方で階層分けされるとフロントエンド実装ではとても助かるので短絡的に導入しがちです。
しかし、デザイナーからするとパーツからつくっていくのはかなり難しいため、デザイナーの理解が必要です。

いきなりコンポーネント指向でデザインするのは大変なので、開発初期はデザイナーは今まで通りページ単位でデザインし、フロントエンドエンジニアがUIコンポーネントに分けるフローにしました。

のちのちUIコンポーネントが溜まってきたらUIコンポーネントを使いながらデザインしたり、慣れてきたらデザイナーがコンポーネント分割をやることを目標にします。

Atomic Designを導入する目的は、UI(画面)をコンポーネント単位で設計し、それらを組み合わせて使い回し可能なUIを作成するためです。
そうすれば、(私の現場に限った話ですが)ゆくゆくはUI/UXディレクターもOfficeの図形でお絵かきではなく、コンポーネント一覧からコンポーネントを選び出しデザイナーなしでデザインカンプをつくれるようになるだろうし、さらに将来的にUI/UXディレクターが何かしらのツールで組み合わせたらマークアップも終わっている状態もつくりだせるとかもと思っています。

②色、タイポグラフィ、余白は無限につくらず段階的に拡張できるようにしておく
例えば、CSS設計手法のBEMを使用しているならば、

.someClass--s {
   ...
   margin: 10px;
   ....
}
.someClass--m {
   ...
   margin: 15px;
   ....
}
.someClass--l {
   ...
   margin: 20px;
   ....
}

といった3段階まではmodifierを用意して変えられるようにしておきます。
拡張できるのはその段階までとデザイナーと認識あわせしておき、デザイナーはそれ以上の幅を持たせないように気をつけます。

③エンジニアからフィードバックする
コンポーネント切り出しをエンジニアが担っているならば、既にコンポーネント化しているかどうかはエンジニアが発見しやすいです。
なので、段階的な拡張の範囲外だったり、意味合いとして一緒なのに微妙に違うデザインを発見した場合は、エンジニアからデザイナーにフィードバックするよう心がけます。

(破)のまとめ

実際に導入してみて出てきた問題点に対して工夫したことを紹介しました。
Atomic Designの理論と実装にはいくつか折り合いをつけなくてはならない点がありそうです。

最近ではReactやVue.jsのstyled-componentsという CSS in JSのライブラリがAtomic Designと相性がよいため、Atomic Designが再注目されています。
qiita.com

次の(Q)では、このstyled-componentsを使ったAtomic Design実装の紹介と、フレームワークを使わない従来のHTMLとCSSだけでやった場合の両方をご紹介します。

Atomic Designとは 〜Atomic Designを使ったコンポーネント指向のUI開発:序〜

はじめに

UI(画面)コンポーネントを切り出したいときにどういう粒度で切り出したらいいか迷う時があります。

適切な粒度で切り出しておかないと、位置を組み替えたりデザインを修正したい場合に、使い勝手が悪くて作り直しになってしまうからです。

メンテナブルなUIコンポーネントに切り出すにはどうしたらよいでしょうか。

いろいろ調べた末、Atomic Design(アトミックデザイン)というアイデアに行き着きました。
このAtomic Designを使ったコンポーネント指向のUI開発を(序)(破)(Q)のシリーズを使って紹介したいと思います。

  • (序)では、Atomic Designがどのようなものかをご紹介します。
  • (破)では、Atomic Designを導入した際にうまくいかなかった点と工夫した点をご紹介します。
  • (Q)では、具体的な開発例をご紹介します。

このシリーズが同様に困っている現場の参考になればかと思います。

本稿(序)の対象読者

  • ReactやVue.jsのようなフレームワークを使用しているがコンポーネントの切り出し方で悩んでいる
  • BEMなどのCSS設計手法を使用しているがブロックの切り出し方で悩んでいる

Atomic Designとは

UI/UXデザイナーのBrad Frost氏によって考案・書籍化されたもので、以下のサイトで読むことができます。
http://bradfrost.com/blog/post/atomic-web-design/

Atomic DesignはUIコンポーネントの切り出し方と組み上げ方ついて、UIの粒度を明確にし、組織的な指標となるよう考え出された概念です。

Atomic Designは自然界で起こっているのと同じプロセスを適用してUIを設計していきます。
自然界で起こっていることとは、すべての物質は原子で構成され、原子は互いに結合して分子を形成し、より複雑な生物に結合し、最終的には宇宙のすべての物質を創造している世界のことです。

小さなUIコンポーネントが集まり、一つのコンポーネントとなり、さらにそれらを組み合わさるとページになる画面UIの比喩としています。

Atomic Designは階層的なUI設計システムを作成するために、コンポーネントを以下の5つの単位に分別します。

スクリーンショット 2018-04-19 14.47.45.png

左から順に次のことを意味しています。
原子 -> 分子 -> 生体 -> テンプレート -> ページ

TemplatesとPagesはあえて自然界の比喩から脱却しているようです。
これらは最終的な成果物になるため、クライアント、上司、同僚に理解してもらえる言葉にする必要があるためだそうです。

具体的にこれらをHTML要素に当てはめると次のようになります。

f:id:uggds:20180620163024p:plain

[画像引用元]
http://atomicdesign.bradfrost.com/chapter-2/#atomic-design-is-for-user-interfaces

  1. Atoms(原子)
    フォームラベル、入力、ボタンなどの基本的なHTML要素。これ以上分けられないもっとも小さなUIパーツ。
  2. Molecules(分子)
    原子を組み合わせてつくる比較的単純なグループ。たとえば、いいねボタン、コメントボタン、詳細ボタンを組み合わせてできるユーティリティ。
  3. Organisms(生命体)
    原子と分子を組み合わせてできる大きなグループ。ヘッダーやフッターなど。
  4. Templates(テンプレート)
    原子〜生体までのコンポーネントを配置した、ページレベルのフレーム。中の画像や文章などは「サンプル」になる。
  5. Pages(ページ)
    テンプレートに具体的にコンテンツを埋め込んだもの

小さなUIコンポーネントを組み合わせてページができあがっていることがわかります。

さらに、Atomic Design ~堅牢で使いやすいUIを効率良く設計する ではUIコンポーネントが階層化されることで次のような利点があると述べられています。

全体を考慮する必要がなく1つの階の責務に関わる課題だけに集中できる
各階層の責務は以下のようになっていて、課題は各階層をみなおすことで解決する可能性があります。

課題 見直すべき箇所 コンポーネント
欲しい情報をみつけられない 画面全体のレイアウト Templates
コンテンツが魅力的でない ユーザーの行動を促すコンテンツ Organisms
コンバージョンに至っていない 行動を阻害しない操作性 Molecules

Atoms(原子)はラベルのフォントやアイコンやボタンの色味に関わる部分の責務をもっています。 もし、企業イメージにあってないと感じたらAtoms(原子)を並べてみて俯瞰的にみてみると解決するかもしれません。

同一階層に属するコンポーネントであれば差し替えることができる
あるUIコンポーネントで解決できない場合は同一層の別コンポーネントに差し替えることが容易です。差し替えが容易であればA/Bテストも容易になります。

上位層のUIコンポーネントの変更が下位層に影響することがない
階層化されたUIでは下位層は上位層の変更に影響を受けないように設計されるため、変更を加えた階層によって影響範囲の見極めが可能です。 例えば、Templeteを見直し、メインとサイドバーを左右逆転させても、その下の階層Atoms、Molecules、Organismsには影響はありません。 逆に、Atomsでフォントなどの見た目を変えた場合、それを使用しているMoleculesではバランス調整のため余白や折り返しを修正し、さらにその影響で上位層を修正しなくてはならないかもしれないとインパクトの違いがわかります。

(序)のまとめ

ざっくりと説明してきましたが、Atomic Designの考えのものとUIコンポーネントを切り出していくことはいくつかの利点があることがわかりました。
しかし、実はAtomic Design はUIを構築するための方法論でしかありません。

つまり、デザインや実装、運用方法は独自に考える必要があります。

実際、導入してみるといくつかの超えなくてはならないハードルがありました。

次の(破)では、実際にAtomic Designを導入した際のうまくいかなかった点と工夫した点をご紹介します。

参考

bradfrost.com

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

サイトの描画スピードをGoogle PageSpeed Insights APIを使って計測し、Kibanaで可視化する

概要

サイトのリファクタリング前後でページスピードがどれくらい改善されたかを調べるために、 Google PageSpeed Insights APIを使って計測し、さらにKibanaで可視化してみました。

f:id:uggds:20170728175213p:plain

使用技術

  • embulk
  • Google PageSpeed Insights API
  • elasticsearch 5
  • kibana 5

embulk

embulkは、さまざまなデータベース、ストレージ、ファイル形式、およびクラウドサービス間のデータ転送をサポートするオープンソースのバルクデータローダーです。

github.com

pluginが豊富で、今回は以下のpluginを使って実現しました。

一覧サイト
http://whttp://www.embulk.org/docs/ww.embulk.org/plugins/

Page Speed Insights

Page Speed InsightsはURLを指定するだけでサイトのパフォーマンスを診断してくれるGoogleのサービスです。
APIも提供しているので、各種アプリケーションからデータを取得することができます。
APIのガイドはこちら
https://developers.google.com/speed/docs/insights/v2/getting_started

Responseは次のものが返ってきます。

{
 "kind": "pagespeedonline#result",
 "id": "https://developers.google.com/speed/pagespeed/insights/",
 "responseCode": 200,
 "title": "PageSpeed Insights",
 "ruleGroups": {
  "SPEED": {
   "score": 94
  },
  "USABILITY": {
   "score": 100
  }
 },
 "pageStats": {
  "numberResources": 17,
  "numberHosts": 8,
  "totalRequestBytes": "2570",
  "numberStaticResources": 13,
  "htmlResponseBytes": "70113",
  "imageResponseBytes": "14985",
  "javascriptResponseBytes": "709324",
  "numberJsResources": 10
 },
 ...

具体的な秒数ではなく、scoreという形で評価しているところが特徴です。
上記ガイドによると

PageSpeed のスコアの範囲は 0~100 ポイントです。スコアが大きいほど良好で、85 以上のスコアはそのページのパフォーマンスが高いことを示します。

だそうです。

環境準備

KibanaとElastisearch

macVirtualBoxで作ったLinux環境のDockerコンテナ上にElasticsearchとKibanaを構築します。
セットアップ方法下でまとめました。 ugap.hatenablog.com

Page Speed Insights

Googleのサービスになるので、Google Cloud PlatformにログインしてAPIキーを発行してください。

embulk

git cloneで取得します。

$ git clone https://github.com/embulk/embulk.git

embulkのセットアップは公式のreadmeを確認してください。
セットアップが完了したら、pluginをインストールします。

$ embulk gem install embulk-input-http embulk-parser-json embulk-output-elasticseach embulk-filter-add_time embulk-filter-column

config.ymlに記述する例を記載します。

in:
  type: http
  url: https://www.googleapis.com/pagespeedonline/v2/runPagespeed
  params:
    - {name: url, value: '[計測したいサイトのURL]'}
    - {name: key, value: '[取得したAPIキー]'}
  parser:
    type: jsonpath
    root: $
    schema:
      - {name: id, type: string}
      - {name: pageStats, type: json} #---------(1)
      - {name: ruleGroups, type: json} #---------(2)
  method: get
filters:
  - type: add_time #---------(3)
    to_column: {name: created_at, type: timestamp}
    from_value: {mode: upload_time}
  - type: expand_json
    json_column_name: pageStats #---------(4)
    root: "$." #---------(5)
    expanded_columns:
      - {name: numberResources, type: double}
      - {name: totalRequestBytes, type: double}
      - {name: numberStaticResources, type: double}
      - {name: htmlResponseBytes, type: double}
      - {name: cssResponseBytes, type: double}
      - {name: imageResponseBytes, type: double}
      - {name: javascriptResponseBytes, type: double}
      - {name: otherResponseBytes, type: double}
      - {name: numberJsResources, type: double}
      - {name: numberCssResources, type: double}
  - type: expand_json
    json_column_name: ruleGroups
    root: "$.SPEED." #---------(6)
    expanded_columns:
      - {name: score, type: double}
out:
  type: elasticsearch
  nodes:
  - {host: 192.168.33.10, port: 9200}
  index: googleinsights
  index_type: googleinsights
項番 説明
(1) APIの戻り値のうち、jsonオブジェクトであるruleGroups.SPEED.scoreが欲しいため記載する。
(2) APIの戻り値のうち、jsonオブジェクトであるpageStats以下の項目が欲しいため記載する。
(3) 戻り値にtimestampが含まれていないため、embulk-filter-add_timeプラグインを使ってelasticsearchに送る際にtimestampを示すカラムを追加する。
(4) そのままでは扱えないので、embulk-parser-jsonプラグインを使ってパースする。
(5) どこを起点にjsonオブジェクトの値を取得するかを定義する。
pageStats直下のnumberResources等を取得したいため、この設定となる。
(6) ruleGroups.SPEED.scoreを取得するため、この設定となる。

実行

それでは実行します。

1. elasticsearch、kibanaを立ち上げます。
2. embulkを実行します。

$ embulk run config.yml

3. kibanaにアクセスしてみて、Discoverにデータが投入できていれば成功です。 f:id:uggds:20170714194807p:plain 4. Visualizeで可視化してみます。
数時間おきにelasticsearchにデータを投入しておいて、折れ線グラフを作成してみました。

横軸にcreated_atを指定し、縦軸にjavascriptResponseBytesを指定してみます。 f:id:uggds:20170714200924p:plain

うまく可視化することができました。

さらに突っ込んでみる

他にも、cssやimageのResponseBytesが取得できるのですが、それらを足し合わせたResponseBytesはないのが残念です。
そこで、Kibanaの画面上でこれらの項目を足し合わせるscriptを書き、新しい項目としてカラムを追加することをやってみます。

以下のサイトを参考にさせていただきました。
Kibanaでの項目集計について - 日本語による質問・議論はこちら - Discuss the Elastic Stack

サイトにあったやりかたと同様に
Kibana > Management > scripted fields > Add Scripted Field
からscriptを作成します。

f:id:uggds:20170714202313p:plain

作成したスクリプトは以下になります。

def t = [];
if (doc['cssResponseBytes'].value != null) {
  t.add(doc['cssResponseBytes'].value);
}
if (doc['htmlResponseBytes'].value != null) {
  t.add(doc['htmlResponseBytes'].value);
}
if (doc['imageResponseBytes'].value != null) {
  t.add(doc['imageResponseBytes'].value);
}
if (doc['otherResponseBytes'].value != null) {
  t.add(doc['otherResponseBytes'].value);
}
if (doc['javascriptResponseBytes'].value != null) {
  t.add(doc['javascriptResponseBytes'].value);
}

return t;

それぞれの値を配列に格納し、それをtotalResponseBytesというフィールドに集め、可視化するときに縦軸のAggregationでsumを指定することになります。

f:id:uggds:20170714203849p:plain

javaScriptのResponseBytesが全体のほとんどを占めていて、絵的には変わっていないように見えますが、 横軸をみるとうまく足し合わせたものになっているようです。

まとめ

今回はサイトの速度を可視化するため、Google PageSpeed Insights APIを使用しましたが、 embulkとelasticsearchの連携は他にも応用がききそうなので、他のデータも可視化して楽しめそうです!