話題の記事

RequireJSでTwitter Bootstrap(jQuery)を非同期ローディングしてみる

2013.02.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、すどーです。

RequireJSでjQueryやjQueryプラグインの非同期ローディングを試してみました。
最近は大規模な構成になると、「ちぢめる、まとめる、かためる(minify, combine, compress)」のが主流のようです。
ですが小中規模な構成や、依存関係にあるフレームワークなども多くあるので、簡単な使い方だけでも覚えておくと便利かと思います。

RequireJS:

http://requirejs.org/
RequireJS API:

http://requirejs.org/docs/api.html

RequireJSの主な特徴

  1. モジュール化(AMD APIをサポート)
  2. 非同期ローディング
  3. OPTIMIZERによる最適化

1. モジュール化(AMD APIをサポート)

AMD(Asynchronous Module Definition)はCommonJSのモジュール規約です。
詳細は下記のリンクを参照してください。僕は「えーえむでぃー」って読んでます。
2次元のキャラが発声してたらかわいいですが、僕は3次元の残念な感じの人なのでアウトです。
「あむど!」って叫んでる人は軽く中二病なので恋しててください。僕はモリサマーが好きです。

CommonJS: JavaScript Standard Library:

http://www.commonjs.org/

なんじゃそりゃって感じですが、この規約に準拠していればどんなモジュールでも以下のメリットが得られるようです。

  • 依存関係のあるモジュールも含めて非同期にロードできる
  • RequireJS以外のローダーでも簡単に使えて互換性が高い

互換性が高いため、jQueryに限らずAMD APIをサポートするライブラリと組み合わせて使うことができます。
なお、互換性のないライブラリも使えるようですが、改造するかshimの設定が必要なようです。
(※ jQueryは、1.7以降からサポート)

jQuery 1.7 Released | Official jQuery Blog:

http://blog.jquery.com/2011/11/03/jquery-1-7-released/

2. 非同期ローディング

非同期ローディングってことは、レンダリングの邪魔をしないので高速化につながりますね。
速さは正義です。力もたぶん正義ですが、速い方が個人的にはカッコいいと思います。
つまり速さも力強さもあるモルジアナさんが可愛すぎて最強ってことですね。

3. OPTIMIZERによる最適化

モジュール同士(複数の外部ファイル)を1つのファイルにまとめたり、サイズを縮小(minify)してくれます。
ネットワーク負荷の軽減に役立つため、高速化につながります。
ちゃんと最適化していかないと色相がにごって犯罪係数が上がってしまいますね。

基本的には同梱されているr.jsをnode.jsやRhinoと合わせて利用しますが、2.1.2以降からブラウザでも動作をサポートしたようです。
なお、今回は非同期ローディングが目的なのでOPTIMIZERは利用しませんが、興味がある方は下記を確認してください。
僕も勉強中だったりします。

RequireJS Optimizer:

http://requirejs.org/docs/optimization.html

使ってみた

以下の構成でデモを作ってみました。

構成など

  • RequireJS 2.1.4
  • jQuery 1.8.3
  • Twitter Bootstrap 2.2.2
RequireJS:

http://requirejs.org/docs/download.html#requirejs
jQuery:

http://jquery.com/download/
Twitter Bootstrap:

http://twitter.github.com/bootstrap/

それぞれダウンロードし、今回はこのように配置します。一部必要に応じてリネームしています。
*印のついたファイルは新規作成したファイルです。

なお、index.htmlは「Bootstrap, from Twitter」と「Javascript · Bootstrap」のModalsに記載されているサンプルをベースに作成しました。

ファイル構成

assets/
    js/
      lib/
        jquery-1.8.3.min.js
        bootstrap.min.js

      require.min.js
      app.js *
      app.norequire.js *

    css/
      bootstrap.min.css

index.html *

index.html

<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
...
</div>

<div class="container">
...
	<!-- Button to trigger modal -->
	<a href="#myModal" role="button" class="btn" data-toggle="modal" id="myModalButton" style="display: none;">Launch demo modal</a>
</div>
<!-- /container -->

<!-- Modal -->
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
...
</div>
<!-- Le javascript
  ================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="./assets/js/require.min.js" data-main="./assets/js/app.js"></script>
<!--<script type="text/javascript" src="./assets/js/lib/jquery-1.8.3.min.js"></script> -->
<!--<script type="text/javascript" src="./assets/js/lib/bootstrap.min.js"></script>-->
<!--<script type="text/javascript" src="./assets/js/app.norequire.js"></script>-->
</body>
</html>

14行目でボタンの初期表示を隠した状態にしています。
25行目でrequire.jsを読み込み、"data-main"属性でメインのJavaScriptファイルを指定します。
その下のコメント行は、RequireJSを利用しない場合の記述ですので比較してみてください。

assets/js/app.js

requirejs.config({
    // pathsオプションの設定。"module/name": "path"を指定します。拡張子(.js)は指定しません。
    paths: {
        "jquery": "lib/jquery-1.8.3.min",
        "jquery.bootstrap": "lib/bootstrap.min"
    },
    // shimオプションの設定。モジュール間の依存関係を定義します。
    shim: {
        "jquery.bootstrap": {
            // jQueryに依存するのでpathsで設定した"module/name"を指定します。
            deps: ["jquery"]
        }
    }
});

// require(["module/name", ...], function(params){ ... });
require(["jquery", "jquery.bootstrap"], function ($) {
    $('#myModalButton').show();
});

assets/js/app.norequire.js

(function($) {
	$('#myModalButton').show();
})(jQuery);

デモ

ロードが完了した時点でボタンが表示され、クリックするとモーダルウィンドウを表示されます。

まとめ

html側で<script>タグの記述が少なく、とてもすっきりしました。
これぐらいのデモではレンダリング速度の向上など感じられないかと思いますが、少し複雑な構成になった場合に期待できそうです。
依存関係が明確になり、管理もしやすくなるためメンタルにも優しいですね。
基本的な使い方だけでもメリットは多く得られますので、まずは小規模な構成から試してみてください。