Webパフォーマンスの計測

ここまでの話は、GYAO!のフロントエンドのを中心とした基盤改修です。今回は時間の都合で割愛させていただきますが、バックエンド側もあわせて改修を行っています。バックエンドの改修では、業務の関心を軸にマイクロサービスとして分解を行っています。

次に「パフォーマンスの改善」についての話をします。

一般的なことですが、パフォーマンスの改善で重要なのは、まず計測することです。アプリケーションのボトルネックは大小さまざまあるため、リターンの大きな箇所に対して改修リソースをつぎ込まないと、局所最適化となってしまい、全体のパフォーマンス向上に寄与しません。わたしたちはOSSをカスタマイズして、Yahoo! JAPANのインフラ上にDocker環境でパフォーマンス計測できるサーバーを構築しました。

(スライドを指して)それがこちらです。GYAO!における表示面のパフォーマンス指標を、数十分おきに監視・計測しています。先ほど上にSpeedIndexの表示をお見せしましたが、パフォーマンス関連の指標のほか、CSS、JSのファイルサイズや独自のパフォーマンスメトリクスなどを計測し、改善に役立てています。

ここで、RAILモデルについて説明させてください。RAILモデルとは、ユーザーの体験をベースにしたパフォーマンス指標です。

例えば、ユーザーがアニメーションを見るとき、60fpsを切るアニメーションは、フレーム落ちしてカクついて見えます。ユーザーの視点だけで見ると、アニメーションは0~16ミリ秒以内の連続した動作を行うことが求められます。

クリックの遷移は1秒以内に動作を行わないと、ユーザーは違和感を覚えます。例えば、クリック後のロードが長すぎて次のページに遷移できない場合、ユーザーは関心を失ってページを離脱してしまいますね。10秒以上経ってしまうと、関心を完全に失う状態となります。

わたしたちはRAILモデルを踏襲して、プロダクトの改善指標を定義することにしました。

GYAO!では、動画サービスの特性を活かして次のような指標を追加しています。例えば、動画の読み込みです。動画サービスとして重要なことは、目的の動画がすばやく再生できることです。そこで、遷移の操作からプレイヤーの読み込みが完了して広告や本編が流れるまでの時間を、2秒以内に収める指標を設けています。現段階では、わたしたちの理想は完全には実現できていない状態ですが、一部のページから徐々に目標達成を実現しつつあります。

フロントエンドのパフォーマンス改善

フロントエンドのパフォーマンス改善でもう1つ重要なものは、初期表示です。

First Meaningful Paintや、Time To Interactiveといった指標で表現されます。この指標の改善には、表示を阻害する要素の読み込みを最適化することが求められます。(スライドを指して)例えば、これはChromeブラウザの開発ツール上で、読み込むリソースをタイムラインで表示したものです。最終的な画面の表示まで、多くの時間を要していることがわかります。

画面に表示するまでの処理のうち、次のステップを阻害するリソースの読み込みが多く見て取れますね。ブラウザが画面に表示するまでの処理の優先順位を、クリティカルレンダリングパスと呼びます。表示までに必要な要素は、ブラウザが確実に読み込まなければならないため、単純に直列で読み込まれると、次の処理を止めてしまい、ページの最終的な表示が遅れることになります。

こうしたブロッキングリソースを回避するためには、リソースを読み込む数や順序を最適化する必要があります。

わたしたちは、まず散らばったスクリプトを、WebPackを利用してすべてバンドルし、CDNから配信を行うことで、表示遅延を減少させることからはじめました。

CSSもクリティカルリソースの1つなので、その部分も非同期で読み込まれるよう改修しています。CriticalCSSというOSSを利用して、主要なページのCSSのインライン化を試みています。

画像の読み込みも最適化しています。IntersectionObserverというWebAPIを聞いたことがあるかもしれません。このWebAPIを利用して、画像の遅延読み込みを実現しています。表示領域外の画像は読み込まず、領域内に入ってきた瞬間に画像を読み込む処理です。バックエンド側では、画像を圧縮して配信するフローを構築しており、それぞれの表示領域に適した最適なファイルサイズで読み込まれるように改修を進めています。

また、ResourceHintsを使って、サービス内で必要不可欠なリソースは事前に取得する最適化も行っています。

バックエンド側のAPIも、徐々にレスポンスの高速化を図っています。リクエストのたびに依存関係を解決して、レスポンスが遅くなるボトルネックに対しては、キャッシュ化やKVSを利用した非正規化を行うことで高速化を図っています。

また、APIから表示要件に応じた必要最低限のデータが取得できるようになれば、オーバーヘッドが減少しますね。そこで現在バックエンド側のAPIを中心に、RESTからGraphQLへの移行を図っています。

AMPの取り組みも行っています。

AMPとは、ご存知の方もいるかと思いますが、制限のあるHTMLの記述方法をとることで処理を高速化し、キャッシュ化された状態で高速に配信される仕組みです。モバイル環境の視聴体験を改善するために、わたしたちはすべての視聴ページをAMPで配信しています。

1つ特徴的なのは、GYAO!の動画プレイヤーもAMPで実現していることです。ぜひ、検索して試してみてください。AMPの恩恵で、モバイル環境でも動画プレイヤーが高速で立ち上がる状況を実現しています。

こうした改善の結果、SpeedIndexがさきほど15,000と言いましたが、徐々に改善して、いま3,000程度になりました。以前と比較すると80パーセント近く向上していることになります。これはまだ道半ばの数値であり、さらなる改善をみなさんにお見せできると思っているので、ぜひ注目していただければと思います。

コンポーネントシステムについて

続いて、コンポーネントシステムについて説明します。先ほど「表示要素をコンポーネントに分解する」と言いました。次のフェーズで重要なのが、チーム全体で利用していくことです。コンポーネントシステムというのはつまるところ、Webページをパーツごとに構成していく仕組みですが、このシステムを高度に発展させるか否かで、後々のプロダクトのパフォーマンスが変わってきます。

(スライドを指して)これは、AtomicDesignの分類フォーマットです。Atomとされる原子的な要素から始まって、最終的なWebページに至るまで、分解された構成要素を組み合わせて複雑な要素を作成していく考え方です。

例えばGYAO!のWebを元に分解を行ってみると、まずグローバルヘッダーがあり、それからジャンボトロンのような要素があって、検索バーがあって、アイテムのカルーセルがあって、下にアプリ誘導のバナーがありますね。

要素を分解して考えていくことで、認識できる範囲を少なくして、組み合わせでページが成り立っている状態を実現します。

さて、カルーセルをさらに分解していくと、カルーセルを成り立たせているアイテム要素に分解されるでしょう。アイテム要素のなかには、さらに後読みの画像イメージ要素や、矢印のボタン要素、ラベル要素などによって構成されています。要素に分けることで、複数の要素間での再利用性が増すとともに、より単純化して物事を考えられるようになっていきます。

コンポーネント分解の粒度は、独自にカスタマイズしています。AtomicDesignは、少々難解な科学の用語が含まれています。例えばMoleculesとか、Organismsとか、ちょっと言いづらいですよね。それに、何を指しているのか明確に判別しづらい問題がありました。

GYAO!では、Predix Design Systemという考え方をベースにして分類しています。AtomicDesignと異なる点の1つは、起点がPageから始まっているところです。PageからLayoutを経て、そのあとにComponents、続いて基礎的な要素であるBasics、そして原則に近いPrinciplesに分かれています。

大きく異なるもう1つの点は、Modecules、Organismsという悩ましいコンポーネントの分類を、Componentsのなかに統一してしまっていることです。

(スライドを指して)この分類でGYAO!のコンポーネントを分類すると、Pageがあって、Layoutがあって、Componentsがあって、最後に基礎的な要素に分類されるでしょう。

わたしたちは、この拡張したComponentsのシステムを使って、レスポンシブデザインを実現しています。これは分類のうち、Layoutの枠組みの中で実現しています。

Layoutは、どのようにパーツを配置するかという枠です。この記述構成を工夫することによって、ComponentsとLayoutの組み合わせで、レスポンシブなコードが書けるようになっています。

スタイルのみではレスポンシブを実現しにくい部分ももちろんあります。そうした場合は、WebAPIを利用することで対応しています。

内部的には、MutationObserverやResizeObserverなどを利用しています。

(スライドを指して)これは、実際のGYAO!の視聴ページです。このページは、レスポンシブデザインで統一されていて、PCとモバイルで共通のテンプレートが利用されています。開発リソースを考えるとフロントエンドエンジニアは非常に少ない状態ですが、改修範囲が少なくなるため、少人数でも十分に改修が行き届くようになります。1つの機能を開発するだけで、モバイルとPCの両デバイスの表現が実現できます。

コンポーネントシステムを行う上で重要なポイント

コンポーネントシステムを行っていくうえで、いくつか重要なポイントがあります。

1つは、影響を閉じ込めることです。先ほど「継ぎ足されたコードが影響し合って、メンテナンスがしづらい状況があった」と言いました。このシステムでは、コンポーネントの影響範囲は必ずコンポーネント内で完結するようになっています。

