はじめに
JavaScriptベースのフルスタックフレームワークであるMeteorを使ったアプリケーションの保守開発をしています。
仕事の都合上、Meteorでいい感じにサーバーサイドコードのデバッグがしたくて調べていたのですが、Meteorの日本語資料が少ない&Meteor 1.6以降で仕様が違う&Meteor 1.6以降は日本語じゃなくても資料が少ないため結構苦戦したので、備忘録として残しておきます。
Meteorのデバッグ方法
Meteorのサーバーサイドデバッグ機能は、内部的にはNode.jsのデバッグ用APIを起動して利用しており、その仕様も__基本的には__同じです。
よって、Meteor v1.6以降ではプロセスの起動時に--inspect
あるいは--inspect-brk
を付ける方法が主流だと思います。
注意するべき点として、Node.jsのデバッグ用APIはV8より前ではDebugger API(node debug)、V8以降ではInspector API(node inspect)と異なることが挙げられます。
内部的にNode.jsを動かしているMeteorでも当然この影響を受けており、V1.6以降以前とそれ以降ではコマンドが異なります。
むかし(例)
meteor debug
いま(例)
meteor run --inspect
既にmeteor debug
コマンドは非推奨となっているため、よほどの事情( バージョンが足りないとか )がない限りはinspectコマンドを使ってデバッグを行うべきです。
v1.6以降のMeteorのサーバーサイドデバッグですが、Meteor公式ドキュメントや、Node.jsの公式ドキュメント,あるいはNode.jsのサーバーサイドでバッグの記事なども参考にすると良いと思います。 日本語の参考資料は多分ありません。
公式ドキュメントを見てみると、meteorの新しいデバッグコマンドは基本的にはNodeと同じ仕様のようですが、以下の2点で異なるようです。
- フラグの影響範囲がビルドプロセスそのものではなく、ビルドプロセスによって生成されるサーバープロセスに影響する。
- --inspect-brkフラグを使用すると、サーバーコードが読み込まれて実行が開始される前にサーバープロセスが一旦止まり、開発者がいい感じにブレークポイントを指定できる。
v1.6以降のMeteorのデバッガに接続するデバッグクライアントとしては、Chrome DevToolsか、VSCodeやWebStormなどのエディタ・IDEのいずれかが適切だと思います。
個人的にChrome DevToolsを使ってクライアントサイドコードのデバッグと同じようにデバッグができるのが結構好きなので、この記事ではChrome DevToolsでのデバッグ方法を記述していきます。(WebStormやVSCについては元気があったら追記したり別の記事を書いたりします。)
ちなみに、CLIでデバッグすることも可能なのですが、GUIでデバッグできるのにわざわざCUIでデバッグする理由が__なんかかっこいいから__以外に思い当たらないので、ここでは取り扱いません。でもなんかかっこいいですよね。
Chrome DevToolsでデバッグしてみる
ではやってみましょう。
まず、デバッグするMeteorプロジェクトを作りましょう。公式のチュートリアルをなんとなくやってみるとなんとなくできるかと思います。
完成したら、ターミナルを開いて該当のディレクトリに移動しましょう。
cd /simple-Todos(例)
移動したら、inspectフラグをつけてmeteorアプリを起動します。
ここでは、いい感じにGUIでブレークポイントを設定したいので、inspect-brk
フラグを使用します。
meteor run --inspect-brk
すると、何やらうにょうにょ動き始めた後、こんな感じになるかと思います。
[[[[[ ~/simple-todos ]]]]]
=> Started proxy.
=> Started MongoDB.
W20191219-01:13:49.236(9)? (STDERR) Debugger listening on ws://127.0.0.1:9229/3044cde4-e74e-469a-9081-49af1033a4e3
W20191219-01:13:49.294(9)? (STDERR) For help see https://nodejs.org/en/docs/inspector
この表示を見ると、meteorのデバッグ機能はnodeのAPIを内部的に使っていることがよく分かりますね。
では、次にクライアントデバッガをアタッチしましょう。
お手持ちのGoogle Chromeを開き、chrome://inspect
と入力してみましょう。
こんな感じのやつが出てくるかと思います。
画面上に光り輝いている(?)、inspect
を押すとデバッガにアタッチされ、ターミナルにDebugger attached.
といういかにもアタッチされたっぽい文言が出現し、クライアントデバッガも現れます。
--inspect-brkフラグをつけてmeteorアプリケーションを起動すると、debug.jsで一旦止まってくれます。コメントに書いてあるように、ここで好きなようにブレークポイントを設定できるので便利です。
ここでは、一旦TODOを新しく作成する部分にブレークポイントを設定してみます。
確認したい箇所にブレークポイントを設定したら、一時停止しているプロセスを再開させましょう。デバッガの右上にある|▶ボタンを押すと、プロセスが再開されます。
すると、ターミナルに以下のようなものが表示されます。
=> Started your app.
=> App running at: http://localhost:3000/
おとなしくlocalhost:3000にアクセスしてみましょう。するとこんな感じの画面が表示されます。
TODOリストに何もないのもアレなので、何かTODOを書いてみましょう。
ちょうど直属の先輩も欲しがっていましたし、__イカ__を買ってみることにします。
これを送信してみると、デバッガが出現します。
先程TODOの新規作成メソッドにブレークポイントをおいたためです。
右側に変数の値などが出ているかと思います。
確認が終わったら|▶を押して次のブレークポイントまで飛んだり、その近くのボタンを押してステップインしたりステップアウトしたりステップオーバーしたりしましょう。いい感じにデバッグができるはずです。
以上が今回の内容です。
2019年はMeteorが買収されたり色々ありました。これまでMeteor JSはAppolo GraphQLへのリソース集中のため3年間 Ben Newman氏1人で開発をしている状況でしたが、買収後は大幅に開発者が増えているようなのでMeteorユーザーが2021年には3億人になっているかもしれないと密かに思っています。
みなさんMeteorをやりましょう。
おわり
補足:いろいろな事情があってできない人に向けた代替手段
世界はとても広いため、上記のデバッグ手順が使えないケースというのが往々にしてあります。( バージョンが足りないとか )
というか私が仕事で関わっているプロジェクトがもろにそのケースなんですが、そういった場合にサーバー側のコードを確認したいんじゃ!という気持ちになってしまった人に向けていくつか方法を記載しておきます。
1. console.logで頑張って出す
一番単純ですが、これが使えないという状況は殆どないでしょう。(機能しないという状況は多い気がしますが)
まあでも、もっとイケてる感じでやりたいですよね。デバッグコードとか消し忘れちゃうし。
2. Meteor shellを使う
Meteor 1.0.2で実装された機能で、各種関数を実行したり、他所のAPIを叩いてみたりできる対話型実行環境です。
使い方も簡単で、起動しているMeteorプロジェクトのディレクトリ内で以下のコマンドを実行するだけです。
meteor shell
成功すると以下のような画面が現れます
Welcome to the server-side interactive shell!
Tab completion is enabled for global variables.
Type .reload to restart the server and the shell.
Type .exit to disconnect from the server and leave the shell.
Type .help for additional help.
作ったメソッドのテストやAPI呼び出しくらいならこれで十分だと言えなくもないですが、meteor shell単体では、特定のユーザーをシミュレートする(特定のユーザーとしてログインしていることにする)ことができません。(デバッグコードとしてthis.setUserId(ほにゃほにゃ)
を埋め込むなどをすれば可能ですが、手間が(1)とあまり変わりません)
Meteorは割とStatefulなフレームワークなので、メソッド呼び出し時に引数としてuserIdを渡すことよりもサーバーサイドコードの先頭でMeteor.userId()
を使って認可をすることが多く、そういったケースにおいてmeteor shellは無力な(あるいは非常に面倒くさい)場合が多いと感じています。
3.meteor debug を使う
上で「非推奨だからあんまりやるな」と書いておいてアレですが、v1.5以前だとconsole.logを出す以外の方法である程度実用に耐えるレベルのサーバーサイドデバッグをするにはこれを使うしかないと思います。
ただ、この場合chromeのDevToolsを使いたいときはnode-inspectorが必要だと思われます。
また、私が試した限りは先のmeteor v1.6以降のサーバーサイドデバッグと比べて著しくパフォーマンスが低下するように感じています。(公式でも同じような言及があります)
私が普段仕事で関わっているプロジェクトで試した際は1時間以上CPU使用率が100%を超えており、実用に耐えないと判断した経緯があります。が、やりようはあるんじゃないかという気はしています。