Node.js Visual StudioでNode.jsの開発 入門・初歩
概要
Node.jsをVisual Studioで扱うことができます。
前提
- Visual Studioをインストール済。
- Node.js Windowsをインストール済。
Node.jsのインストール途中で必要なものを自動インストールするかという選択肢が表示されるので一緒にインストールします。Chocolateyもインストールされますと表示されますが、インストールしましょう。ChocolateyはNuGetというパッケージ管理をWindowsでも使うためのもので、NuGetはヌガーという風にも読めそうなところからChocolateyという名前が使われています。ちょっと容量が大きくなりますが、頑張って勉強するなら入れておいたほうが楽でしょう。
Visual StudioでJavascriptのデバッグをするときはNode.jsのWebサーバ機能を使いますので、Node.jsの勉強をしたいわけではないときも、インストールすることになるでしょう。以下のような手順になります。
- [ツール]-[ツールと機能を取得]
- 表示されたウィンドウで、[ワークロード]-[Web&クラウド]からNode.js開発のチェックボックスをマークします。
- バックグラウンドで起動しているVisual Studio本体側を閉じます。もともとのウィンドウに戻って、右下のボタンからインストールを開始します。
Hello World!
まずは、新しい言語を覚える時の最初の一歩。Hello World!と表示される処理をやってみましょう。
Node.jsのソリューションを新規作成します。HelloWorld_Stepという名前のソリューションを作ります。Server.jsのソースエディタで以下のように入力します。
'use strict';
var http = require('http');
var url = require('url');
var port = process.env.PORT || 1337;
var server = http.createServer(function (req, res) {
res.write("Hello world!\n");
res.end();
}).listen(port);
入力したら、ツールバーの[▶ウェブサーバ(Microsoft Edge)]をクリックします。わりかし時間がかかりますが、ブラウザが起動あるいは新しいページを開いて、http://localhost:1337というURIアドレスでHelloWorldが開いたと思います。
これでHelloWorldは完成です。
Hello World! その2
Hello Worldを違う場所に表示させます。ふたつ目は、ウェブサーバのコンソール画面に出力する方法です。res.writeの前後に以下の命令を追加します。res…の前後といいましたが、命令の記述順序はどっちでもいいという意味です。
Console.log("Hello world!\n");
res.write("Hello world!\n");
res.end();
Console.logでWebページへではなく、コンソールに表示できます。
Hello World! その3
Hello Worldを違う方法で表示させます。Node.jsコンソール画面に出力する方法です。res.writeの前後に以下の命令を追加します。
process.stdout.write("Hello world!\n");
Console.log("Hello world!\n");
res.write("Hello world!\n");
res.end();
標準出力というものです。コンソールに出力されます。
Hello World! その4
Hello Worldを更に違う方法で表示させます。
process.stdout.write("Hello world!\n");
Console.log("Hello world!\n");
res.write("Hello world!\n");
res.send("Hello world!\n");
res.end();
res.sendでも出力できます。writeはWebページのContent部品として書き出しますが、sendは、特にどこへ記述するか意識しないので、Header部分にもContent部分にもなりえます。
GET POST
httpプロトコルではGETメッセージという方式とPOSTメッセージという方式の2大メッセージがあります。GETメッセージではすべてアドレスに書かれた情報をもとにWEBServerが応答します。例えば以下のようなURLです
GET
http://localhost:1337/TEST?Key=Value&Key2=Value2
と上記のようなものがGETメッセージを処理するアドレスの例です。QueryStringと呼ばれるページに対するデータがアドレスに付け足されて表示される仕組みです。以下のように解釈されます。
Path : /TEST QueryString : Key=Value&Key2=Value2 名前1 : Key 値1 : Value 名前2 : Key2 値2 : Value2
POSTメッセージは、アドレスには表示されないQueryStringです。通常はhtmlのformタグのMethodの値にPOSTが指定されてformActionが実行されたときにQueryStringが発行されます。開発段階においては、formを使わずにPOSTメッセージを発行する方法が用意されています。ひとつの方法はCommandPromptでメッセージを送る方法です。
以下のようなコマンドになります。Windows PowerShellでは異なる動作なので、CommandPromptをつかって下さい。
curl -X "POST" -d Key1=Value -d Key1=Value2 -d Key2=Value3 http://localhost:1337/TEST
以下のように解釈されます。
Path : /TEST QueryString : Key1=Value1&Key1=Value2&Key2=Value3 名前1 : Key1 値1 : { Value1, Value2 } 名前2 : Key2 値2 : Value3
このような値を処理するには、
var querystring = require('querystring');
http.createServer(function(req, res) {
if(req.method === 'GET') {
res.writeHead(200, {'Content-Type' : 'text/html'});
res.write("Get Hello World!");
res.end();
}
if(req.method === 'POST') {
res.writeHead(200, {'Content-Type' : 'text/html'});
res.write("POST Hello World!");
req.on('readable', function(chunk) {
data += req.read();
});
//全て読み込んだらendイベントが発生。
req.on('end', function() {
//パースする
querystring.parse(data);
res.write(data);
});
res.end();
}
}).listen(port);
上記のようにreq.methodの値を判断するとそれぞれのメッセージ毎に異なる動作をするServerについて記述ができます。ここではJavaScriptの基本については理解しているものとして、記述しています。JavaScript 制御構造のような記事で学習して下さい。
ここであたらしくres.writeHeadというメソッドを使っています。引数にはステータス番号とメタタグのキーワードと値を記述できます。
メッセージ番号 200 メタタグ キーワード : Content-Type 値 : text-html
と上記のように設定しています。
そしてreq.onというメソッドでは、呼び出されたときのデータを読み込むreadable状態が発生して、定義した関数function(chunk)が実行されます。このようにメソッドが(状態,実行する関数);のような引数をとるものは多くあります。そして、関数の実行が終わったらまたイベントが発生して、(状態2,実行する関数2);のように関数の呼び出しが連鎖します。処理自体は可能な限り次へと次へと進みます。このような仕組みをノンブロッキングと呼んでいます。Node.jsの特徴の一つです。2番目のreq.on('end', …);が発生してデータをparse解析して出力しますが、貧弱なParse処理です。この方法だとデータの読み取りが面倒なのでExpressというパッケージが配布されていて、より強力にParseできるため、Expressを導入するのが一般的です。
ノンブロッキングとExpressについて紹介していきます。
Expressモジュールの導入
Node.jsでは後から便利なモジュールを追加して構築していくことができます。ExpressはGETメッセージとPOSTメッセージを的確に解析して、QueryStringを使いやすい状態にしてくれます。
VisualStudioでもモジュールの導入ができます。npm(Node Package Manager)というパッケージ管理全体のメカニズムに名称がついています。npmから導入しましょうといった具合に使われます。npmに各種の便利なモジュールパッケージが配置されていて、使いたい人はnpmから入手して使いましょうという形式になっています。最近はこういった具合に他のプログラム言語でもモジュール管理システムに有用なモジュールは配置して、使いたい人はそのシステムをつかって導入するということが流行っています。
VisualStudioの場合はソリューションエクスプローラのViewでソリューション名の下にnpmというのがあります。これを右クリックして表示されるメニューの[新しいnpmパッケージマネージャーをインストールする]から導入できます。検索ウィンドウでExpressのようにパッケージ名を入力すると存在するパッケージへの情報が表示され、右下のパッケージのインストールから処理が開始できます。Expressを導入してみましょう。すると同時に必要な他のモジュールもインストールされます。
さっそく、使うためのコードを記述します。
'use strict';
var http = require('http');
var url = require('url');
var port = process.env.PORT || 1337;
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));
app.post('/', function (req, res) {
for (var key in req.body) {
console.log(key, '=', req.body[key]);
}
res.end();
});
app.post('/test1', function (req, res) {
res.send('TEST1\n')
});
- var express = require('express');
- 上記の行で、さっそく、expressモジュールを取り込んでいます。こうして宣言したオブジェクト変数expressを
- var app = express();
- で、expressのコンストラクタ関数を動かした結果をappに設定します。
このような操作で、後でapp.postメソッドとして、2つのノンブロッキング関数を呼び出しています。
- var bodyParser = require('body-parser');
- app.useというメソッドで使うためにbody-parserというモジュールを取り込んでいます。
- app.use(bodyParser.urlencoded({extended:true}));
- そうして、useメソッドの引数にbodyParser.urlencode({extended:true})を設定してencodeを設定します。
- app.post(Path, 関数{ 関数内の命令処理 });
- 上記の形式でPath毎に関数を変えたNonBlocking処理の関数。
POSTメッセージを受け取ると、呼び出される app.post('/', function(req, res){});が定義出来て、req.body[key]=Valueの形式でクエリーの値を受け取れます。req.bodyをfor… in…構造でループさせるとすべてのキー名が得られます。
このようにexpressモジュールを使うとParse処理が楽になります。
ノンブロッキング ブロッキングの違い
ノンブロッキングの良い例は以下のようなプログラムです。簡単な例なので、上記のようなWebServerソリューションではなく、任意のディレクトリにノンブロッキングの動作確認用*.jsファイルを作ってみましょう。どこからでもNodeコマンドは使えるので任意。好きなディレクトリにTEST1NonBlocking.jsとか適当な名前で拡張子が.jsのようなファイルを作ります。
setTimeout(function(){
console.log("hello world");
}, 5000);
console.log("TEST ");
上記のようなコードを入力して、保存します。そして、保存したディレクトリのフルパスをファイルエクスプローラのアドレス部をクリックしてコピーするとかして、command promptを起動します。コマンドに cd "" と入力してダブルクォーテーションの間に矢印キーで入力カーソルを合わせて、Ctrl+Vでコピーしておいたパスを貼り付けて、Enterキーを入力するとカレントディレクトリをファイルを作成した位置に合わせることができます。
次に、
node TEST1NonBlocking.js
として実行します。すると、次の行にTESTと表示されて、しばらくするとTEST の後ろにHello worldと表示されたと思います。このように次の行にあったはずのTESTの表示処理がSetTimeOutの処理の完了をまたずに実行されました。そして、しかるべき時が来たら、先に合った行の処理が終わるという手順です。このような動作をNonBlockingと呼んでいます。ただし、このように関数の呼び出しを準備するという以外の方法ではBlocking処理が行われます。例えば、TEST1Blocking.jsとか適当な名前で拡張子が.jsのようなファイルを作ります。
var start = new Date().getTime();
while(new Date().getTime() < start + 5000);
console.log("Hello world");
というような方法で5秒後までループする処理はブロッキングが起こる処理です。先にHello worldが表示されることはありません。後に書かれた処理の実行はしっかりまたされます。