hakobera's blog

技術メモ。たまに雑談

Heroku で package.json で指定した任意のバージョンの Node.js を 動かす方法

2012/8/7 追記

Heroku が公式で package.json での Node.js/NPM のバージョン指定に対応したので、現在は以下の方法は必要ありません。普通に package.json の engines に利用したいバージョンを書けばOKです。

以下の情報は古いです。

本日、開催された Heroku JP Meetup #3 で話してきた内容です。
内容としては去年の12月の東京Node学園3時限目のLTの進化版で、package.json の engines の指定を変えることで、Node.js のバージョンを切り替えられる公式の versions ブランチの利用法について解説しています。

heroku/heroku-buildpack-nodejs at versions · GitHub

これでもう Node.js の超速バージョンアップも怖くないですね。

おまけ

Node.js v0.7.3 も使える自分の Fork

hakobera/heroku-buildpack-nodejs · GitHub

nvmw で npm がインストールできない問題を修正しました

hakobera/nvmw · GitHub

1週間前に対応したんですが、念のため、こちらでも告知しておきます。
主な変更点は以下の通りです。

  • npm がインストールできなくなっていた問題を修正
    • npm の git リポジトリの構成変更に伴いインストール方法を変更
    • npm をビルドしていたが、ビルド済みのバイナリをダウンロードして展開するだけにした

上記変更により、インストール時間が大幅に短縮されました。

アップデート方法

$ cd [nvmw を clone したフォルダ]
$ git pull

npm の Windows コンパイル済みバイナリの場所

以下の場所から npm の Windows コンパイル済みバイナリが取得できます。
普通にインストーラ使う分には必要ないでしょうが、豆知識です。

http://npmjs.org/dist/

Play Framework で複数データベースに接続する方法

Play Framework 1.2.4 では、標準の機能で複数データベースに接続することができません。
ただし、希望としては上がっていて、実は 1.3 では実装される予定です。

#706 Multiple database/JPA support - Play framework 1.0 (now in maintenance mode) - play

しかし、現在のプロジェクトでどうしても複数のデータベースに接続する必要がある要件があったので、1.3 で実装される予定の機能をバックポートして使っています。

メモがわりにその方法を書いておきます。

注意点

  • データソースを複数管理するところまでしかやっていません
    • なぜなら Doma を使っていて、JPA を使っていないから
  • JPA も上記 branch では対応しているので、できるはず(未検証)

706 チケットの修正ブランチをみつける

mbknor/play at lighthouse-706-patch · GitHub

差分ファイルを取ってくる(JPAの部分は除く)

面倒なので gist に貼っておきました。これをまとめて plugins パッケージのおいてください。
play.plugins は app フォルダ直下においてください。

https://gist.github.com/1716464

設定ファイルを書き換える

この書式は 1.3 になっても使えるはずなので、バージョンアップも安心ですね。

# デフォルトDB
db.url=${DB_URL}
db.driver=oracle.jdbc.driver.OracleDriver
db.user=${DB_USER}
db.pass=${DB_PASS}

# 2個目のDB
db_other.url=${OTHER_DB_URL}
db_other.driver=org.postgresql.Driver
db_other.user=${OTHER_DB_USER}
db_other.pass=${OTHER_DB_PASS}

"db_" の後に任意の文字列を指定する。この文字列が DB を特定する ID となります。
上記で言うと、"other" が ID となります。

Doma から使う

DB.datasource を DB.getDBConfig("ID").getDataSource() に変更します。
DB.getDBConfig("play").getDataSource() だとデフォルトDBが取得できます。

public class ReportDBConfig extends DomaAbstractConfig {

	protected static final LocalTransactionalDataSource dataSource = createDataSource();

	static JdbcLogger jdbcLogger = defaultJdbcLogger();

	protected static final Dialect dialect = new PostgreasDialect();

	@Override
	public DataSource getDataSource() {
		return dataSource;
	}

	@Override
	public Dialect getDialect() {
		return dialect;
	}

	@Override
	public JdbcLogger getJdbcLogger() {
		return jdbcLogger;
	}

	protected static LocalTransactionalDataSource createDataSource() {
		return new LocalTransactionalDataSource(DB.getDBConfig("other").getDatasource());
	}

	public static LocalTransaction getLocalTransaction() {
		return dataSource.getLocalTransaction(jdbcLogger);
	}

}

以上です。

僕の考えた最強の Node.js Document Viewer

自分がNode.js でプログラミングをする際に、必ず参考にするページがあります。それは Node.js の公式ドキュメントです。

Node.js v0.8.12 Manual & Documentation

バージョンアップにも追随して、最新の情報が得られるので、書いている人には頭が上がりません。情報量も十分です。(たまに空っぽのページとかありますが)

ただ、このドキュメントを見たことある人ならわかると思いますが、すごく見難いのです。より具体的にはナビゲーションが良くないのと、検索がない、という2つの難点を抱えています。

というわけで、この問題を解決する Document Viewer を作りました。
名付けて 「YAND」=「Yet Another Node.js Document Viewer」です。

Yet Another Node.js Document Viewer

[追記] 日本語訳版 も公開しました

こんな感じでカテゴリをツリー表示できたり、
f:id:scalar:20120130013827p:image:w640

こんな感じでカテゴリ、サブカテゴリで検索して表示できたりします。
f:id:scalar:20120130013828p:image:w640

ここ頑張った

iPad で快適に見られることを優先して作りました。デュアルディスプレイがない環境で、ノートPC の横に iPad を置いて、ドキュメントを見るというシチュエーションに最適です。アイコンも用意したので、是非ホーム画面に置いてやってください。

