jQueryと一緒にRequireJSを使ってみる
RequireJSをちゃんと使うべく勉強。
WEB+DB PRESS vol.69に
「RequireJSでらくらくモジュール管理」
というのがあったのでこれを参考にする。
まずはRequireJSのメリット3つ
□カプセル化されたモジュールの定義
AMD(Asynchronous Module Definition)モジュールと呼ばれるカプセル化された再利用性の高いモジュール定義が行える。
AMDはコールバック関数を使って定義するのでグローバル変数に頼らずに他のモジュールを呼び出せる
□ネストした依存関係の自動解決
依存関係が多段にネストしていても利用するモジュールを呼べば自動でRequireJSが依存を解決してくれる。
□非同期読み込みと最適化ツールによるパフォーマンスの向上
非同期に読み込むことでレンダリングのブロックを回避できる。
最適化ツールが用意されている(今回の実験ではやらない)
ではとりあえず書いてみる。
元々記事に記載されていたコードをjQueryを使った
バージョンに書き換えてみる。
RequireJSはここのページの「Sample RequireJS 2.1.2 + jQuery 1.8.2 project」をおとしてくる
※2012/12/07時点です。
ここから先のサンプルコードで使っている「require-jquery.js」は
解凍したフォルダの中の
jquery-require-sample\webapp\scripts\require-jquery.js
を使っています。
■ファイルの構成
.
|– js
| |– component.js
| |– config.js
| |– counter.js
| |– maxheight.js
| |– page.js
| |– require-jquery.js
| |– require.js
| `– util.js
`– page.html
require.jsとrequire-jquery.jsの両方があるけど
jquery使う場合はrequire-jquery.jsがいいらしい。
ただrequire-jquery.jsはrequire.jsとjquery.jsを
連結しただけのものらしい。
でもこうすることでjqueryのプラグインが非同期で
ロードされる前に本体がロードされていることを保障
できるってことらしい。
■page.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <!-- 現在の時刻を表示する --> <h1 id="label"></h1> <div id="clock"></div> <hr /><!-- 単純なjqueryプラグインの実験↓ --> <label>一番大きいdivの高さ</label> <p id="height"></p> <hr /><!-- 複数のライブラリ中でjqueryプラグンが呼び出されたときの実験↓ --> <label>呼び出された回数</label> <p id="count"></p> <script> var require = { // キャッシュの防止 urlArgs: 'bust=' + (new Date()).getTime() }; </script> <script src="js/require-jquery.js" data-main="js/page" async></script> </body> </html>
■js/config.js
define(function() { return { label: '現在の時刻', format: '%Y/%m/%d %H:%M:%S' }; })
■js/util.js
define(function() { function pad2(num){ return ('0' + num).slice(-2); } function formatDate(date, formatStr) { return formatStr. replace('%Y', date.getFullYear()). replace('%m', pad2(date.getMonth() + 1)). replace('%d', pad2(date.getDate())). replace('%H', pad2(date.getHours())). replace('%M', pad2(date.getMinutes())). replace('%S', pad2(date.getSeconds())); } return { formatDate: formatDate }; });
■js/component.js
define(['jquery', 'config', 'util', 'counter'], function($, config, util) { function display($elem){ $elem.text(util.formatDate(new Date(), config.format)); } function render($elem) { display($elem); setInterval(function() { $(this).counter(); display($elem); }, 1000); } return { render: render }; });
■js/page.js
require(['jquery', 'config', 'component', 'maxheight', 'counter'], function($, config, clock) { // configのラベルを表示(config依存) $('#label').text(config.label); // 現在の時刻を表示(component依存) clock.render($('#clock')); // ここから下はおまけの実験 // ページ内のdiv要素で最も高いもののheightを返してみる(maxheight依存) $('#height').text($('div').maxHeight()); // 5秒に1回たまったカウントを表示(counter依存) setInterval(function() { $('#count').countDisplay(); }, 5000); });
■js/maxheight.js
define(['jquery'], function($) { $.fn.maxHeight=function(){ var max = 0; this.each(function() { max = Math.max( max, $(this).height() ); }); return max; }; });
■js/counter.js
define(['jquery'], function($) { var count=0; $.fn.counter=function(){ count++; }; $.fn.countDisplay=function(){ this.text(count); } });
実際に書いてみると以外に簡単に使えるんだなという印象。
自作したライブラリはとりあえずdefineで囲めばいいっぽいし。
defineで囲みたくない場合はshim設定で利用すれば擬似的に
モジュールで使えるということらしい。
後は今回でいうpage.jsの中でKAYACのURL dispatcher的な
ものを使えばよりいい感じになるのかもしれない。
そこそこ規模が大きくても何とかなるjavascriptの設計(URL dispatcherの薦め)
■参考URL
JavaScriptを分割&非同期で読み込めるRequireJS
RequireJS 2.0による依存関係の明示、フォールバック、複数バージョンの混在
勉強会資料シェア Getting Started with RequireJS