dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

Frontrend Vol.10 - 夏の終わりに納涼パフォーマンス話 に行ってきた

行ってきました。
絶対ブログ書く人類枠だったのでブログ書きます。

ハッシュタグ#frontrend。また動画が FRESH! で観られます。

https://freshlive.tv/tech-conference/151511

FRESH! クライアントサイドパフォーマンス改善

FRESH! 鈴木雅佳 ( @sutiwo_ ) さん

1. SW で静的アセットのキャッシュ
  • 設計方針と実装方法
    • キャッシュがあればキャッシュを返し、なければフェッチ
    • リリース単位でキャッシュさせるもの(Circle CI の build_id に紐づく)
    • 意図的に更新させないとキャッシュされ続けるもの(version.json に任意の日付を入力)
  • SW のディレクトリ構成
service-worker/
  - assets.js // Web フォント・CSS・JS ファイルのホワイトリストを作成
  - index.js  // イベントハンドラの登録
  - register.js // SW がインストールされているかの確認

最終的に browserify で service-worker.js へ

  • ローカルで確認するときはブラウザでスーパーリロードも使えるが、環境変数にフラグを用意するのをオススメ DISABLED_SW_CACHE: bool


2. Intersection Observer で遅延ロード
  • 遅延ロード:スクロールなどをトリガーとして画像を非同期ロード
    • FRESH! での例:コンテンツのランキング画面
      • ランキング画面には 50 位ぐらいまで表示する必要があるが、常に見えているのは 6 個ぐらい
  • Intersection Observer


3. SVG スプライトやめてプログレッシブなロード
  • これまで:アイコンはSVGファイルを結合してた
  • HTTP/2 対応により通信多重化や並行リスエストが可能になり、スプライトをやめた


パフォーマンスを改善して本を売る!「読書のお時間です」の取り組みについて

ブックテーブル 小林正弘( @masahiro_koba ) さん

※資料公開されたら貼る

  • SPA + SSR
  • 技術選定
    • jQuery, handlebars, grunt から React, Flux, webpack などのモダンなツール・ライブラリへ
  • 旧システムのページと共存、行き来できる設計
    • #! (ハッシュバン)から / (パスルーティング)へ
  • 1 ページに大量の書籍の表紙画像を表示する必要がある
    • サイズ ◯ px × ◯ px、圧縮率 ◯ % でクライアントからリクエスト -> Image Magick で圧縮
  • 事業 KPI との関連を可視化


アメブロ: Isomorphic Application のパフォーマンス・チューニング

アメーバブログ 侯斌 ( @houbin217jz ) さん

  • アメブロ SP リニューアル 2016.8
    • Java -> Node.js へ
    • SSR -> Isomorphic App (SSR + SPA)
  • チューニング内容
    • バックエンドのキャッシュ
    • 遅延ロード&コード分割
    • Service Worker&アセットのプリキャッシュ
バックエンドのキャッシュ
  • Perf (SSR React) < Perf (Template e.g. Handlebars.js)
  • バックエンドキャッシュの設計
    • 問題点を洗い出す
      • 何をキャッシュする
      • 保存・削除するタイミング
  • ReactDOMServer.renderToString() の結果をキャッシュしたい
    • クライアントによって動的に変わる内容があるので、生成されたHTMLをそのままキャッシュするのではなく、ユーザーの情報に依存しないテンプレート部分のみキャッシュ
  • キャッシュ削除タイミング
    • 記事の投稿時に前の記事・次の記事のリンクとかも更新しないといけない
      • 削除漏れこわい
    • -> Namespace (Ameba Id) ごと削除
    • Fallback としてキャッシュの TTL を設定
    • さらにトランザクションの問題があるのでキャッシュにバージョンId もつける


遅延ロード & コード分割
  • SSR の流れ:
    • Path マッチング、コンポーネントと必要な処理を取り出す
    • Redux Store 準備:API コールを含め、必要な処理を行う
    • Redux Store + ReactDOMServer.renderToString()
  • コード分割
    • 必要ないコンポーネントをロードしないようにして JS 評価時間が短くなるように
    • 分割粒度: Atomic デザインの Organisms 毎
  • webpack の dynamic import で
    • Lazy Load にしたい場合 const loadExample = () => import('./ExampleComponent')
  • リビルドが遅いのでローカル開発ではコード分割を無効化する
SW & アセットのプリキャッシュ


