2.IDEA

JP only

フロントエンドチューニングのTips(Frontrend in Fukuoka)

先月、サイバーエージェントが開催しているフロントエンドの勉強会 "Frontrend in Fukuoka" に行ってきました。そこで、一番関心があったahomuさんのフロントエンドチューニングの話で気になったことをババッと書きます。

"Page speed insight"と"YSlow"

両方ともパフォーマンス評価ツールです。

「このページ、ここが駄目だわ。まあここは良いけどね///」と、アメとムチでページのパフォーマンスの評価、解決策の提案をしてくれます。

前者は、調べたいページのアドレスを打ち込むだけなので手軽ですし、UXの評価(こちらはβ版っぽいですが)までしてくれます。
後者はブラウザのプラグインですのでほんのちょっと手間がかかりますが評価項目は多いです。
ちなみに前者がGoogle提供、後者がYahoo提供です。

以下に、導入&使用まで一番早くたどり着けるであろうリンクを紹介します(前者は本家サイトそのものなんですが...)。

  1. Page speed insight
  2. YSlowの評価項目まとめ

"Google Chrome Canary"の"Developer Tools"

今度は計測です。

"Google Chrome Canary"とは、"Google Chrome"の開発者向けのNightly Build版(毎晩更新されますよの意)になります。かなり〜良いです。
リリース版(普通のChrome)でもDeveloper Toolsは使えるんですが、最新機能を使えるに越したことはないのでCanaryを使おうという話でした。

command+option+i(mac)を押してからのTimelineという機能で、「何をするために何msかかってるか」をこと細かに計測ができます。

以下の吉川徹さんのスライドがわかりやすかった気がします。

Chrome Developer Toolsを使いこなそう! - SlideShare

"Above the fold"

ページを開いたときスクロールせずに最初に目に入る領域のことを、"Above the fold"というらしいです。なんかかっけえですね。そこで悪い印象を与えてしまうとまずいよ、という話でした。

ガコンとなるページ

説明が難しいんですが、Above the foldに高さを指定していない画像があると、画像が読み込み終わった瞬間に高さが生まれて(?)ガコンとなってしまいます。 文字を読んでる途中にガコンとなったら、「おいおい」となりますよね。

だから、widthとheightを最初からきちんと設定してあげて防ぎましょう、とのことでした。

"CSS Sprite"と"data URI scheme"

両方ともHTTPリクエストを減らすために、読み込む画像ファイルの数を減らすという試みです。

CSS Spriteは、CSSのbackground-imageで画像を表示する際に画像をひとつひとつ用意するのではなく、画像をひとつにまとめてbackground-positionでずらしてうまく表示してあげる技術ですね。この名前を聞くと無性に炭酸を飲みたくなります。

data URI schemeは、画像を表示するとき、サーバーにある画像ファイルを参照する代わりに、長い文字列をHTMLやCSS、JavaScript内に記述する(埋め込む)ことです。

ただ、HTTPリクエストが減るからといって多用すると以下のような弊害があります。

  1. CSS Sprite:まとめた画像のサイズがでかくなりすぎると、まとめた画像が一向に表示されないという事態が発生する
  2. data URI:やたらサイズがでかい画像を文字列にしてCSSに埋め込んでしまうと、ページを開いたときにスタイルが適用されてない状態が見えちゃったりする

ahomuさんは、以下のような画像サイズの目安をつくってるっぽいです。

  1. CSS Spriteは30KBまで
  2. data URI schemeは1KBまで

以下、関連するページです。

  1. CSSスプライトについてあれこれ。
  2. 画像をBase64に変換するツール (data URI scheme)

Retina用の画像

Retinaディスプレイでは2倍の解像度で表示されます。なので、画像を綺麗に表示をしようと思ったら「表示したいサイズの2倍の画像を用意してCSSで半分にする」というテクニックを使います。

ただ、画像のサイズをすべて2倍にしてしまったら、2次元なので2*2=4倍のサイズになってしまい、重くなります。

ahomuさんは、キービジュアルと画像化したテキストだけ2倍の画像を用意してあげるのが良いと言っていました。
理由としては、画像化テキストは、マークアップで表示している文字が高解像度で綺麗に見えている分、画像化したテキストでさぼると相対的に汚く見えちゃうかららしいです。

以下、画像のRetina対応の方法です。

