node-chromeを一日いじくり回してわかったこと
今朝方
http://www.moongift.jp/2013/02/20130216-2/
という記事を見つけた。
簡単にいえばnode.jsのUI部分をchromeに任せるようなものを作っちゃおう!って代物
過去にこういうことをやろうとしてchrome-extensionを作って挫折したりlocalhostの方をブクマしてたり色々やってた自分には朗報だったので早速node-chromeを触ってみた。
まずは普通にインストール
$mkdir node-chrome-sample $cd node-chrome-sample $npm init $npm install node-chrome
windowsだとインストール時にエラーが出る。ここについては後述するが、簡単に言うとエラー出ても問題なく動くっぽいのでこの場ではひとまず気にせず進める。
ソースを見てみる
https://github.com/hij1nx/node-chrome
メインとなるのはlib/index.jsだけでとても簡素。
肝になっているのは
var args = [ '--app=http://localhost:' + (opts.port || 8080) + opts.index, '--force-app-mode', '--app-window-size=' + (opts.width || 1024) + ',' + (opts.height || 760), '--enable-crxless-web-apps', '--user-data-dir=' + __dirname ];
このあたり。
なるほど。appモードとして起動するのか。その後のほうはサーバー起動をしてるみたい。
user-data-dirも別になっているのでchrome通常起動時とは独立した状態になっている。
デモを動かす
node-chrome/exampleにサンプルがあるのでとりあえずサンプルを起動
$cd node_modules/node-chrome/example $node demo
ん?動かん。
とソースを見ると
: var opts = { runtime: "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome", :
あー・・・はい。すいません。macなんて高貴なもの持ってないんです。でも警告ぐらい出してくれても・・・
なので下記のように書き換え
: var opts = { runtime: process.env.LOCALAPPDATA+"\\Google\\Chrome\\Application\\chrome.exe", } :
再度起動。
動く。うむ。問題ない。
runtimeを決めてくれないのはなかなか痛い。パッケージで配布するときに困りそう。
とりあえず自分の何かをおいてみる。
demoが問題なかったのでちょっと簡易に作ってみる
index.js
var opts = { runtime: process.env.LOCALAPPDATA+"\\Google\\Chrome\\Application\\chrome.exe", files: "./view", port: port, index: "/index.html", }; var fs = require("fs") var client = require(".server.js"); cn(opts, function(websocket, chrome) { console.log("foo") chrome.on('exit', function (code) { process.exit(0); }); });
view/index.html
<html> <body> foo </body> </html>
で、起動
$node index.js
・・・・あれ?console.log(foo)としているのでコンソール上になにかしら出力がありそうなのに黙りこくられる。なんで・・・?
コードをもっかい見てみる
var wss = new WebSocketServer({ server: httpserver }); wss.on('connection', function(ws) { callback.call(this, ws, chrome); });
ハッ!callbackがwebsocketコネクション確立後に来ている!なんてこった!*1 *2
確かにdemoもwebsocketコネクションやっとる。
なのでwebsocketへの接続を追加。
<html> <script> var ws = new WebSocket("ws://localhost:8080"); </script> <body> foo </body> </html>
これで再度起動してみたら動く。うん。動いた・・・
言いたいことはあるけどまとめにて後述。
小ネタとか。
色々やってみて気づいたこともあるのでメモ。
ウィンドウサイズ
ウィンドウ画面のサイズが起動時に固定されているので
画面をサイズを変えて閉じる→再起動 とすると元の大きさに戻ってしまう
'--app-window-size=' + (opts.width || 1024) + ',' + (opts.height || 760),
という部分をコメントアウトしてやると保存されるようになるのでこれはぜひオプションが欲しいところ。*3
まとめ
- 最終的に起動されたときの感じはすげえいい。素敵。
- ただ結構不満がいろいろ・・・
- モジュールの方針としてchromeをうまいこと起動するだけにしてはruntime必須とかでちょっと気が効いておらず、サーバー周りについてはwebsocket部分に関してはws強制で自由度効かなくて辛い感じがあってちょっとそのまま使うのは辛い。
- どういうモジュールとして振りたいのか図りかねるので何かpull request投げづらい感強い。
- 個人的にはchrome起動のモジュールとして特化してくれたらありがたい。
- どういうモジュールとして振りたいのか図りかねるので何かpull request投げづらい感強い。
- runtimeの指定をうっかり間違うと無言で黙りこくられて捗らない。
- wsがwindowsでエラー出るしあんまり使いたくない。どうせローカルなんだしsocket.ioとかでも良いしなあ感。*4
- callbackイベントがwebsocketのconnection確立後に発動してるのでchromeの起動に成功したけどサーバー起動に失敗した時はchrome終了するとかも出来ないの辛い。
- モジュールの方針としてchromeをうまいこと起動するだけにしてはruntime必須とかでちょっと気が効いておらず、サーバー周りについてはwebsocket部分に関してはws強制で自由度効かなくて辛い感じがあってちょっとそのまま使うのは辛い。
- コード量も大したことないので今のところprocess.spawnして自前するという選択肢もありそう。
- 兎にも角にもchromeの起動部分は超有用なのでガンガン使って行きたい。