遅くて重いWordpressサイトの速度改善を目指していろいろとやってみた話のひとつ。
WordPress自体も遅いし安いレンタルサーバーも遅いけど、とりわけ何が遅いって、facebookやTwitterなどのSNSですがな。これを貼り付けた瞬間、表示が激遅になります。
そこでいろいろ探ってみた。
非同期
非同期にするといいそうな。非同期て何でしょう。わかりませんが、非同期にするといいそうです。
そこで、facebookのコードに非同期を指令するという js.async = true; を足してみた。
どこに足したかというとここなんです。6行目。
<div id="fb-root"></div> <script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.async = true; js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=123456789"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk'));</script>
よくわからないながらもTwitterのコードにも同じような文字列を見つけて足してみた。
結果、少し改善した感じではありました。
しばらくはこれで過ごしていたんですが、でもやっぱり読み込みの遅さが気になります。
そこでもう少し調べてみたら、そもそもSNS絡みのコードをページと一緒に読み込むから遅いんであって、これを遅らせればいい、ということがわかりました。
SNSボタンなんぞは、ページの読み込みや描画が終わってから時間差でゆっくり読み込めば十分であるという考え方ですね。これはいいですね。
でもその方法がわかりません。
方法やスクリプトを書いている記事を漁ってみましたが、そもそもスクリプトとか、何のことやらわかりません。
「あとはご自身の環境に応じて便宜書き換えてください」などと言われても何がご自身なのか便宜とはどこをどうするのか、基礎的なことすらわからないからどうしようもありません。
拝借できそうな具体例を探してまわります。
で、長らく探し続けて最適な記事を見つけました。
デザイン日々独学さんの「Webサイトの読み込み体感速度が2秒くらい上がるかも。SNSボタンは後から読み込め!」という派手派手しいタイトルのこの記事です。たいへん役に立ちました。
記事では、まず最初に概要とそのコードが、次に具体例とそのコードが書かれています。
これは素人にとってとてもありがたい配慮です。なんせ意味がわかります。意味がわからないところは具体例に当てはめて何とかなります。
さっそく、具体例をそのままコピーして自分のサイトで試しましたところ、何とエラーも出ずにちゃん処理されているじゃありませんか。これはすばらしい。大抵はコードをコピぺしても自サイトではエラーが出るもんです。
ただし、思い通りに動いているわけではありません。それは当たり前ですね。設置しているボタンも表示しようとしているdivのcssクラスも違いますから。
一つずつ検証と修正を施します。
以下、「Webサイトの読み込み体感速度が2秒くらい上がるかも。SNSボタンは後から読み込め!」さんの載せているコードをお手本に、どのように変えていったかを記します。
ですので、該当記事とセットでお読みください。
不要なところを消す
まず使用するこちらのサイトには「はてなボタン」はありません。これは不要なので消し去ります。
// はてな (wordpress使用のため、phpタグあり) hatena_btn = '</pre> <div class="htbtn btn"><a class="hatena-bookmark-button" title="このエントリーをはてなブックマークに追加" href="//b.hatena.ne.jp/entry/<?php the_permalink(); ?>" data-hatena-bookmark-title="<?php the_title(); ?>" data-hatena-bookmark-layout="standard"><img style="border: none;" alt="このエントリーをはてなブックマークに追加" src="//b.st-hatena.com/images/entry-button/button-only.gif" width="20" height="20" /></a></div> <pre>' + '<script charset="utf-8" type="text/javascript" src="//b.st-hatena.com/js/bookmark_button.js" async="async">// <![CDATA[ </script>';
これを消しました。そうするとエラーが出ました。
エラーのわけはすぐにわかりました。最初の定義のところや、最後の表示のところに消した部分に関する記述があります。「hatena_btn」というのがそれです。
これらを同じように消してあげて整合性を取らねばなりません。整合性を取り、動作を確認します。動いています。いいぞいいぞ。
ボタン表示を含めない
デザイン日々独学さんのわかりやすい解説とコードで順調に進みつつありますが、自分の環境と大きく異なるところがあります。
自分のサイトでは、スクリプトのコードと、それを表示するコードを分けているのです。
表示するコードを独立させて管理していますから、この場ではスクリプトだけを対象にしたいところです。
var snscode = 'ここにボタン表示の指令'+'ここにスクリプト';
簡単に書くとこういう仕組みらしいですから、前半のボタン表示のところを+記号もろとも消し去ります。
多分ですけど、そもそもは’1行のスクリプト’であるべきところをわざわざ分割して+で繋げているだけでありましょうから、表示部分を消しても問題ないと思われます。
ボタンを表示するための場所はdivでくくったものがすでに用意されています。
ことのついでに、そのdivに「id=snsbox」と名付けました。どんどんお手本に合わせていきます。
で、後から読み込むコードにもともとあるボタン表示がちゃんとついて、動作の確認を取ることができました。
Facebookのコード
次はFacebookです。
うちのコードとぜんぜん違います。なぜでしょう。それは、iframeとhtml5の違いです。お手本のはiframeによるコードで、うちで使っているのはhtml5によるコードです。
facebookのサイトから取得するコード、今ではiframeが没にされてhtml5のコードしか発行してくれていません。
そこで、コードをまるごと差し替えます。
デザイン日々独学さんのサイトではこうなっています。
facebook_btn = ' <div class="fbbtn btn"><iframe src="//www.facebook.com/plugins/like.php?href=<?php the_permalink(); ?>&amp;send=false&amp;layout=button_count&amp;width=100&amp;show_faces=true&amp;action=like&amp;colorscheme=light&amp;font=arial&amp;height=35&amp;appId=202396756503689" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:100px; height:21px;" allowTransparency="true"></iframe></div> ';
iframe用のこのコード部分を、html5のコードにそっくり置き換えます。
facebookのサイトで発行されるhtml5用のコードはこんなのですね。
<div id="fb-root"></div> <script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.async = true; js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=436359929754329"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); // ]]></script>
これをお手本を見ながら当てはめます。IDのところの数字はちゃんと自分のIDにします。 何度か失敗しつつ、このように落ち着きました。
// Facebook facebook_btn = '<div id="fb-root"></div><script>(function(d, s, id) {var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) return;js = d.createElement(s); js.id = id;js.src = "//connect.facebook.net/ja_JP/sdk.js#xfbml=1&appId=436359929754329&version=v2.3";fjs.parentNode.insertBefore(js, fjs);}(document, "script", "facebook-jssdk"));<\/script>';
これはいったい何をしているのかというと、発行されたコードを以下のように変更して放り込んだだけです。
1. 改行を消して1行に繋げます。
2. シングルクォーテーションがある箇所があります。これをダブルクォーテーションに変えます。
3. 最後の
</script>
を
<\/script>
に変えます。
特に「1行に繋げなければならない」ところで嵌まってしばらく停滞しました。
何度も失敗しながらでしたが、できてしまえばなんてことありません。
wordpressとjQueryの問題
何度も失敗したのは、何をどう頑張ってもエラーになるからでした。
ええそうです。正解のコードが書けてもエラーが出続け、それで嵌まってしまったんです。
エラーの原因はコード自体ではなく、jQueryにありました。
デザイン日々独学さんのお手本の最初のほうに注目です。これです。
. . <div id="snsbox"><!-- ここにボタンが現れる --></div> . . <!-- jQuery を Googleから読み込む --> <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <!-- 万が一 Googleが落ちていたら自分のサーバーに置いたjQueryを用意する (Boilerplateテク) --> <script type="text/javascript">window.jQuery || document.write('<script src="js/libs/jquery-1.7.2.min.js"></script>')</script>
これの意味がわかりませんでした。「.」って何ですか。
最初は「.」に意味などないだろうと思って消したんですが、そうするとエラーが出るので、この点が大事な点なのか、と変に納得していたんですがそうではなく、問題はjQueryを読み込んでいるところにありました。
WordPressにはjQueryが内蔵されています。ヘッダで呼び出しも済んでいるはずなんです。
ですので、ここでふたたびjQueryを読み込んでしまうとダブってしまうので駄目なんですね。
Wordpressで使っているプラグインもjQueryを使っていて、そいつとの相性問題も出ました。
ここで停滞して、あれやこれやと検索して読みあさりますと、答えがわかりました。
WordPressのjQueryは特別仕様なので、「$」を使ってはならないということだったんですね。
ははぁ。そうですか、そりゃ知らなんだ。
意味はわかりませんが、お手本の中に一箇所「$」があります。これをどうにかするといいのです。
どうしましょう。こうしました。
$をjQueryに置き換える
いろいろ賢い人の解説を読みますと賢そうな解決策が出てきますが、賢い人のややこしい話は意味がわかりません。その中でひときわ明快な解説を読みまして、それによるともともと「$」は本体の仮の姿であり、本体とは「jQuery」であるからして、「$」を「jQuery」に置き換えればいいと、こういうことらしいのです。
さっそくお手本のjQueryを読み込んでいる箇所を消し去り、スクリプトの中の「$」を「jQuery」に置き換えてみますと、さっ動きました。万歳。
最終的なコードはこんな感じになりました。もちろん、うちで使用している環境に合わせたものですから、他の方はそれぞれご自身の環境に応じて便宜書き換えないといけません。あれ?この言葉って。
<script type="text/javascript"> // 最初に変数をまとめて定義 var google_btn, twitter_btn, facebook_btn; // google google_btn = '<script src="https://apis.google.com/js/platform.js" async defer>{lang: "ja"}<\/script>' // Twitter twitter_btn = '<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");<\/script>'; // Facebook facebook_btn = '<div id="fb-root"></div><script>(function(d, s, id) {var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) return;js = d.createElement(s); js.id = id;js.src = "//connect.facebook.net/ja_JP/sdk.js#xfbml=1&appId=436359929754329&version=v2.3";fjs.parentNode.insertBefore(js, fjs);}(document, "script", "facebook-jssdk"));<\/script>'; // 2秒後<div id="snsbox"></div>の中に上記をまとめて出現させる setTimeout(function(){ jQuery('#snsbox').append(google_btn + twitter_btn + facebook_btn); },2000); </script>
というわけでですね、SNSを時間差で読み込むという大技、大成功ということで、それを実践したサイトはここではなくてMovie Booやチルドレンクーデターサイトです。
記事が増えてきて重くて仕方なかったんですよねえ。どうでしょう。ソーシャルボタンの鬱陶しさが解消されているでしょうか。
→ Movie Boo
→ チルドレンクーデター
改めましてお手本のデザイン日々独学さんのおかげです。
[追記 2015年12月]
書いた当初、コードを表示するプラグインを知らなかったもので、<> ← この記述が
&amp;gt;
みたいになっていました。
その後プラグインを入れたのに内容を修正せずにいたわけで、スクリプト表記がぐだぐだになっておりました。 なんとなく修正しましたが間違いがあるかもしれません。いい加減な記事ですいませんでした。 また、時は流れ、いろんな仕組みで非同期読み込みが当たり前になった昨今です。 ここに書いたのも旬を過ぎた情報になっているかもしれない、ということで追記しておきます。