これは、ShadowとCSSの詳細度を用いて制御する仕組みで実現しています。

中には複雑な動作を伴うコンポーネントも存在するため、コンポーネント同士で状態が影響しあう場合もあります。その場合の状態の管理は、現在のところAMPで利用されている状態管理の仕組み(AMP State)に似た形で実現しています。将来的にはSPAの環境での実現を考慮しています。

どのような場合にせよ、ここで重要なのは、他のコンポーネントとスタイルの衝突が発生しない状況が担保されることです。

詳細度でスタイルを閉じるという手法は、Inverted Triangle CSSというスタイルの詳細度の制御の考え方をもとにしています。現在は、各階層ごとに自動でビルドされ、それぞれ上の階層にスタイルの上書きが発生しないよう考慮されています。

(図をみながら)例えば、ComponentsからLayoutのスタイルを変化させることはできません。 逆に、LayoutからComponentsを変化させることはあります。逆方向からのみ上書きができないことを担保しています。

もう1つのポイントは、一意な出力です。

これは、データ型(エンティティ)を明記することから始まります。受け渡すデータの型を明示しておくと、バックエンドとフロントエンドで開発が並行した際にも、開発者間のコミュニケーションが容易に進みます。

例えばカルーセルの要素を作成するには、まず画像が必要ですし、タイトルも必要です。複数の要素が必要なときに、開発者同士(ひいてはデザイナー)の意思疎通を明確にしておくと、結合時の不具合を最小限にできるでしょう。

このデータの型を明確にするために、JSON-Schemaを利用して型定義を実現しています。

JSON-Schemaのように一般化した形でデータを定義すると、そこからスタブデータも自動で生成することができます。

スライドに「ピュアみ」と書きました。これは先ほど登壇した弊社エンジニアの石井直矢さんの言葉ですが、すごく重要なので書きました。これは「一意な出力、同じデータを入力したら、必ず同じ表示が出てくるということ」を表現した尊い言葉です。

「同じデータで同じ表示がされること」がなぜ重要かというと、予測不能な制御をコードから除外できるとともに、表示面のスナップショットテスティングが担保できるからです。データが同一なのに出力がランダムに表示されていては、出力のテストが困難です。コンポーネントシステムでは、スナップショットテストや画像回帰テストの実装を見越して作成されており、現在はその裏側の実装が進められています。

コンポーネントシステムを構築する際の分解のポイントとしては、いきなり細かく分解しすぎないことが重要です。

わたしたちは既存のプロダクトを徐々に刷新するプロセスを踏んでいるので、Fat Viewとなっている巨大な要素から徐々に切り出して分解を進めていく必要があります。

その際に、共通性が見出せない要素をやみくもに分解してしまうと、再利用性のないコンポーネントが誕生する上に、手間が増えて開発リソースを切迫します。まずは、できる範囲で分解していく。大きいところからPage>Components>Basicsの順番で分解していって、デザインパターンや原則が見出された段階でより細分化していくプロセスが、今のところベストではと考えています。

デザインシステムについて

ここまでが、コンポーネントの話になります。続いて、このコンポーネントシステムをもとにデザインシステムを導入した話をします。

「デザインシステム」という言葉を聞いたことがあるかもしれませんが、さまざまなものがありますね。Googleのマテリアルデザイン、Carbon Design Systemなどは聞いたことがあるでしょうか。例えばAtlassianやAirbnbも、独自のデザインシステムを持っていることで有名ですね。

ここで、『Modular Web Design』の著者であるNathan Curtisさんは、次のように述べています。

「デザインシステムは、製品を提供するための製品である」。これはどういうことかというと、プロダクトを作成するワークフローを振り返ってみるとよくわかります。

わたしたちのこれまでのワークフローは、まずデザインから始まって、仕様を決め、プロトタイピングをして、開発し、最後にプロダクトに届くという流れになっていました。見て分かる通り、作業が直列に進んでいます。

このワークフローでは、矢印の分だけコミュニケーションを取らなければなりません。まず、デザインから仕様として成立するまでが1つの障壁で、何度もやり取りして仕様を策定します。仕様からプロトタイピングを作るまでにも障壁があります。実際に開発するまでにも、プロダクトに反映するまでにも障壁があります。矢印の分だけコミュニケーションが発生して、そこで巻き戻ることもあるわけです。

UIデザインは、デザイナーだけが決められるものではありません。開発の制約もあり、もちろんビジネスの仕様も盛り込まなければならないからです。全員の意見を集めてプロダクトを作成する必要があるため、最初にデザイン面からの情報のみを考慮して作成していては、プロダクトに届くまでに、ものすごく長い修正の道のりをたどることになります。

デザインシステムの仕組み

デザインシステムとはこのような仕組みになります。

プロジェクトによってさまざまなワークフローが存在しますが、GYAO!では図のような形態を取っています。スタイルガイドラインやコンポーネントシステムを利用して、ビジネス要件やデザインのアップデートをプロダクトに反映させるまでの流れの障壁を少なくしています。

ここで注目したいのは、「プロダクトに届けるまでのプロセスを仕組みにする」ということです。先ほどの図と比較して、矢印の数が減っていることがわかると思います。

例えばデザインのアップデートは、案件に依存せず、コンポーネントシステムを変えれば、プロダクト全体に意図が反映されるような環境を作ります。

仕様の更新や開発についても、反映を行いやすいプロセスを作ります。

GYAO!では、仕様策定のプロセスもコンポーネントシステムに取り込んでおり、企画側からは変えたい仕様に対して「この仕様を変えてね」とプルリクエストを出してもらっています。これをもとに関係者で議論し、開発を行い、プロダクトとして実現していきます。コンポーネントシステムを共通言語として、デザインと開発と企画が密に連携することにより、出戻りの発生を少なくしています。

(スライドを指して)これは実際に飛んできたプルリクエストです。「こんな仕様を実現したい」という依頼に近い形で飛んできます。マークダウン形式で書かれています。開発以外の職種の方にとっては敷居が高そうに見えますが、GitHubにはWebUIがあるため、マークダウン形式さえ覚えれば、Gitの仕組みがわからなくても記述と依頼が可能です。仕様と実コードを集約して管理できることは、非常に大きなメリットです。

デザインシステムを実行していくうえで、いくつかポイントがあります。

コンポーネントシステムの実現は、デザインシステムを強固なものにする上で重要な要素です。そのためには、案件を行う際に常にコンポーネントの粒度で仕様を決定できるように、頭を切り替える必要があります。制限がある代わりに、わたしたちは小さな単位で、仕様・デザイン・コードを考えていくことができます。管理も容易となり、機能の再開発やデザインの不統一を防ぐことができます。

また、信頼できる唯一の情報源を作ることも重要です。問題点の1つとして、仕様が分散することがよく発生するのですが「この仕様を見ればすべて把握できる」資料を作成するフローを構築しておけば、あとから参加した人のキャッチアップが容易になります。仕様を再度調べ直すコストは、馬鹿になりません。唯一の情報源を作成することは、把握の速度を短縮してプロダクトを迅速に届けるプロセスに貢献します。

加えて、UI/UXの変更意図や試行錯誤の過程をまとめていくと、次回の作成段階にも非常に役立つでしょう。

始め方のポイントとしては「小さく始める」ことが非常に重要です。先ほどのコンポーネントの仕組みは、これまでのワークフローを大きく変化させます。システムを理解する人が中心となって基盤を作成し、有用性を示した上で、徐々に人を増やしていくプロセスを経ると導入しやすくなるでしょう。

組織を変える

続いて「組織を変える」というお話をします。

先ほど「デザインシステムは小さく始める」と言いましたが、運用を止めないことは組織にとって重要です。既存の運用を止めてしまうと、その間のビジネスは停滞してしまいます。

既存運用の混乱を抑えながら、プロセスを変化させるために、何を行ってきたかを説明します。

まず当たり前ですが、考え方を普及させることが重要になります。次に、システムを学ぶバックアップ体制を整えるということです。

1つ目から説明します。デザインシステムを導入する際に、さまざまなロールを巻き込んでデザインシステムを導入していくわけですが、役割ごとに求めているものが異なることは意識したほうが良いでしょう。

当然ですが、デザイナーであれば、デザイン制作のしやすさについての説明を求めていますし、開発者側は開発のしやすさについて説明を求めています。また、ビジネス観点では開発速度や目標達成のしやすさを求めています。求めている観点が違うなかで、各立場に立ったうえで、システム導入のメリットを説明すると良いでしょう。

ここは簡単なようで、大変難しいプロセスです。デザインシステムは「システムの理解や構築が最も難しい」と思われがちですが、実は組織の理解と普及が一番難しいプロセスです。

わたしたちは、担当者ごとに具体的なメリットを説明して、理解してもらうよう努めました。開発者であれば「パフォーマンスが向上」「コンポーネントの仕組みで、開発管理しやすくなる」などです。デザイナーであれば「ユーザーに一貫性を担保できる」「デザインを迅速に反映できる」ということを説明しました。企画や経営者側には「事故リスクや工数が削減でき、高速リリースできる」といったプロセスのメリットを説明しました。