iPad で使った時のイメージ

参考にした jQAPI だと、検索フィールドに毎回フォーカスを移すので、項目をクリックするたびにキーボードが出てきて使いにくいので、その機能は実装していません。PC で jQAPI に慣れている人は、そこ使い勝手違うのでご注意を。

あわせて読みたい

Cloud9 が提供している以下のマニュアルも良いと思います。こっちは Cloud9 上で動くサンプルコードとかもありますし、メソッドとプロパティが分けて書いてあってわかりやすいです。

Node.js Reference Guide

uglify-me : UglifyJS のフロントエンドを作った

既にあるような気もするのですが、ちょっとだけ特殊な要件に対応したかったので、uglify-me という JS 圧縮ライブラリである UglifyJS のフロントエンドを Node.js で組んでみました。

hakobera/uglify-me · GitHub
デモ

以下のようなケースにマッチします。

  • ビルドサーバや、各開発者のマシンに Node.js が様々な理由で入れられない
  • Closure Compiler Service API で圧縮するのは、セキュリティ上の理由などでダメだと言われた
  • 圧縮用処理がシェルスクリプトだけで記述できなければいけない

ようするに、既存のアプリ、インフラ、開発環境にほとんど手を加えずに、JS の圧縮を実現するにはどうすれば良いか、という思想で作ってあります。上記のケースに当てはまらない場合、普通に UglifyJS の CLI か、Closure Compiler API を呼べば良いと思います。

使い方

clone してきて、npm インストールして、起動するだけです。

$ git clone git://github.com/hakobera/uglify-me.git
$ cd uglify-me
$ npm install
$ node app.js

実運用する場合は forever などで起動してください。環境変数で起動するポート番号も変更できます。

$ PORT=9000 forever app.js

画面はこんな感じです。

f:id:scalar:20120126024714p:image:w640

現状の出力結果は以下のコマンドの出力結果と同等です。

$ uglifyjs -nc source.js

圧縮処理を行うシェルスクリプト

uglify-me の本命はこっちです。画面なんてデバッグ用のおまけです。

  • アプリのデプロイ前に JS を圧縮したい
  • でも、ビルドサーバには標準的なコマンドしか入っていない
  • ローカルネットワーク内の別のサーバにアクセスすることはできる

この制約下で複数の JS ファイルを1つのファイルにまとめて、圧縮するまでを実現するシェルスクリプトとしては以下のようなものを組みます。

ここでは uglify-me を http://uglifyserver:9000 で運用していると仮定します。

uglify.sh

#!/bin/sh
CURRENT=$(cd $(dirname $0) && pwd)

files=''
num=1

echo "Find uglify target files in $CURRENT/$1"
for JS in `ls $CURRENT/$1/*.js`
do
  files="$files -F f$num=@$JS"
  num=`expr $num + 1`
  echo "found $JS"
done

echo "curl $files $2"
curl $files $2 > $3
$ uglify.sh javascripts http://uglifyserver:9000/uglify app.min.js

というわけで、これで複数 JS ファイルの連結から、圧縮までできました。

単純に1ファイルのみを圧縮したい場合は、以下で実現できます。

$ curl -F f=some.js http://uglifyserver:9000/uglify > some.min.js

まとめ

  • uglify-me は UglifyJS のフロントエンド
  • インハウス(社内限定とか)で圧縮サーバを手軽に立てるのに便利
  • curl が入っていれば良いので、利用する側の環境構築がほぼ不要

tail.io - 標準入力をブラウザで tail -f できる htmlcat のクローンを Node.js + Socket.IO で作った

標準入力をブラウザで tail -f できる htmlcat というのを書いた - NaN days - subtech

この記事をみて便利そうだったのですが、Perl 詳しくなくて動かし方がよくわからなかったので、勉強がてらに Node.js + Socket.IO でクローンを作ってみました。npm モジュールとして登録してあるので、以下の方法でインストールできます。

$ npm install tail.io -g

コマンドラインツールなのでグローバルインストールしてください。これで tailio というコマンドが使えるようになります。

(追記) Socket.IO のデバッグログを標準で出力しないようにしました。また、--port オプションでポート番号を明示的に指定することもできるようにしてみました。既にインストールした人は npm update tail.io -g でアップデートしてみてください。--verbose オプションでデバッグログを出力することもできます。

本家と同じく --exec オプションに対応しているので、Mac で以下のコマンドを実行すると、サーバ起動と同時にブラウザが立ち上がり、そこのログを tail した結果が出力されます。

$ tail -f access.log | tailio --exec open
   info  - socket.io started
Server listening on port 10631
open http://0.0.0.0:10631

カラーコード周りはなんか上手く動いていませんが、用途としては間に合っているので気が向いたら直します。

参考記事

空きポートを探す emptyPort の実装は sugyan さんの記事 を参考に、標準入力 (ReadableStream) から1行ずつ読み込む LineReader の実装は koichik さんの記事を参考にさせてもらいました。

Node.js 入門者向けチュートリアル テストもあるよ

先月、学生向けの無料講義を開催している TechHUB.jp で Node.js の講義をやりました。

そこで利用した講義資料(正確には補足資料)を、最新の Express と mocha でも動くように修正したので、せっかくなのでブログでも周知しておきます。

Node.js で作るリアルタイム投票アプリ

実際はよくあるリアルタイムに結果が反映されるアンケートシステムなのですが、そのまま Heroku にデプロイできて、実際のアプリケーションっぽくて、テストまで網羅したチュートリアルがなかったので、書いてみました。

Node.js 入門する人の参考になれば良いなと思います。

以下のようなアンケートが作れます。

Node.js 入門について | rtvote