f:id:cocoro27:20170118182205j:plain

WebアプリにしろWebサイトにしろパフォーマンスはとても重要です。どんなに高機能であっても、どんなにデザインが良くても、パフォーマンスが悪ければユーザーは離れてしまいます。
とは言え現場はキツキツのスケジュールで、パフォーマンスにまでこだわる余裕がないよ!パフォーマンスはひとまずできる限りのところまで頑張るよ!となってしまうこともあるかと…。

この問題の解決の糸口はパフォーマンスを良くする手段をどれだけ知っているかです。仕様を決めるとき、デザインを決めるとき、実装するとき、それぞれのフェーズでパフォーマンスを常に意識していると自ずとハイパフォーマンスに近づきます。

というわけで今回はフロントエンドの観点から、イマドキのパフォーマンス改善手法をまとめてみました。イマドキと謳っておきながら2年前くらいの技術が出てきたりして最新の話題でもないのですが。

ちなみに、本題に入る前にWebパフォーマンスの基本として押さえておくべき本を紹介しておきます。どうぞ遠慮なく離脱してポチりに行ってくださいませ。

ハイパフォーマンスWebサイト ―高速サイトを実現する14のルール

ハイパフォーマンスWebサイト ―高速サイトを実現する14のルール

  • 作者: Steve Souders,スティーブサウダーズ,武舎広幸,福地太郎,武舎るみ
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2008/04/11
  • メディア: 大型本
  • 購入: 32人 クリック: 676回
  • この商品を含むブログ (127件) を見る

続・ハイパフォーマンスWebサイト ―ウェブ高速化のベストプラクティス

続・ハイパフォーマンスWebサイト ―ウェブ高速化のベストプラクティス

  • 作者: Steve Souders,武舎広幸,福地太郎,武舎るみ
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2010/04/10
  • メディア: 大型本
  • 購入: 20人 クリック: 351回
  • この商品を含むブログ (30件) を見る


もくじ

  • リフローを減らす
  • 高負荷のペイントを回避する
  • 優先度の低い処理を先送りにする
  • scrollイベントを減らす
  • scrollジャンクを減らす
  • リソース取得を最適化する preload 編
  • リソース取得を最適化する Resource Hints 編



リフローを減らす

  1. widthなどレイアウトに影響のあるプロパティ操作を最小限にする
  2. will-changeを節度を守って使う
  3. CSS Containmentを利用する

言わずと知れたリフロー問題です。1, 2の情報はそこそこ流通しているので、今回はwill-changeの注意点とCSS Containmentの概要について触れます。
リフローってなんだ?という場合はこちらの記事がとても参考になります。


will-changeプロパティ

軽くおさらいをすると、レイアウトをアニメーション付きで変更する動き(横からスライドインするハンバーガーメニューなど)はCPU負荷が高く、モバイル端末などではカクついてしまうことがあります。これを回避するために処理をGPUに任せる(≒GPUアクセラレーション)という手法があります。opacitytransformなどの特定のCSSプロパティは、ブラウザによってGPUアクセラレーションが対応されています。
そのため、上記の例のスライドインを実装するときはtransform: translateX()を使ったほうがいい、ということになるわけです。

/** CPUを使うのでカクついてしまう例 */
.menu {
  width: 100px;
  left: -100px;
  transition: left 0.4s ease;
  &.show {
    left: 0;
  }
}

/** GPUを使う例 */
.menu {
  width: 100px;
  transform: translateX(-100%);
  transition: transform 0.4s ease;
  &.show {
    transform: translateX(0);
  }
}


ただ、これは「このプロパティはブラウザがGPUで処理させるだろう」という期待を込めた実装であって、GPUアクセラレーションが確約されているわけではありません。そこで、明示的にブラウザにGPUアクセラレーションを指示する(というか、レンダリングの最適化を指示する)方法がwill-changeです。
仕様的な話をすると、要素がこれからどう変化するかを事前にブラウザに伝えることで、レンダリングを最適化させるというものになります。

これだけ言うと便利そうですが、こいつを扱うには知っておくべき注意点があります。

GPU利用はマシンのリソースを大量消費する

何でもかんでもGPUを使わせればいいというものではありません。GPUでの処理は高コストなのです。なので、基本的にはJavaScriptを利用して要素が変化する前にwill-changeを付与し、変化が終わったら取り除くということをする必要があります。

ブラウザは勝手に最適化するので利用はほどほどに

そもそもブラウザはレンダリングの最適化を行っています。その最適化に意図的に手を加えるのがwill-changeなので、ご利用は計画的にということです。

将来起きる変更に対して付与しないと効果がない

will-changeは名前の通り「将来起きうる変更」をブラウザへ伝えるもの。ブラウザはそれを知ってから最適化を行うので、あまりに直前will-changeを付与されても効果を出せません。以下の記事に例が記されていました。

例えば、要素がクリックされる時に変化するとしたら、その要素がホバーされる時にwill-changeを設定すれば、ブラウザが変化に備えて最適化する時間を稼げます。ユーザが要素にホバーしてから実際にクリックするまでの時間で、ブラウザは十分に最適化を行うことができるからです。

参考:CSS will-changeプロパティについて知っておくべきこと

f:id:cocoro27:20170118173129p:plain


CSS Containment

ブラウザが行うスタイルやリフローやペイントの範囲を制限するという新しい仕様です。言い換えると、CSSやJavaScriptで要素を変化させるときにレンダリングする範囲を制限させることができるということです。つまりリフローが減るということです!(とても喜ばしいですね