Javascriptファイルを非同期に読み込む$script.jsを使ってみた
Posted by admin at 10:06 日時 2012/06/09
Javascriptの読み込みが遅いのは、ユーザー体験のリッチなウェブページを作るうえで悩むポイントです。特に、Facebook・Twitter・Google+の各スクリプトの読み込みが遅い気がしていました。
<a href="https://twitter.com/share" class="twitter-share-button">Tweet</a> <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>
<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/all.js#xfbml=1"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk'));</script> <div class="fb-like" data-send="true" data-width="450" data-show-faces="true"></div>
<g:plusone annotation="inline"></g:plusone> <script type="text/javascript">// <![CDATA[ (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })(); // ]]></script>
これら3つの埋め込みスクリプトは、一応読み込み速度に関しては考慮されていて、scriptタグをあとから生成するタイプ( document.createElement(‘script’) という記述がポイント)になっています。下記のようにscriptタグのsrc属性に指定してJavascriptを読み込むと、読み込んでいるあいだページのロードをブロッキングするためレンダリングが遅くなるのを回避しているわけです。
<script src="//platform.twitter.com/widgets.js"></script>
さらにGoogle+は非同期読み込みに対応していて( po.async = true; という記述がポイント)、さらに読み込み速度に配慮されているのが分かります。
けど、やっぱりそれでも遅い気がするんですよね…。そこで、受託開発案件で $script.js というJavascriptを非同期で読み込むことに特化したライブラリを使ってみました。まだ公開してないサイトなので実物は見せられないのですが、面白かったのでさっそく記事にしてみました。
$script.js – Another JavaScript loader
https://github.com/ded/script.js
このライブラリを使うと、通常は以下のように書くJavascriptの読み込みが、
<script src="jquery.js"></script> <script src="my-jquery-plugin.js"></script> <script src="my-app-that-uses-plugin.js"></script>
このように書くことができます。
$script('jquery.js', function () { $script('my-jquery-plugin.js', function () { $script('my-app-that-uses-plugin.js') }) })
この書き方で、ページのレンダリングを阻害せず、非同期にJavascriptを読み込むことができ、なおかつ「jQueryが読み込まれてからjQueryプラグインを読み込み、そのあとウェブサイト用のスクリプトを読み込む」というような依存関係のある複数のJavascriptファイルの読み込みにも対応できちゃいます。
そして、Facebook・Twitter・Google+の各スクリプトを$script.jsを使って読み込むコードがこちら。
<div id="fb-root"></div> <script type="text/javascript">// <![CDATA[ $script([ "//platform.twitter.com/widgets.js", "//connect.facebook.net/ja_JP/all.js#xfbml=1", "https://apis.google.com/js/plusone.js" ],"social-js"); // ]]></script>
このコードのいいところは、3つのサイトのスクリプトを非同期で、かつ並行してロードしていること( [“a.js”,”b.js”,”c.js”] のように配列で指定すると並列で読み込める)。これにより体感的にはかなり表示が軽くなったと感じました。まあ、あんまり真剣に検証してないんですが。
実際のツイートボタン等を表示したい部分には、下記のコードを書いておきます。複数あっても問題ありません。
<a class="twitter-share-button" href="https://twitter.com/share">Tweet</a> <div class="fb-like" data-send="true" data-width="450" data-show-faces="true"></div> <g:plusone annotation="inline"></g:plusone>
使い方も分かりやすいし、$script.jsの本体は2KBと軽量だし、受託開発案件で使ってみただけですが、これを応用して軽量にソーシャルボタンを埋め込むconcrete5のブロックを作ろうと思っているところです。