余談

HTTP/2 にしてないと細かく分割した JS はブラウザの同時接続数の問題になりそう...という予想は当たっていたが
SSR だと少なくとも(一番読み込みファイル数が多くなるであろう)初回表示でそういったことは問題にならないのか。なるほど。


おまけ

話に出てきてあまり理解できなかったところの補足。私的メモに近い。

Service Worker・PWA

Service Worker というか PWA については Google for Mobile Workshop Day でやった Google のコードラボがわかりやすかった気がする。

コードラボ
(はじめてのプログレッシブ ウェブアプリ)

で、やってみるとわかるが、Service Worker を使うためにブラウザが対応しているかチェックしたり起動ほか Service Worker のライフサイクルメソッドを手で実装するのはめんどくさいので
そのあたりよしなにやってくれるライブラリを利用する。

コードラボで紹介されていたのは sw-precache というライブラリだったが、最後の発表で紹介されてた workbox もおそらく似たようなことができるんだろう。
(どちらも触ってはいない)

また、Service Worker 自体はプッシュ通知など様々なことが行えるんだけど、とりあえず導入してその恩恵を受けるのにまずは静的アセットのプリキャッシュを試してみるといいですよ〜というのはコードラボでも Google の人が話してた気がする。


Intersection Observer・遅延ロード(lazy load)

Intersection Observer については前々から聞いてはいたもののどういったものなのか知らなかったが、jxck さんの記事が参考になった。
Intersection Observer を用いた要素出現検出の最適化 | blog.jxck.io

また、lazy load については以前弊社の勉強会で外部の方がこういう LT をしてくれたんだが
そのときは難しくてわからなかった。。。今見たら多少は理解できるだろうか。

みんなにやさしいlazy loadと Reactそしてredux-observable - Google スライド


パフォーマンス測定ツール・指標

会の終わりに
「パフォーマンス測定のためのツールや見るべき指標などは、サイバーエージェント内で全体的に統一されているんですか?」
という質問をした。
(すいません、懇親会出られなかったので最後の発表内容とあまり関係ない質問をしてしまいました。。。)

で、

ということだったので帰り際 @1000ch さんにちょっとだけお話を伺うことができたんだけど、発表にも出てきた通り

を多くのプロダクトでは使用しているとのこと。

SpeedCurve というサービスは使ったことがなかったんだけど、特定の URL のページ表示速度を継続的に測定してくれるサービスみたい。
ただしこれはサーバーの場所やネットワーク速度などが固定された場所からの定期アクセスであり、実際のユーザーの環境ではない。
なので実際のユーザーがアクセスした時のパフォーマンスがどうだったのかは、測定結果を Google Analytics に送ることで収集しているらしい。

また Speed Index という指標についてはこのあたりを読むと勉強になった。


感想

SSR + SPA、Service Worker、HTTP/2 などなど次々に実プロダクトに投入していて、そのあたりはさすがサイバーエージェントさんだなあというのが率直な感想です。

私は業務では Salesforce というプラットフォーム上でアプリ開発をしているので
正直 SSR とか Service Worker とかを業務で使うことはなさそうなんだけど、フロントエンドに関わる人間として知っておかないといけない技術だと思うし
今回 3 名とも事例という形でリアルな話を聞けたのは非常に有意義でした。
(正直めちゃめちゃ難しかったんですが)

また、個人的には最後の発表にあった、JS のコード分割を Atomic Design の Organisms 単位にしているという話が興味深かったです。
Atomic Design の考え方をそこに利用できるのねーという素朴な感想と、Atomic Design も導入して全てうまくいくようなものではなくて何が Atoms/Molecules/Organisms なのかはチームで共通認識を作る必要があると思っているんだけども、
その共通認識の形成や言語化をめんどくさがらずにちゃんとやっておくと今回のような一見関係ない話題でもメンバー同士の会話がしやすいんだろうなあと。

あとこれ。


追記:合わせて読みたい

発表の中で、パフォーマンスと事業 KPI とを関連づけるという話がありましたが、それについてはこういった記事があるようです。
WebパフォーマンスとプロダクトKPIの相関を可視化する話

また、ちょうど今日(9/11)HTML5 Experts.js からタイムリーな記事が。読まねば。
「最近のWebパフォーマンス改善について知っておきたいコト」についてあほむに聞いてきた | HTML5Experts.jp