2013-12-08

browserify を使い始めるためのファーストステップ 2013 冬

browserify は、ブラウザ JavaScript のためのコードを、Node スタイルのコード(Node 向けの JavaScript コードを書いているかのような形)で記述しておいて、ブラウザ上で利用できるような Javascript コードとして出力してくれるツール。
require() で利用しているモジュール群をすべてアナライズして、それらモジュールコードまですべて都合よい形で同梱してくれる。

リリース当初(3年くらい前)は Node で HTTP サーバを建ててブラウザ用 Javascript コードを返すような仕掛けから始まったはずで、そこから静的ファイルを出力する仕組みが追加されて、現在ではむしろ後者の方がメイン扱いになっている感じになっている。
そうなった背景として、Grunt の登場でその辺りの機能が有効的に参照利用できるようになったり、実際に Grunt を使ってのビルド環境がカジュアルに行われるような土壌が出来上がったからというのが大きいのかもしれない。

今から browserify の利用を始めるべく browserify 側の情報をみても、低レベルなところが中心で戸惑ってしまい躊躇してしまうかもしれない。どんなものかを知るために動かすならば、簡単に利用できる Grunt 経由側のものを知ってしまったほうがよいと思う。
ということで、簡単なサンプルを紹介。

今回利用するファイルとツリーの状態は以下の通り。

@ /
├─ Gruntfile.js
├─ package.json
├─ index.html
├─ main.js
└┬ lib/
├─ foo.js
└┬ bar/
└─ baz.js
view raw tree hosted with ❤ by GitHub


------------

まずは環境作りのための package.json。
モジュールは grunt と、grunt で browserify するための grunt-browserify。
あとはサンプル用スクリプトで使うモジュール例として async.js を指定している。

{
"private": true,
"dependencies": {
"async": "0.2.9"
},
"devDependencies": {
"grunt": "~0.4",
"grunt-browserify": "*"
},
"optionalDependencies": {},
"engines": {
"node": ">= 0.8.0"
}
}
view raw package.json hosted with ❤ by GitHub


記述後、npm install を実行する。

続いて、ブラウザ上で動作させるための JavaScript コードを Node スタイルで記述。
以下のサンプルでは、core モジュールと npm で入れたモジュールを require() で利用しつつ、エントリポイントとなるスクリプトから自前のファイルを require() して読み込んでいる。

var foo = require('./lib/foo.js');
var content = document.getElementById('content');
foo.run([ 3, 10, "foo", "bar", 42 ], function (err, results) {
if (err) throw err;
results.forEach(function (r) {
content.innerHTML += ' ' + r;
});
});
view raw main.js hosted with ❤ by GitHub

var async = require('async');
var baz = require('./bar/baz');
exports.run = function (values, callback) {
async.map(values, function (v, next) {
next(null, baz(v));
}, callback);
};
view raw foo.js hosted with ❤ by GitHub

var format = require('util').format;
module.exports = function (v) {
if (typeof v === "string") {
return format('%s OK.', v);
} else if (typeof v === "number") {
return v * 10;
} else {
return v;
}
};
view raw baz.js hosted with ❤ by GitHub


browserify を実行する Gruntfile.js を用意。

module.exports = function(grunt) {
var pkg = grunt.file.readJSON('package.json');
grunt.initConfig({
browserify: {
dist: {
src: 'main.js',
dest: 'build.js'
}
}
});
Object.keys(pkg.devDependencies).forEach(function (devDependency) {
if (devDependency.match(/^grunt\-/)) {
grunt.loadNpmTasks(devDependency);
}
});
grunt.registerTask('default', [ 'browserify' ]);
};
view raw Gruntfile.js hosted with ❤ by GitHub


grunt を実行すると、build.js が出力される。
中身を覗いてみると、browserify が頑張って構築してくれたブラウザ用 JavaScript コードとして、先ほど自分で記述したコードやアナライズした結果同梱する必要ありと判断された util.fomat や async.js などが含まれている。

適当な HTML ファイルを用意して、この build.js を script タグで読み込むようにする。

<html>
<head>
</head>
<body>
<div id="content"></div>
<script src="build.js"></script>
</body>
</html>
view raw index.html hosted with ❤ by GitHub


実行デモ


先ほど browserify v3 がリリースされたばかりで、記念的な感じで。