Webサイト&WebアプリのRetina対応方法まとめ | KRAY Inc

gzipで圧縮しよう

CSSやJavascriptはgzip形式に圧縮してサイズを落とせるので、がんがん圧縮しましょう。

ちなみに、「minifyしよう」も日本語で「圧縮」と言われるときがありますが、「縮小」が正しいようです。
「縮小」と「圧縮」は以下のような違いがあります。片方で満足せずに両方ともやっとくのが良いんじゃないかと思います。

  1. minify:コードの余分な空白や改行を削除すること。手作業でも時間をかければ出来る。
  2. gzip:文字通り圧縮すること。ファイル形式を.gzにする。賢いコンピュータが賢いアルゴリズムで符号化してるので手作業では無理。

以下、minifyとかgzipする方法です。(私はgruntでやってますが...)

Googleのウェブマスターツールがgzip圧縮をオススメするのでやってみた。 - 雨ときどき晴れ

CSS3はほどほどに

ahomuさんは、パフォーマンスの話をするときはやたらCSS3をdisる、と言っていました(笑)

見た目"だけ"やたらかっこいいサイトはあまり好きじゃないとのことでした(心の中で激しく頷きました)。

とくに、border-radiusやbox-shadowはよく使用されますがレンダリングに時間がかかるのでほどほどにしましょう。

GPUアクセラレーション

CPUではなくGPUにアニメーションを担当してもらうと滑らかに動きますよって言う話です。

HTML5 RocksのHigh Performance Animationを見た方が早い気がします。

CSSでは、以下のプロパティを使ったときに、GPU側で処理されるようです。

  1. position-> transform: translate
  2. scale:-> transform: scale
  3. rotate-> transform: rotate
  4. opacity-> opacity: 0~1

jQueryのTips

jQueryセレクタのキャッシュ

セレクタは変数に格納しましょうという話でした。プログラミングやってる人にとっては当たり前ですね。

1 $('#id').append("Hello");
2 $('#id').append(" World");
3 $('#id').append("!");

1 var id = $('#id');
2 id.append("Hello");
3 id.append(" World");
4 id.append("!");

としたほうがいいとのことです。また、DOM操作はいっぺんにできるならいっぺんにやったほうがいいので、以下が最良の方法らしいです。

1 var id = $('#id');
2 id.append("Hello", " World", "!");

多い要素へのイベントは、delegateでまとめて設定

jQueryイベントの設定の方法にもひと工夫できるとのことです。

1 $('table td').on('click', function(){...});

上記のようにやると、td要素ひとつひとつにイベントを登録してしまうみたいです(旧APIでのbind())。 わかりやすくいうと、td一人ひとりに「クリックされたらこういうこと(function)をしてね」と教えているみたいな感じです。 一人ひとりに伝えるのは時間がかかりますよね。

1 $(table).on('click','td', function(){....});

上記のようにしてあげると、親のtable要素にイベントを登録して「クリックされたら、その子がtdかどうか判定して一致していたらイベントが起動」するみたいです(旧APIでのdelegate())。 わかりやすくいうと、table先生に「生徒がクリックされたらこういうこと(function)をさせてくださいね。ただし、tdという子だけですよ」と教えているみたいな感じです。 table先生に1回伝えるだけなので、すぐ終わりますよね。

さらに、後者ならあとからtd要素が追加されてもちゃんとイベントが発生します。何も知らない転校生が入ってきても、ちゃんと先生が知っているの大丈夫ですね。

"throttle"と"debounce"

高頻度で呼び出されるイベントはこれらを使って間引くことができるそうです。

throttleは、発火する頻度を指定したdelaytimeだけ間引くことができます。発火した時点からdelaytime間は発火させないという仕組みです。

debounceは、連続したイベント発生が一段落してからdelaytime後に発火します。イベント発生からdelaytime後に発火するが、その間にイベントが発生するとリセットされるという仕組みです。

以下、詳しい解説のページです。

jQueryを使った文字数カウントとthrottle/debounce - ELAB.

まとめ

他の方の勉強会の振り返り記事を見てても思うんですが、どうやってもとっちらかりますね...以下、この勉強会で学んだ教訓です。

  1. PDCAが大事。計測できなければ改善のしようがない。
  2. はやい>かっこいい
  3. ブラウザの気持ちになる