タグ「npm」が付けられているもの

Browserify CDNはよさそう

  • 投稿日:
  • by

先日、Browserifyを使ってみたという記事を書きましたが、 その後、Browserify CDNというもをの知りました。Browserify界隈では普通なのかもしれませんが、Browserifyというのはてっきりローカルで動かすものという先入観があったので、眼から鱗でした。

初めに知ったのは、

https://wzrd.in/

です。 browserify-as-a-serviceとのこと、いいですね。URLも短くてよいです。 説明も分かりやすく、APIも直感的です。

これはいいと思っていたところ、さらに、

https://www.brcdn.org/

を見つけました。 こちらは後発ですが、wzrd.inとの比較が書かれています。 コンパイルしたファイルはAmazon S3に置かれるということで、productionにも使えそうです。 minifyもproductionを想定しているとのことです。

なるほどと思ってhttps://github.com/jfhbrook/browserify-cdnを見直すと、 Heroku installが書いてあったり、キャッシュが消えると書いてあったり、 どちらかというとa serviceであって複数のインスタンスが立ち上がることを想定しているようです。

というわけで、今後はhttps://www.brcdn.org/を積極的に使ってみようかと思います。

今さらながらbrowserifyを使ってみました。 存在は知っていたものの普段はcdnを使ってライブラリを読み込むようにしていたので、 必要性を感じていませんでした。 今回、ライブラリをローカルに保存したかったので使ってみました。 bowerと比較してnpmだけで済むのがいいです。

しかし、npm上のライブラリが対応しているかどうか分からないというのは難点ですね。 実際に使おうとしていたライブラリがうまくラップしていないものがありました。 そこで、browserify-shimを使いました。 これは、CommonJSでexportしていないライブラリをexportしたかのように使えるようにするものです。 関連して、napaを思い出しました。 うまくやればnapaとbrowserify-shimの組み合わせは最強ではないでしょうか。

browserify-shimの使い方はあまり検索しても見つからなかったので、メモしておきます。 基本的にはREADMEに書いてあるのがそのままなのですが、一瞬理解しにくかったです。

以下、package.jsonの中身の書き方です。まず、

{ 
  "browserify": {
    "transform": [ "browserify-shim" ]
  }
}

これが必須です。これにより、browserify-shimが認識されるようです。 transformは他にも用途があるのでしょうか。それも興味あります。 次に、

{
  "browserify-shim": {
    "./node_modules/foo/bar.js": { "exports": "Bar" }
  }
}

これはどのファイルのどのようにラップするのかを記述します。 詳細は調べていませんが、これはbar.jsのファイルの最後に

exports = Bar;

を追加したような感じです。もちろん、function(){}でスコープを切っているでしょうが。 さて、一番悩んだのは、どうやってこれを利用するかでした。 状況としては、./public/javascripts/hoge.jsというファイルでどのように使うかというものです。 これは、

var bar = require('../../node_modules/foo/bar.js');

としたら動きました。パスが違うのが曲者です。

改めて、これはnapaと組み合わせると便利かもしれません。 最近自分でよく使っているcdnとhttp://rawgit.com/の組み合わせに匹敵するかも。


5/13追記。

よりよい設定方法が分かりました。というか単にbrowserify自体の設定方法をよく理解していなかっただけでした。 package.jsonを、

{ 
  "browserify": {
    "transform": [ "browserify-shim" ]
  },
  "browser": {
    "bar": "./node_modules/foo/bar.js"
  },
  "browserify-shim": {
    "bar": { "exports": "Bar" }
  }
}

のように書けば、

var bar = require('bar');

として利用することができました。 分かってしまえば簡単なのですが、browserify-shimのドキュメントだけでは理解できなかったです。

Angularのdependency injectionはminifyに弱いです。 angular.jsのチュートリアルにも書かれています。

https://code.angularjs.org/1.3.8/docs/tutorial/step_05

A Note on Minificationのセクションに、 annotationをつけると書いてあります。

しばらく悩まずこの書式で書いていましたが、これはとても気をつかいます。スペルミスや並び替えをするときなど。なによりも、同じ文字を2回タイプするのは効率が悪いです。

ngminというのは聞いたことがあったのですが、100%変換できるわけではないという噂を聞いて使っていませんでした。今ではng-annotateというツールがあります。

https://github.com/olov/ng-annotate

ngminとの違いも説明されています。うまく行かない場合のためにコメントで明示的に指示できるというのが安心感があります。

これで快適になりました。やはり、自動化できることを人がやるのは無駄ですね。

ng-annotateはminifyをしてくれないので、minifyツールと合わせて使うことになります。今回は、

https://github.com/mishoo/UglifyJS2

を使うことにしました。下記にpackage.jsonを載せます。

{
  "scripts": {
    "minify:main": "ng-annotate -a public/main.js | uglifyjs -c -m > public/main.min.js"
  },
  "devDependencies": {
    "ng-annotate": "*",
    "uglify-js": "*"
  }
}

これで、

npm run minify:main

で動きます。 grunt等を使いたい人は、対応しているプラグインを使えばできるでしょう。

いつも思いますが、nodeではモジュール探しが大変です。

今回は、icalフォーマットを出力するためのモジュールを探します。 icalというのは通称で、通称としては他にもicalendarとかicsとかあって紛らわしいです。iCalというソフトの名称もあるのでなおさら。RFC5545と言えば一意に特定できるでしょう。