上記例は v2 系を動かした結果 (grunt-browserify がまだ v2 を使うため)  なものの、恐らくただ単純に使う分には v3 以降も違いなくいけるんじゃないかと(個人的な期待)。

2013-02-19

MongoDB イン・アクションを頂きました


2012年末、勉強会後の懇親会で玉川竜司さん (@tamagawa_ryuji) と初めてお会い/お話することがあり、その際に話の流れで

「NodeでのストレージにはMongoDBを使う事が多くて触ってるんですけども、小規模なら簡単でも、中大規模になると途端に難しくて…」

みたいなことを言っていたら、

「今度 MongoDB の翻訳本が出るから、これもなにかの縁だし送ってあげるよ」

と言われ、そんなこと初めてだし、わーそうなったらいいなあなどと思っていたら、本当に郵送で送っていただきました。やたー!



……などと、年末の話だったにも関わらず、年明け早々いろんなことがあったせいで今頃のエントリで大変申し訳ございません…。

 
 

ということで、MongoDB イン・アクション (http://www.oreilly.co.jp/books/9784873115900/) の紹介です。
海外ではいくつか出ている MongoDB の書籍ですが日本では単独でのものがなく、これまで MongoDB の日本語情報といえば利用者によるブログ、勉強会、および公式ドキュメントでの翻訳を頼りに進めてきていた感じでした。(でもそれらが比較的充実していたり、はまりやすいポイントをいち早く紹介されていたりと、比較的恵まれた環境だったと思う)

MongoDB イン・アクションでは、MongoDB の基本的なお話、特徴、および利用法について1から紹介していきます。
中身は大きく3つの部に分かれていて、「1. はじめての方のための MongoDB」「2. ショッピングサイトシステムを実例にした利用方法の紹介」「3. 本格運用する際に抑えておくべき要素」となっています。

1, 2 では所々 RDB と比較して「RDB ならばこうだっただろう、MongoDB ではこうするんだ」といった具合に解説が入るので、既に RDB を利用している人であれば、MongoDB におけるアプローチ方法や差異などを把握しながら読んでいく感じになります。リレーショナルなデータであったものについて、RDB で正規化していた事に対して MongoDB での対非正規化であったりそれに伴う設計の流儀などが、2 のショッピングサイトシステムを例として紹介されるので、2 までを読み終えた時点で、簡単な CRUD アプリケーションならば作れてしまう程度に知識はついているんじゃないでしょうか。

3 では、データベースを扱っている人ならば気になるであろう、クエリ最適化(インデックスの話)、レプリカ、シャーディング、バックアップとリストアなどを扱っています。
冒頭に書いているとおり、MongoDB は簡単なデータ構造で規模も小さいアプリケーションならば本当にシンプルに扱えるものの、取り扱うデータが大きくなったり構造が複雑になったりすると知っておかなければならない話が色々あったりします。特にクエリ最適化とシャーディングあたりが重要(そしてはまりやすい)だと思うんですが、きちんとそのあたりが構築例、動作例含めて紹介されているのが良い感じです。

 

全体的にテンポ良く読み進めていける本です。目的に対するクエリ例を逐一紹介してくれるのが嬉しい。
ちょっとだけ気になった点としては「突然紹介され始める○○」みたいなのが何回かあったような。でも変な感じではないので大丈夫。

完全に知識がつくまで、これを見ながらシステム構築する感じなりそう。



以上、MongoDB イン・アクションの紹介でした。
玉川さん、およびオライリージャパンさん本当にありがとうございました。

2013-02-06

新しい Windows PC を組んで Win8 環境にした ー 2013春


最近パソコンの普段使いは完全に Mac に移っているものの、Windows マシンはゲームのために一応持ち続けている。

もうずいぶんと昔に買ったマシンパーツから入れ替えしながらやってはきていたけど、それも 2009年1月 (Warhammer Online のためにビデオとCPUを変えた) を最後に進化は止まっていて、壊れた電源だけは変えたものの、性能的にはもうずいぶんと置いてけぼり状態だった。OS も未だ Windows XP だった。

で、シムシティの新作がこの春に出ることと、近頃の為替に比例してパーツの値段がモリモリ上がっていっているのを眺めていてもう我慢ならん!ということで久々に一機買いしてみた。
  • CPU: Intel Core i7 3770
  • Cooler: ENERMAX ETS-T40-TB
  • RAM: 8GB x 2
  • Mother: ASUS P8H77-V
  • GPU: 玄人志向 GF-GTX660-E2GHD/DF/OC
  • Storage: Intel SSD 335series 240GB
  • Case: Corsair Obsidian 550D

しめて 89,796 円。電源だけ流用。
DVDドライブは、必要なときにUSB接続 (IDE/SATA変換) すればよいと思って買ってない、というか最近はマザーに IDE 端子ついてないんだね。おじさんびっくり状態。
そのくせにデカいケース買ってどうすんの状態だけども、ケースはメンテナンスしやすいに越したことはない。最近の良いケースは本当によく出来ている。これまでの苦労が嘘のようだ。
 

OS は Windows 8。さすがにこの時期から 7 はないだろうということで。(8 が良いものかどうかは置いといて)

以下、 Windows 8 導入後に行ったときの作業メモの写しを紹介。
前述のとおり、メインは Mac で Windows はゲーム用途ということなので、実はそこまでやる事はない。


キーカスタマイズ

利用している Real force にあわせて、レジストリを操作することで低レベルでキーポジションを変更する。

参考:

HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Keyboard Layout
という領域に、新たに Scancode Map というバイナリ値を新規作成。

以下、バイナリ値として次のように設定した。
今回は Ctrl を A の左に、および ESC と半角/全角を入れ替えるというシンプルな変更に留めている。

0000 0000 # ヘッダ
0000 0000 # ヘッダ
0400 0000 # 以下に続くエントリー数を定義。終端のNULLのぶんも含める
1D00 3A00 # 1. CapsLock を Ctrl に
0100 2900 # 2. 半角/全角 を ESC に
2900 0100 # 3. ESC を 半角/全角 に
0000 0000 # 4. NULLによるターミネータ


ショートカットキー

Emacs のショートカットが欲しいので xkeymacs をいれた。


近年ついに64bit版の対応がなされた ( http://d.hatena.ne.jp/kfujieda/20110428/1303924737 )  とのことで、本当に有り難いお話。

XP の頃は窓使いの憂鬱を利用してキー入れ替えやショートカット変更をしていたが、設定ファイルをゴリゴリ書くほどのカスタマイズはもうしないだろう(テキストを書くような作業を Windows に求めていない)ので、のどか ( http://www.appletkan.com/nodoka.htm ) や yamy ( http://sourceforge.jp/projects/yamy/ ) の採用は見送った。ブラウザのアドレスバーで C-a や C-h が効いてくれればそれでよい。


Dropbox

Dropbox のサイトからプログラムをダウンロードしてセットアップ、既存アカウントを設定。気づいたら同期完了していたので出来るやつだ。


Skype

for Windows8 を Windows Store から落とせと言われたが、レビューを見る限り使い勝手が悪いことばかり書いている。
なによりストア利用のためのアカウントを(多分持っているけど)用意するのが面倒だったので、別プログラムとして Skype サイト上で用意されていた Windows Desktop 版というものを入れた。いつもの Skype だった。


Steam

Steam のサイトからプログラムを落としてセットアップ。新しいマシンでの初ログインではメールによる確認キーを求められる。一手間かかるけども安心できる。
早速 Civ5 をいれて DirectX 11 版で起動、その速度をみて満足する。(ちゃんと遊んで、八方美人具合に度が過ぎたのかお隣の大国から喧嘩売られて散る)


Diablo3

いれてない。

2012-10-19

依存するモジュールも解決できる Node/AMD (サーバ/クライアント) 共通化モジュールを書く



このエントリは、 東京Node学園祭 2012 アドベントカレンダー 5日目の記事です。


■ 前置き - AMD とは


AMD (Asynchronous Module Definition) は、Javascript のコードをモジュールとして定義して、非同期ないし遅延ロードするための仕組みです。

http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition (現在、接続が遅い模様)

CommonJS により提唱されたものですが、昨年あたりからクライアントサイド (ブラウザ) で JavaScript モジュールを構築する仕組みとして各所で一気に取り上げられ、現在ではクライアントサイドの主要なライブラリでもサポートされてきている(AMD によるモジュールとして利用できる)状態にあります。

モジュールに依存性を指定する仕組みも用意されています。遅延ロードされますので、依存モジュールの読み込みが完了次第、目的の(依存元の)モジュールの定義処理が実行されます。
比較的カオスになりがちなクライアントサイド Javascript が、このモジュール化によりすっきりしたものになります。

また処理は非同期で行われるため、ブラウザ上での読み込みの速度向上が見込まれます。実際に、Twitter の Web ページの高速化にも一役買ったとの話があります。

Twitter Engineering Blog: http://engineering.twitter.com/2012/05/improving-performance-on-twittercom.html
Publickey による日本語紹介: http://www.publickey1.jp/blog/12/twitter51.html

クライアントサイドで AMD を利用するには、AMD 機能を提供してくれるライブラリを用います。たとえば、 RequireJS があります。

http://requirejs.org/



■ サーバサイド/クライアントサイド Javascript のモジュール共通化


もし仮に Web アプリケーションのサーバ実装を Node.js で行っていて、かつある処理をサーバ/クライアントのどちらでも行いたいとするならば、その処理を行うコードを改変することなくサーバ/クライアントどちらでも実行できればという考えが出てきます。

そこで、その処理のコードを Node モジュールかつ AMD モジュールとして実装しておき、環境にあわせて適切にモジュールとして読み込まれるようにします。


今回は例として、「その年の 1/1 から今日までの日数の回数 hello world を出力する」というつまらない機能を、Node/AMD 共通モジュールとして作ります。

この問題に対して、Lo-Dash (http://lodash.com/) と Moment.js (http://momentjs.com/) の2種類のライブラリを使おうと考えました。
Lo-Dash, moment ともに Node モジュールとして npm で導入できると共に、AMD モジュールとしても利用できるもので提供されています。

実際に実装したコードが次のものです。

(function(define) {
    define('hellodays', ['lodash', 'moment'], function (_, moment) {
        function hellodays() {
            var days = Number( moment().utc().format('DDD') );
            _.times(days, function (d) {
                console.log('Hello, world ! (' + (d + 1) + ' days)');
            });
        }

        return hellodays;
    });
})(
   // 1: AMD
   typeof define === 'function'  ? define :

   // 2: Node
   typeof module !== 'undefined' ? function(id, deps, factory) {
       module.exports = factory.apply(this, deps.map(require));
   } :

   // 3: Plain (window object)
   function(id, deps, factory) {
       var dependencies = [ this._, this.moment ];
       this[id] = factory.apply(this, dependencies);
   });


2行目で実行している define は、AMD API の仕様に基づき Javascript モジュールを定義するための関数です。引数として AMD 内モジュール名 (以後、id と呼びます)、依存モジュールのリスト (以後、deps と呼びます)、およびモジュールの構築を行う関数 (以後、factory と呼びます) を指定します。
モジュール構築関数 factory 内でオブジェクトあるいは関数を返すと、それがモジュールとして利用できるようになります。ここでは、実際に 1/1 から現在日までの日数を算出し、その回数分 hello, world を出力する処理を記述しています。

実際に Node/AMD モジュールのためのコントロールを行っているのは、1行目から定義している即時関数の引数として与えている、13 行目からのコードです。若干分かりやすくなるよう、コメントを明記しています。

もしグローバル空間に define 関数が定義されているのであれば、AMD によるモジュール機構を備えているため、そのまま define を即時関数に与えて実行させるようにします。これで、AMD モジュールとして hellodays が利用できるようになります。

AMD define 関数はないものの、module が定義されているのであれば Node のモジュール機構と見なし、define のような振る舞いをする関数を与えます。
define への引数はモジュール名 id、依存するモジュール名のリスト deps と、モジュール構築のための関数 factory が与えられるわけなので、Node の require を使って deps で指定されている依存モジュールを読み込み、得られたインスタンスを factory の引数として与えます。factory を実行すると構築された関数が返されるので、それを module.exports にセットします。これで、Node でこの hellodays モジュールを require すると、factory で作られた関数が得られます。

最後は、AMD でも Node でもないパターンです。これまでのブラウザ用 Javascript ライブラリであれば、window オブジェクトへ割り当てるくらいはしていることと思います。lodash, moment もそれぞれ _, moment という名称で参照可能になっていることでしょうから、それらを factory の引数に与えてモジュール構築を行います。名称として id が define の引数で渡ってくるので、その値で window オブジェクトの要素の1つとして定義しています。


以上、AMD > Node > plain という優先度でモジュール定義を行うことができるようになりました。
状況にあわせて依存モジュールの実体であるインスタンスが適切に factory に渡っている、factory の結果が利用されている、あたりがポイントになります。




■ 共通モジュールを利用する


サーバサイドである Node ならば次のように利用します。
普通の Node モジュールの利用となんら違いはありません。(require で読み込めるようモジュールパスが解決されている場合)
var hellodays = require('hellodays');
hellodays();

一方クライアントサイドの場合は、AMD が利用できるよう RequireJS を使います。
上記で作成したモジュールが読み込まれ、hellodays 変数として参照可能になってやってきます。
<script src="./scripts/require.js"></script>
<script>
  requirejs.config({
      paths: {
          "lodash": "./scripts/lodash.min",
          "moment": "./scripts/moment.min",

          "hellodays": "./scripts/hellodays"
      }
  });
  requirejs(['hellodays'], function (hellodays) {
      hellodays();
  });
</script>

Jam (http://jamjs.org/) などのクライアントサイドパッケージマネージャを使うと、依存先となるモジュールの導入や、AMD (RequireJS) で読み込むパスの管理などを一手に引き受けてくれるので、もう少し楽に利用できるようになります。
$ jam install lodash
$ jam install moment
<script src="./jam/require.js"></script>
<script>
  requirejs.config({
      paths: {
          "hellodays": "./scripts/hellodays"
      }
  });
  requirejs(['hellodays'], function (hellodays) {
      hellodays();
  });
</script>

最後に、クライアントサイドで AMD を利用しない場合です。必要なファイルをすべて読み込んだ後、直接 hellodays 変数の関数を実行します。利用の機会はほとんどないと思いますが、利用すること自体は問題はありません。
<script src="./scripts/lodash.min.js"></script>
<script src="./scripts/moment.min.js"></script>
<script src="./scripts/hellodays.js"></script>
<script>
  hellodays();
</script>



■ 共通モジュールとして用意する対象について


今回依存モジュールとして利用した Lo-Dash や Moment.js のような、サーバ/クライアント関係なく汎用的に利用できるライブラリなどは、共通するモジュールとして利用できると大きな価値がありそうです。他にもフローコントロールやイベント管理などは同じように共通モジュール化の価値があると考えられます。

一方、自前で提供するサービスのためのコードではと考えると、データの正規化 / 妥当性確認 (Filter / Validator) ルールの共通モジュール化に一定の価値がありそうです。
例えばユーザ情報の更新処理において、あるルールに基づいた妥当性確認をサーバサイドだけでなくクライアントサイドでも行って確認結果をいち早く掲示したい、といった要件がある場合。これまでなら同一ルールながらも異なるコードで実装したり、妥当性確認処理を非同期で逐一サーバと通信して行ったりしていたところです。
共通モジュール化されているならば、妥当性確認処理をクライアントで行い、サーバへ POST されてきた情報も同じモジュールで再度確認する、といったことができます。




■ 備考. テストについて


共通モジュールとして実装されたコードのテストをどうするか?

現在の私の場合はですが、まずは使い慣れた環境による、提供されうる機能のテストを書きます。
すなわち、Node モジュールとして提供されて、Node 上でなんら問題なく利用できるである確信のためのテストを用意します。
その上で、AMD モジュールとして読み込んで利用可能な状態になるかのテストを用意しています。

Node モジュールの amdefine (https://github.com/jrburke/amdefine) を使うことで、Node 上で define を使ったコードが一時的に利用可能になります。
これを用いてモジュールをロードし、読み込んだモジュールが不自由なく(そこまでの機能テストは省略しつつ。機能の妥当性は前述のテストコードで満たされているはずなので。)利用できれば、良しとしています。




■ 備考2. Node の RequireJS モジュールと AMD 採用の是非


実は Node 上でも RequireJS モジュールが用意され、利用することができます。

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

非同期にモジュールを読み込む AMD のための RequireJS ですが、Node の場合は立ち上がったサーバインスタンスが基本的に永続した上でモジュールインスタンスの永続化がコードの書き方次第で容易だったり、Node 本体の require 時におけるインスタンスの再利用性が悪くなかったりといった理由から、その Node モジュールが RequireJS に依存する、というのは必要ないのではないかと個人的には思っています。


2012-10-13

ランダム文字列生成 gachar


https://github.com/kumatch/gachar

ただのランダム文字列生成です。
最近の個人的なブームに沿って、一応フロントエンドでも使えるようにしときました。使うかどうかは別にして。

var gachar = require('gachar');

var string1 = gachar.run(128);

gacha.run(256, function (string2) {
  ....
});


実は最初 crypt なにがし系を使って適当な文字列を作る処理で書いてたんですが、C モジュールを持ってしてもただの Math.random() に速度で勝てなかったという。やっぱ暗号化処理って重いんですねー(当たり前)。

ランダム性能的にはそこまで良くなさそうですが、使い捨てなトークン値などではこれで十分かなと思ってます。
あと、名前は結構気に入ってます。

2012-10-03

runie.js

https://github.com/kumatch/runie

Node で用意された任意変数を、フロント javascript で参照、利用するためのライブラリです。
変数を一旦 DOM 要素として埋め込んで(描写して)、フロントスクリプトで改めて読み込みます。

Jade template
div
  p= title

!{ runie.tag('items', items) }

Front javascript
runie.read('items', function (items) {
    if (items.length) {
     ....
    }
});

これ以前はフロントスクリプト上から ajax で JSON を受け取って読み込んでいたりしてたので遅かったんですが、これを使うようになってから処理が圧倒的に早くなりました(当たり前)。

2012-09-19

フロントエンドパッケージマネージャ bower のメモ


Twitter が先日リリースした、Javascript や CSSなどのフロントエンド向けパッケージマネージャ Bower (http://twitter.github.com/bower/) についての簡単な下調べを行ったときのメモ。


■ Git リポジトリを指定しての導入


bower install コマンドで指定できるのは名前だけじゃなくて、git リポジトリの URL を指定することができる。

  $ bower install git://github.com/kumatch/asyncall.git

末尾にシャープ付きでバージョンを指定すると、ちゃんと git タグのバージョンが使われる(シェルによっては # をバックスラッシュでエスケープすること)。みんなでちゃんとバージョン付けをしよう。

  $ bower install git://github.com/kumatch/asyncall.git#0.1.1


これら方法で導入したパッケージも、bower update で最新のものに更新されることを確認した。



■ component.jsonを使ってのパッケージ管理


component.json ファイルを自身のプロジェクトリポジトリに置いて、そのプロジェクト内で利用しているパッケージ群を定義することができる。

{
  "dependencies": {
    "jquery": "~1.7.2",
    "asyncall": "git://github.com/kumatch/asyncall.git"
  }
}

component.json のあるディレクトリ(あるいは bower 側で辿ることができる場所。マニュアル参照。)で bower install を実行すれば、定義しているパッケージ群を一気に導入できる。


先ほどのように、git リポジトリ URL でのバージョン指定も OK。
注意点としては、dependencies に定義するキーの値は、導入パッケージ側の "name" 要素で指定されている名前とあわせること。そうでないと、導入後の list コマンドでおかしなことになった。



■ bower で導入されることを想定しているコンポーネントの依存性定義


例として、次のような component.json を含んだ git リポジトリがあるとする。
(ここでは git://github.com/kumatch/bower-samples-nop.git とする)

{
  "name": "sampels-nop",
  "version": "0.1.0",
  "main": "./lib/index.js",
  "dependencies": {
    "asyncall": "git://github.com/kumatch/asyncall.git"
  }
}


一方、自身のプロジェクト側の component.json で、このパッケージを利用するよう定義。

{
  "dependencies": {
    "sampels-nop": "git://github.com/kumatch/bower-samples-nop.git"
  }
}


bower install を実行すると、samples-nop パッケージと一緒に、依存している asyncall が導入される。

$ bower list
/path/to/bower-test
├── asyncall#0.1.2
└─┬ sampels-nop#0.1.0
  └── asyncall#0.1.2


$ bower list --paths
{
  "asyncall": "components/asyncall/asyncall-0.1.2.min.js",
  "sampels-nop": "components/sampels-nop/lib/index.js"
}


bower-samples-nop.git リポジトリの component.json を package.json としていても、問題なく(依存性を解決して)導入することができた。従って、npm パッケージとして用意されていて、かつブラウザでも利用可能なもの (Underscore.js とか) は普通に依存パッケージとして指定することができて、導入時にも問題なく解決される。



■ 導入パッケージのエントリポイントをスクリプトで得る


次のようなコードで paths にオブジェクトで受け取ることができた。まだ何も試していないけども、色々と自動化したいならば必要になってくると思う。

var bower = require('bower');

bower.commands.list({ paths: true }).on('data', function (paths) {
    // console.log(paths);
    // …
});