一方で一番の説得力は、小さな単位で実現して、実際にその効果を見せていくことだと思っています。その際には、なるべく具体的な説明を入れると良いでしょう。

システムを学ぶバックアップ体制

2つ目に、バックアップ体制についてです。

わたしたちにとってコンポーネントのシステムを用いた開発は、以前の手法とまったく異なる手法でした。この手法にチームが慣れるように、勉強会の時間を取り、練習問題を作成しました。実際に開発する方には、デザインシステムのワークフローを体験してもらってから業務に参加してもらいました。実際に作る体験を通して、実践までの移行をサポートします。

(スライドを指して)例えば、このような練習問題を用意しています。

練習問題には難易度が設定してあり、簡単なところから始めて徐々に難しくなるように作成されています。

この画面は「レベル1」です。課題は、「『ザクザクカイキン!』と書かれているバナーを視聴ページ内に出してください」と設定されています。

単純な問題ですが、実際にGYAO!で利用するコンポーネントシステムを使って開発できるかどうかを確認できます。これは、例えば新しくジョインした新卒の方だったり、中途の入社で実際に開発される方にとって、有用な情報が詰まっています。

徐々にレベルアップしていくと、例えばこういった問題もあります。

(スライドを指して)何やらちょっと動いてるのがわかると思いますが、「ザクザク」っていうボタンを押すと、どんどんポイントが加算されていく。動きを伴うような開発も、練習問題の中でデザイナーとエンジニアが協業して問題を解きます。このように実際の開発に沿った流れを経験して感覚をつかみ、実践までスムーズにフォローアップできるような体制を準備しています。

負債を解消し、さらなる飛躍へ

長く話してきましたが、これまでのまとめです。

述べてきたように、GYAO!は多くの負債を抱えている状態でしたが、行ってきた施策によって、段階的に、確実に負債を解消しています。アーキテクチャの段階移行、Fat Viewの解体、テストやCI/CDの環境の導入、パフォーマンスの改善、コンポーネントシステムの導入。これらの施策によって、開発のボトルネックになっていた箇所が解消に向かっています。

また、古いものづくりのやり方も、デザインシステムによって変えていきました。肥大化した仕様や過剰なワークフローをなくして、迅速にプロダクトが届く仕組みを実現していきました。

全体を通し、重要なエッセンスをまとめると、以下の通りです。

1つは、技術選択とその移行プロセスです。これまであげてきたフロントエンド技術の改善策は、どれも当たり前のように行われるべきことだと思っています。ただ、少人数であることや組織の状況などを鑑みて、組織の活動を止めない最適な移行手順で進めることは非常に重要だと思います。

その際に、将来を見据えた形で技術選択ができるとベターです。

もう1つは、タイトルにもある通り、デザインシステムの考え方を「普及」させることです。いままでのやり方のものづくりに固執せずに、よりモダンなやり方で作っていく。企画・開発・デザインが直列するワークフローには、リリースまでのやり取りの無駄があります。コンポーネントシステムを取り入れたデザインシステムにワークフローを移行して、プロダクトを迅速に届けられる仕組みに変えていくことは、大きなメリットがあります。

基盤の整備によって、未来に向けてより技術的な挑戦ができるようになります。冒頭で触れましたが、GYAO!ではマイクロサービスアーキテクチャへの移行を行っています。またTypeScriptへの移行や、GraphQLを用いたシステムの移行も徐々に進められています。

パフォーマンス指標の達成も、次の段階に進んでいます。ServiceWorkerの導入や、画像最適化サーバーを準備しています。

また、Progressive Web App化や、WebPackagingの技術にも取り組んでいて、キャッシュ化を利用したSPAの構成を実験している最中です。

ベースを整えることで、これからにむけて挑戦できる環境が整ってきました。

刷新するに当たり、どうしても以前のUIから変更せざるを得ない箇所もあります。至らない点も多々あると思いますが、その都度、お客様からの要望を可能な限り取り入れ、高速な改善を図っていく所存です。GYAO!のサービスのこれからを楽しみにしていただければと思います。

最後になりますが、GYAO!とYahoo! JAPANはフロントエンドエンジニアを求めています。

10年以上にわたる負債をここまで解消してきたわけですが、基盤が整った今、さらなる飛躍に挑戦するチャンスでもあります。例えばReactとか、TypeScript、GraphQL、BFF、WebPackaging、Progressive Web Appといったワードにピンときたなと思ったら、スライドのメールアドレスまでお願いします。わたしがサポートして、最後まで伝えます。

以上です。ご清聴ありがとうございました。

(会場拍手)