Vue.js/JavaScript
アプリケーションの
パフォーマンス最適化
Ryo Utsunomiya(@ryo511)
Ikyu Frontend Meetup
2018-12-12
自己紹介
Agenda
- 一休.comで実施したパフォーマンス最適化について
- フロントエンドのパフォーマンス最適化について
- JavaScriptアプリケーション一般に適用できるパフォーマンス改善手法
- Vue.jsアプリケーション特有のパフォーマンス改善手法
第1部
一休.comで実施した
パフォーマンス最適化
やったこと
- スマホ版ホテルページのリニューアル
- UIは一部変更
- 再検索は画面遷移ではなく検索結果の再描画に
- システムは変更点多数
パフォーマンス改善の背景
- サイトのスピードが遅いという声は以前から上がっていた
- 遅いサイト = 使いづらいサイトなので、UXの観点からは改善が必要
- SQLのチューニング等、サーバサイドの最適化はそれなりに実施されてきた
- ただし、アーキテクチャ的な問題でパフォーマンスが出し切れていなかった
- フロントエンドの最適化はイマイチで、これが足を引っ張っていた
当時の課題
- Time To First Byteが遅め(500ms~)
- 目標値は200ms
- Render Blocking Scriptsが多い
- 目標値はゼロ
- JSのバンドルサイズが大きい(400KB)
- 目標値は、長期的には170KB、短期的には300KB
- CSSのサイズが大きく、保守性に問題あり(1万行ほど)
- 画像のサイズが大きく、lazyloadが不十分
なにをやったのか
- サーバサイドのフレームワーク差し替え
- ASP.NET WebForms => ASP.NET MVC
- フレームワークの移行によって、.NETのasync/awaitをフル活用できるように
- Solr/SQLのクエリを並行実行してパフォーマンス改善
- フロントエンドの大幅書き直し
- imgixを活用した画像最適化
- 機能・デザインは既存を踏襲し、スコープを広げすぎないように
結果(1) Before/After
※Chrome DevToolsのAuditsを使用、プロファイルはSimulated Fast 3G
結果(2) 競合比較
競合の中で一番速かったBooking.comを
ベンチマークにして改善を実施
最終的にBooking.comよりも速くなった
第2部
Webフロントエンドの
パフォーマンス最適化
パフォーマンス改善のサイクル
- 計測(+目標設定) => 改善 => 維持のサイクルを回すことが重要
- ダイエットに似てますね
計測
-
フロントエンドの計測ツールはLighthouseがデファクトスタンダード
- Chrome DevTools
- PageSpeed Insights
- web.dev
- WebPageTest
- SaaSにもLighthouseを組み込んだものがある。Calibre等
計測時の注意点
- 必ずThrottlingしてから計測する
- Fast 3G = 1.4Mbps
- 計測環境は毎回同じであることが望ましい(ローカルのChromeよりPageSpeed InsightsやWebPageTestの方がよい)
計測結果の見方(1)
- まずはスコアを見る
- 最近LighthouseのScaleが変わって、厳しくなった(以前は75以上で「速い」)
- スコアは様々なページ・サイトの比較に便利
計測結果の見方(2)
- 「改善できる項目」と「診断」は超有用
- ここをベースに改善案を考える
目標設定
- 最終的なゴールはRAILモデルを参考に
- Load 1秒以内、Response 100ミリ秒以内、等
- RAILが現状と乖離しているなら、より近いところに短期目標を置く
他のサイトも計測してみる
- 他社の同等のページを計測してみると、パフォーマンスの短期目標を立てやすい
- 一休.comのホテルページの場合、競合で一番速いのはBooking.comのホテルページだった
- そこで、Booking.comと同等以上のスピードを目標にしてパフォーマンス改善を実施
- 結果、一休.comのホテルページは、主要なホテル予約サイトでは最速に 💪
- しかしRAILモデルの目標値には達してない
他サイト計測の注意点
- 性質の異なるサイトを比べるのはあまり意味が無い
- サイトの仕様によってチューニングしやすさは変わる
- コンテンツのリッチさ
- パーソナライズされたコンテンツの有無
- 広告、ウィジェット等、サードパーティから読み込むコンテンツの有無
定期的な計測
- Webサイトのパフォーマンスは、簡単に劣化する
- 定期的な計測が重要
- 一休ではCalibreというパフォーマンス計測のSaaSを使って時系列の推移をみている
Performance Budget Alert
- 定期的な計測に合わせて、パフォーマンス予算のチェックをするのがおすすめ
- 指標としては、転送するリソースのサイズ、SpeedIndex、Time To Interactive等
- 予算を超過したらSlackにアラートを流す
第3部
JavaScript/Vue.jsアプリの
パフォーマンス改善
改善ポイントは主に3つ
- 画像とWebフォントの最適化は費用対効果が良い
- JavaScriptの最適化は結構大変
速いJavaScriptとは?
- 速いJS = 少ないJS
- Webページを表示するまでに読み込まれるjsファイルの総転送量が重要
- モバイルでは、回線速度を考慮すると170KB(minified/compressed)が上限
- これより多い場合は「遅い」
- サイズを意識しないで開発していると、この上限を超えていることが多い。実現可能な短期目標を立てて、少しずつ改善する
速いJavaScriptのための設計
- JSで書く必要があるか? を常に考える
- SPAにするより、MPAにしてCDNでキャッシュを効かせる方が速いかも?
- ライブラリの選定ではサイズを重視する
- ReactよりPreact、momentよりDay.js等
- 自前でJSを書かず、チューニング済みのコンポーネントを使う(=AMP)
⚡AMPは速い
JSの最適化ポイント
- JSの最適化ポイントはいくつかある
- ロードの最適化、インタラクションの最適化等
- ロードの最適化が最もクリティカル
- ロードの最適化のためには、ロード時に読み込まれるJSのサイズをできるだけ減らす必要がある
JSのサイズを減らすために
- WebpackのCode Splittingで画面ごとにJSを分ける
- Polyfillを減らす方針を考える
- PCとモバイルでバンドルを分ける
- ES Modulesに対応しているかで分ける
- polyfill.ioを使って配信を最適化する
- ビルドツール(webpack, Babel等)の最新版を使う
- メジャーバージョンアップのタイミングで最適化が入ることが多い
precache
- Service Workerによるprecacheで、JSのダウンロード時間をゼロに
- 一休.comではWorkboxの導入を検討中
- AMP版ホテルページで非AMP版ホテルページのアセットをprecache
- ホテルリストページでホテル詳細ページのアセットをprecache
- といった用途が想定される
Vue.jsのパフォーマンス
- Vue.jsは十分に速い
- 本体のサイズも小さめ(22KB min+gzip)
- 参考:jquery 30KB, react-dom 30KB
- Vueコンポーネントのサイズには要注意
- ミニマムなコンポーネントでも1KBくらいになる
Vueコンポーネントの設計
- コンポーネントの数が少ない方が、JSのサイズが小さくなる = 速くなる
- ただし、大きいコンポーネントは保守性が落ちる
- トレードオフを考えてケースバイケースで対応が必要
条件付きレンダリング
- v-if
- false: コンポーネントを描画しない
- true => false: コンポーネントを破棄
- v-show
- false: コンポーネントを描画後、非表示にする
- true => false: コンポーネントを非表示に
- デフォルトで非表示の要素はv-ifにすべき
- 後から非表示にできる要素はv-showがよい
- 全部v-ifでも、ほとんどのケースで問題ない
非同期コンポーネント
const AComponent =
() => import('path/to/AComponent');
<button @click="show = true">Lazy</button>
<a-component v-if="show" />
- Dynamic importを使ってオンデマンドでコンポーネントを読み込む
- v-ifと組み合わせることで、初期ロード時に不要なコンポーネントをロードしないようにできる(Vueコンポーネントのlazyload)
まとめ
- Webフロントエンドの最適化のためには、計測・改善・維持のサイクルを回していく必要がある
- 改善のフェーズでは、細かいチューニングからアーキテクチャ変更まで、様々なスコープの対応が必要
- パフォーマンス改善には、エンジニアの技術力だけでなく、サービスを開発・運営する組織全体で、UXに意識を高くもつ必要がある