npmで探しました。上記のようにタグがicalだったりicalendarだったり統一されていません。それでも、5個見つけました。

  • peterbraden/ical.js これはパーザしかなく、今回の目的には使えず。
  • tritech/node-icalendar Staræ•°44でトップ。しかしIssue#5が無視されているのが気になるところ。
  • sunrise/vobject-js vobjectという名前なので一瞬分からない。新しそう。
  • shanebo なんとイベント一つ分しか出力できない。
  • sebbo2002/ical-generator APIはシンプルで分かりやすそう。しかし、save, saveSync, serveは余計な機能ではないか。

セオリー通りにいくとStar数トップのnode-icalendarでいくのですが、Issue#5が気になるのとドキュメントが貧弱なのがマイナスポイントです。ドキュメントの貧弱さは自分のプロジェクトをみると、人のこと言えないですが。

今回は、vobject-jsで行くことにしました。現時点でStar数2!今後の発展に期待します。

昨日、 NodeとAngularを使ってTwitterクローンを15分で作るスクリーンキャスト を書いたのですが、ライブラリの紹介をし損ねたので紹介します。

そもそもの動機は、Twitterクローンを簡単に作りたいと思ったことが発端です。 そこで、なにかいいライブラリはないかと色々調べたら、Railsもどきのフルスタックフレームワークがいくつか見つかりました。

他にもいっぱいあるのですが、気になったのがこのあたりです。

ところが、なんと言うかAngularJSを使おうとするとこれらのライブラリはオーバースペックな感じがするのです。Ruby on Railsのようにデファクトが一つある状態であればいいですが、もどきがいっぱいある状態ではコンベンションも統一感がなさそうです。

Angularを前提とするのであれば、フレームワークではなくもっとシンプルなライブラリがあればいいのではないかと思いました。それでもって、面倒なことはそのライブラリが引き受けてくれるような。

そこで、TwitterやFacebookのようなSNSのサイトを作ることに限定したライブラリを作りました。node.jsではexpress.jsがほぼデファクトなのでexpressのmiddlewareとして作りました。middlewareにすることで、単一のフレームワークに依存することなく、他のアプリにアドオンする形で導入できます。

面倒な、認証や権限管理の機能はライブラリが面倒みてくれます。 現状では、Facebook認証と、標準的な権限管理(ownership based)の機能が用意されているだけですが、プラグインとして他の認証や権限管理の機能を追加できるようになっています。 また、通知(メールアラートなど)の機能も今後追加してきたいと考えています。

このライブラリを使うと、フロントエンドを作るだけですぐサービスできます。Railsのようにデフォルトがないので作らないとなにもできないのですが、Angularに慣れていればコンベンションを意識してコーディングするよりもずっと楽かもしれません。

まずは、 こちら からスクリーンキャストを見てみると雰囲気が分かるかもしれません。 もしかしたら、分からないかもしれません。

ソースコードは、

https://github.com/dai-shi/social-cms-backend

にあります。


8/7追記。

最近知ったのですが、http://sproute.io/というフレームワークもあるようですね。 こちらは比較的SNSに特化したようなフレームワークであるようです。 ほとんどコーディングなしでTwitterクローンが作れるようです。 でも、$99って。

今回は、npm周りのTIPSです。特に新しい知見ではないのですが、メモのために書いておきます。

node.jsのパッケージマネージャであるnpmは依存パッケージの解決をしてくれます。依存パッケージは、package.jsonに書いておきます。

例えば、expressを使う場合、

"dependencies": {
  "express": "*"
}

のように書きます。バージョン番号を指定しておきたい場合もあります。

"dependencies": {
  "express": "3.1.0"
}

のように書きます。他にも不等号やチルダを使ってバージョン番号の範囲を書くこともできます。今回はそのあたりは詳しく書きませんが、package.jsonにはバージョン番号の範囲を書いておくことがおすすめです。node.js関連のパッケージはまだ発展途上で仕様が変わることがよくあるからです。そうでなくても、">=3.0.0"などと書いておけば、"3.0.0"では動いたのだということが分かってよいかもしれません。

さて、本題です。依存パッケージがnpmに登録されていない場合はどうすればよいでしょう? 一つの答えは、登録してしまえばよいのです。が、登録したくない場合もあります。今回そのようなケースがありました。それは、GitHubでforkした場合です。将来的にはPull Requestして取り込んでもらうつもりなら、npmに独自バージョンを登録するのはうまくありません。そこで、npmに登録されていないけれど、依存パッケージとして使いたいときにどうするかという話です。

GitHubを使うとしても方法は2通りあります。一つは、tarballで取得する方法、もう一つは、gitプロトコルで取得する方法です。

前者は、

"dependencies": {
  "jsdom": "https://github.com/dai-shi/jsdom/tarball/3bb5b24c5e"
}

のように書き、後者は、

"dependencies": {
  "jsdom": "git://github.com/dai-shi/jsdom.git#3bb5b24c5e"
}

のように書きます。

どちらがいいのでしょう? よく分かりません。 試しに一回だけ、npm installの時間を計測してみました。 結果、前者が11秒、後者が14秒でした。 gitプロトコルの方がオーバヘッドがあるのかもしれません。 httpプロキシしか使えない場合は、前者に決まりですね。 GitHubがtarballのURLを廃止したら(ZIPのURLはリンクがありますが、tarballってどこまでオフィシャルなのでしょう?)、後者に決まりですね。

今のところはどちらでもよいのかもしれません。


10/20追記。

"https://github.com/dai-shi/jsdom/tarball/3bb5b24c5e"

の代わりに、

"https://github.com/dai-shi/jsdom/archive/3bb5b24c5e.tar.gz"

と書く方法もあるようです。こっちの方がオフィシャルな感じがしますね。