Mainly Devel Notes

Twitter, GitHub, StackOverflow: @ovrmrw (short hand of "overmorrow" that means the day after tomorrow)

Node.js環境だけどjspmを使うことでブラウザでもrequireを使いこなす!(ミニファイもするよ)

Node.jsにおいてrequireとは"サーバーサイド"でJavaScriptモジュールを読み込むための宣言で、クライアントサイド(フロントエンド)では使えない。

これが一般論ですね。せっかくnode_modulesフォルダにjsファイルをたくさんダウンロードしてあるんだからそれをブラウザでrequireすればいいじゃん!って誰しも一度は考えると思いますが、数時間から数日の格闘の末、それは出来ないのだと思い知ることになります。Node.jsを使う者の宿命です。
ところが

jspmというパッケージを使うことで"クライアントサイド(フロントエンド)"でもnpmからダウンロードしたJavaScriptモジュールをrequire出来る!

そんな魔法があるんです。詳しくは公式サイト:jspm.ioで。Browserifyは使いません。
(node_modulesフォルダから読み込むわけじゃなくて別にダウンロードしたjsファイルを読み込むんですけどね)
実を言うとnpmだけじゃなくgithubからもダウンロードできます。この2か所から好き放題jsファイルを持ち込めるのでまあ不自由しないですね。
bundleというさらなる魔法を使わないとミニファイされていないjsファイルを読み込むことになるので動作が遅いのが特徴(!)ですが、bundleを使えば大丈夫。かなり速くなる多分。
順を追って説明すると、

まず-gを付けてjspmをインストールします。

npm install -g jspm

次にgithubアカウントで認証しておきます。これをしないとjspm実行時にエラーを量産します。なぜならgithubから大量のダウンロードを行なってAPI制限を超えることになるから。

jspm registry config github

プロジェクトフォルダに移動して下記のコマンドを実行します。package.jsonにjspmの記述を加えることになるのですが、よくわからなければ全てデフォルトで進めます。

jspm init

あとはブラウザで使いたいパッケージをひたすらダウンロード!バンドル(ミニファイ)!最初の1行以外はbundleコマンドで、"あるモジュールを使うときに必要になる別パッケージも一緒にした上でミニファイしつつconfig.jsにも記述をinjectする"ということをモジュール別にやっています。

jspm install -y css json jquery moment d3 knockout angular bootstrap font-awesome aurelia-bootstrapper lodash npm:chai npm:sinon npm:toastr npm:q npm:async npm:rx npm:xhr bluebird &&
jspm bundle css + json bundle/plugin.js --minify --inject &&
jspm bundle jquery   bundle/jquery.js --minify --inject &&
jspm bundle moment   bundle/moment.js --minify --inject &&
jspm bundle d3       bundle/d3.js --minify --inject &&
jspm bundle knockout bundle/knockout.js --minify --inject &&
jspm bundle angular  bundle/angular.js --minify --inject &&
jspm bundle bootstrap bundle/bootstrap.js --minify --inject &&
jspm bundle aurelia-bootstrapper bundle/aurelia-bootstrapper.js --minify --inject &&
jspm bundle lodash   bundle/lodash.js --minify --inject &&
jspm bundle toastr   bundle/toastr.js --minify --inject &&
jspm bundle q        bundle/q.js --minify --inject &&
jspm bundle async    bundle/async.js --minify --inject &&
jspm bundle bluebird bundle/bluebird.js --minify --inject &&
jspm bundle rx       bundle/rx.js --minify --inject

さあ後はフロントエンドで使うJavaScriptファイル内で好きなようにrequireしましょう。
TypeScriptを使っているなら、tsdで定義ファイルをダウンロード済みであればimportでも書けます。
この簡単さは一度覚えるとクセになりますね。私はもうこれ以外の方法でフロントエンドを書きたいとは思わないです。

// JavaScriptの場合
var $ = require('jquery');
var _ = require('lodash');
var myModule = require('./myModule') // 同一フォルダにあるmyModule.js
// TypeScriptの場合
import $ = require('jquery');
import _ = require('lodash');
import myModule = require('./myModule') // 同一フォルダにあるmyModule.ts

jspmによって作成されたconfig.jsの記述に従ってちゃんと必要なモジュールを読み込んでくれます。それもミニファイされた方を。
ただし最初に読み込むHTMLの中で2つのjsファイルを必ずロードすること。このへんはよくわからなければGoogle先生に聞いてください。

<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>

jspmの公式wikiにも必要なことは大体書いてあります。↓