シングルページアプリの初速を上げる取組み

https://www.youtube.com/watch?v=VkTCL6Nqm6Y

1 comment | 2 points | by WazanovaNews 3年弱前 edited


Jshiike 3年弱前 edited | ▲upvoteする | link

OSCON 2014におけるInstagramのWebチーム責任者であるPete Huntの講演。PeteはInstagramに異動する前は、FacebookのPhoto/Video/Product Infraチームに在籍。

今回は、InstagramのwebサイトInstagram.comにおいて、シングルページアプリの課題である最初の読込みスピードを上げるために、どのような工夫をしたかについて紹介してくれてます。

  • Instagram.comのJavaScriptファイルは、縮小化後で9.5MB & gzip圧縮後で2.5MB。そのサイズだと、一つのファイルにまとめてダウンロードするには向いてないし、リソースに限りのあるモバイルサイトでパースするのもパフォーマンス的に問題。
  • そこで、17個のエントリーポイントを用意し、各ページに必要なJavaScriptだけをダウンロード。エントリーポイントは共有ライブラリ的な位置づけとし、別のエントリーポイントにユーザが遷移したときに、既にダウンロードしたJavaScriptは再度読込まないように工夫した。
  • モジュール単位の仕組みとし、依存関係はCommonJSで管理。モジュールは各エントリーポイントごとに必要なコンポーネントを組み合わせる。例えば、React とPhotoModalは、profileエントリーポイントとFeedエントリーポイントの両方で必要になるので、まとめて共有のJavaScript bundleに入れて再利用できるようにする。HTTPリクエスト数とダウンロードバイト数を減らすベストなバランスをオブティマイザーが担ってくれる。
  • 全てのエントリーポイントにクライアントサイドrouterを置いている。routerがまとめて全部をrequireするのではなく、必要なものだけを適宜処理できるよう、bundleを非同期に読込むかたちとした。
  • CSSや画像ファイルは、require(‘./bootstrap.css’);myImage.src = require(‘./myimage.png’);などのように適宜インライン化し、モジュールに組み込んだ。less / sass / CoffeeScript / TypeScriptも同様。
  • このモジュールシステムで、静的アセットは全て管理できるようになったので、ビルトシステム(Grunt)は不要になった。
  • 複数のメンバでCSSを書いていると、詳細度 / Class名のコンフリクトで予想外のコードが反映されてしまうことがある。また、必要なくなった箇所を削除できるかどうかの判定も相当難しい。そこでInstagramチームのガイドラインは、
    • 例えば、.igUserProfileAvatarのように、誤って被ることのない明確なclass名をつけるようにして、積極的にネームスペースを確保。
    • 階層を排除。CSSルールごとに単一のクラス名のセレクタのみ。その名称でgrepするだけで、ルールが生きているかどうか判別できる。
    • 上書きは極力避ける。
  • module bundlerとしては、webpackがパフォーマンス的に最適だった。そこで得たノウハウはwebpack-howtoページにまとめた。その他の検討したツールは下記の理由で不採用。
    • Browserify: JavaScriptを一つにまとめるためのソリューション。
    • RequireJS: HTTPリクエスト or 一つのJavaScriptファイルの選択で、複数のエントリーポイントという仕組みには使えなかった。
    • Grunt: テストにはものすごく役立ったが、依存関係の管理には向かない
    • gulp.js: パフォーマンスとしてはGruntより優れているが、モジュール単位でなくファイル単位というコンセプト。

#facebook #instagram #シングルページアプリ #commonjs #react


ワザノバTop200アクセスランキング


Back