Skip to content

Instantly share code, notes, and snippets.

@japboy
Last active January 29, 2016 10:32
Show Gist options
  • Save japboy/5628828 to your computer and use it in GitHub Desktop.
Save japboy/5628828 to your computer and use it in GitHub Desktop.
ソーシャルボタンのスバラシサについてまとめてみた (嘘

みんなだいすきそーしゃるぼたん

今日は以下の記事よりソーシャルボタンのスクリプト読み込み最適化についてメモしておきたいと思います。

Delay-load non-essential scripts (e.g., Facebook Like, Google +1, Twitter).

Everyone wants their page to be popular on social networks, but social network scripts tend to be large and can cause sluggish response for the user. Waiting until the page has loaded before requesting these scripts can make the page responsive sooner. Even better, rethink whether these buttons are necessary at all, and whether they improve your page's overall experience.

こちらの文中で紹介されていた以下記事を読みまして、SNS のサードパーティースクリプト、ちゃんとしないとアカンと思いました。

Web パフォーマンス最適化の話においてよく言われるのが;

5 秒以上ユーザーを待たせると、ユーザーはあきらめてページを閉じてしまう。

と言った感じで、5 秒が一つの基準になっていたりしますが、すっかり定番となった SNS の拡散用ソーシャルボタンは、この待ち時間に結構影響をおよぼすようです。

埋込タグはロードを遅くする

まぁそれもそのはずで、ソーシャルボタンのコードというと以下のようなスタイルが一般的です:

<a href="https://twitter.com/share" class="twitter-share-button" data-lang="ja">ツイート</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>

これは Twitter ボタン の例ですが、要するに HTML タグがあって、その直後にその HTML を装飾するための JavaScript が記述されている訳です。

こんな感じのソーシャルボタン埋め込みタグを盲目的にページの各所にコピペしていくと、HTML 中のあちこちに <script> タグを書き散らかすことになります。

これの何が問題なのかは最初に挙げた記事の以下の引用をみればわかるでしょう:

The browser must retrieve, parse, and execute a script file in the HTML markup before it can continue parsing the rest of the file, [...]

Web ブラウザは HTML 読込の過程で <script> を見つけると;

  1. スクリプトの内容を取得し
  2. 内容を解析し
  3. そして実行する

という 3 つのステップを始めてしまいます。そしてこれらが完了したら、残りの HTML を読み込み始めるのです。

という事は盲目的に埋め込みタグを HTML 中に書き散らかすと、HTML が読み込まれる過程で何度も JavaScript の処理が走り、その度に HTML の読込が中断されてしまうのです。

Web ブラウザは HTML 全てが読み込まれないとレンダリングしません。つまり、ユーザーは何も表示されない状態でより長い時間待たされる訳です。

これはイカン。

チューニング

という事でソーシャルボタンのスクリプト読込のパフォーマンスチューニングについては以下の記事で紹介されています:

うれしい事に日本語訳もあります:

これらの記事では Facebook の JavaScript 埋め込みタグがパフォーマンス考慮しててステキだから、こいつをベースに他のソーシャルボタンのスクリプトも一緒に読み込むようにすれば、パフォーマンス改善するよねと言っています。

<script>
(function(d, s) {
  var js, fjs = d.getElementsByTagName(s)[0], load = function(url, id) {
    if (d.getElementById(id)) {return;}
    js = d.createElement(s); js.src = url; js.id = id;
    fjs.parentNode.insertBefore(js, fjs);
  };
  load('//connect.facebook.net/en_US/all.js#xfbml=1', 'fbjssdk');
  load('https://apis.google.com/js/plusone.js', 'gplus1js');
  load('//platform.twitter.com/widgets.js', 'tweetjs');
}(document, 'script'));
</script>

記事中で紹介されているチューニングスクリプトは上記のような感じで、一つの即時関数の中で、Facebook と Google と Twitter の JavaScript ライブラリの読込 <script> タグを動的に生成してるわけです。

冷静にそれぞれのソーシャルボタンの埋め込みタグ見ると付属の JavaScript って大抵ライブラリ呼び出すための <script> タグを動的に挿入しているだけなんですよね。こんなもん、わざわざ HTML 中あちこちに散らかす必要性って全然ないですね。まとめて </body> 直前に書くのは自然な流れですね。

更にチューニング

2 つ目に挙げた記事ではこのチューニングを紹介した上で、更なるチューニングを施しています:

<script>
(function(w, d, s) {
  function go(){
    var js, fjs = d.getElementsByTagName(s)[0], load = function(url, id) {
    if (d.getElementById(id)) {return;}
    js = d.createElement(s); js.src = url; js.id = id;
    fjs.parentNode.insertBefore(js, fjs);
  };
    load('//connect.facebook.net/en_US/all.js#appId=272697932759946&xfbml=1', 'fbjssdk');
    load('https://apis.google.com/js/plusone.js', 'gplus1js');
    load('//platform.twitter.com/widgets.js', 'tweetjs');
  }
  if (w.addEventListener) { w.addEventListener("load", go, false); }
  else if (w.attachEvent) { w.attachEvent("onload",go); }
}(window, document, 'script'));
</script>

どうやら web ブラウザの onload イベント発火後に動的な <script> タグの挿入を行う事で、読込時間が -68% まで削減されたようです。これは素晴らしいですね。マネするしかありません。

マネした

という訳で記事で紹介されていたスクリプトに mixi と LINE も追加したものを書いてみました:

こいつを </body> 直下で;

<script src="./socials.js"></script>

てな感じで読み込んでやって、あとは HTML 中好きなところに埋め込みタグを書いてやる。タグの書き方はコメントを参照。要は <script> タグを動的に生成するスクリプト部分を省いてやれば良いだけ。

まてよ

ここまでやってふと思ったのですが、先日書いた Jade によるコンポーネント化を実践すれば、そもそもこんな <script> タグを動的生成するスクリプトなんていらないんじゃないでしょうか。

例えば Jade のインクルード用ファイルとして以下のようなファイルを作成します。

_inc_script.jade:

script(src='//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=XXXXXXXXXXXXXXX')
script(src='https://apis.google.com/js/plusone.js')
script(src='//media.line.naver.jp/js/line-button.js?v=20130508')
script(src='//static.mixi.jp/js/plugins.js#lang=ja')
script(src='//static.mixi.jp/js/share.js')
script(src='//platform.twitter.com/widgets.js')

そして、こいつをメインの Jade ファイルからインクルードします。

index.jade:

!!!5
html
  head
    meta(charset="UTF-8")
    title 最高にクールなホームページ
  body
    p 最高にクールなホームページへようこそ。
    include _inc_script

あとは Grunt 使って HTML を生成してやれば、動的に <script> タグを生成するなんていう気持ちわるい事をする必要もなくなりますし、処理速度の向上も期待できますね。

ソーシャルボタンカワイイデスネ。

みんなだいすきそーしゃるぼたん!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment