豆腐とコンソメ

豆腐とコンソメ

ラズパイ工作ともろもろのプログラム勉強記録

Node.jsを使って、簡単なWebアプリケーションをつくる(1)

日記

職業欄に「無職」と書くのはなかなか精神的にくるものがある。

Node.jsとは?

サーバ側で使用できるjavascriptというぐらいの認識しかありません。
今回使用する目的としては、「Socket.IO」を使ってみたかった、というそれだけの理由になります。

今回作成するもの

定番のチャットアプリを作成してみたいと思います。

f:id:konoemario:20170704220013j:plain:w500

参考させていただいた(むしろそのまま)は以下の通りです。 参考記事のほうが圧倒的にわかりやすく、正確です。なのでこの記事は自分の作業メモみたいな立ち位置になりますので、間違い等ご容赦ください。また、ご指摘いただければ幸いです。

Node.jsのスクリプトの基本を覚えよう(1/5):ビギナーのための Node.jsプログラミング入門

初心者向けNode.js基礎講座 | Udemy

Crear una aplicación web de Chat con NodeJS y SocketIO | Udemy

流れとしましては、

  1. Node.jsでWebサーバーを立てて、リクエスト/レスポンス処理をやってみる
  2. DjangoでいうURLディスパッチャみたいなものを用意して、リクエストに応じてレスポンスをかえてみる
  3. Node.jsのフレームワーク、Expressを少しさわってみる
  4. Socket.IOを使ってチャットアプリケーションをつくってみる

を予定しています。

上記が完了しだい、目的であるラズパイのラジコンのコントローラーとしてSocket.IOを使ってみたいと思います。



インストー

推奨版を公式よりダウンロードしてきます。
Node.js

使用したバージョン

masao-3:DesignPattern konoe_mario$ node -v
v6.11.0


プロジェクトの作成

直近でPythonのWebフレームワークであるDjangoもそうでしたが、Node.jsでもプロジェクトというアプリケーションを管理する考え方があるみたいです。

インストールが終わったら、ターミナルで以下のコマンドを打ちます。
ここでは、任意のディレクトリ「SampleProject」を作成して、そのディレクトリに移動して実行しています。

プロジェクトの作成

masao-3:SampleProject konoe_mario$ npm init

「npm init」を入力すると、プロジェクトの初期設定を行う質問がいろいろとでてきます。
ここでは、プロジェクトの名前である「name」と、Webアプリケーションのエントリーポイントになる、「main」の設定だけ、ちゃんと行い、後は適当にしちゃいました。

プロジェクトの設定

name: (SampleProject) nodeapp
version: (1.0.0) 
description: practice
entry point: (index.js) server.js
test command: 
git repository: 
keywords: 
author: tohu
license: (ISC) 
About to write to /Users/konoe_mario/WebstormProjects/SampleProject/package.json:

{
  "name": "nodeapp",
  "version": "1.0.0",
  "description": "practice",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "tohu",
  "license": "ISC"
}


Is this ok? (yes) 

ちなみに「npm」とはNode.jsのパッケージマネジャーで、後ほどNode.jsの外部モジュールをインストールするときに使ったりします。

プロジェクトが作成し終わると、以下のように「package.json」のみが作成された状態になるかと思います。
package.jsonにはjson形式でさきほどターミナルから入力した内容が設定されています。

masao-3:SampleProject konoe_mario$ tree
.
└── package.json


server.jsの作成

まず、プロジェクトの設定で入力した、エントリーポイントとなる「server.js」を新規で作成します。
内容は以下の通りです。

server.js

var http = require("http");

var server = http.createServer();


server.on("request",function(req, res){
   console.log("リクエストがあったよ");
});

//受け付けるポート番号
server.listen(6677);

流れとしては、

  1. http.createServerでWebサーバオブジェクトを作成します。
  2. server.onでWebサーバーオブジェクトのイベントが発生した場合の処理を書きます。
    ここでは、クライアントからリクエスト処理はあった場合に、コンソールにメッセージを表示しているだけです。

  3. 最後に、待ち受けるポート番号を記載しています。

書き方によっては、以下のようにすることもできるみたいです。

var server = http.createServer(function (req,res) {
    console.log("リクエストがあったよ");
}).listen(6677);

これは、createServerメソッドの第一引数に書かれた関数はrequestイベントに登録されるというNode.jsの仕様ということと、.listenはjavascript(jQurery?)のメソッドチェーンという言語仕様の話になります。

server.jsを作成したら、ターミナルで、以下コマンドを叩きます。

masao-3:SampleProject2 konoe_mario$ node server.js 

その状態で、ブラウザから「http://localhost:6677」にアクセスしてみます。

ブラウザ側には何も変化は起きないと思いますが、ターミナル上には、console.logで指定した文字列が出力されるかと思います。

masao-3:SampleProject2 konoe_mario$ node server.js 
リクエストがあったよ


レスポンスを返す

さきほど、「http://localhost:6677」にアクセスしてもブラウザには何も変化がありませんでした。 これは、ブラウザからWebサーバーにリクエスト処理は行っているのですが、レスポンスがないため、ブラウザが待っているよう状態になります。

なので、次にWebサーバーからレスポンスを返すようにします。

server.js

var http = require("http");

var server = http.createServer();

server.on("request",function(req, res){
   console.log("リクエストがあったよ");
   //サーバーにレスポンスを返す。
   res.end("<h1>おはんきー!</h1>");
});

//受け付けるポート番号
server.listen(6677);

一行、「res.end()」を追加しています。
これを行うことで、サーバ側の処理はもう終わったよ!といってクライアントにメッセージを送信します。
このタイミングでコネクションが切れるのかな、とかそういった事に関しては自分自身まったくわかってないです。

この状態で、ブラウザから「http://localhost:6677」にアクセスします。

すると、以下のように文字化けした状態で表示されるかと思います。

f:id:konoemario:20170704220106p:plain:w500

ブラウザ側に文字コードを教えてあげる必要があります。 なので、htmlファイルのheadタグにcharsetの指定を追加します。

server.js

var http = require("http");

var server = http.createServer();

server.on("request",function(req, res){
   console.log("リクエストがあったよ");
   
   res.write('<head><meta charset="UTF-8"></head>');
   //サーバーにレスポンスを返す。
   res.end("<h1>おはんきー!</h1>");
});
<br/>

//受け付けるポート番号
server.listen(6677);

追加した「res.write()」ですが、前述の「res.end()」とは異なり、送信するデータあれば何回でも追記できるみたいです。
こうすることで、無事、表示されたかと思います。

f:id:konoemario:20170704220218p:plain:w500

ちなみに、最初はHTTPヘッダの文字コードutf-8にしなきゃいけないんだ!と思い、以下のようにヘッダファイルを編集する「writeHead()」でcharsetの設定を行っていたのですが、まったく変わらずに時間をとっちゃいました。

server.js

var http = require("http");

var server = http.createServer();

server.on("request",function(req, res){
   console.log("リクエストがあったよ");
   
   //HTTPヘッダを編集する。
   res.writeHead(200,{'Content-Type':'text/html','charset':'UTF-8'});
   //サーバーにレスポンスを返す。
   res.end("<h1>おはんきー!</h1>");
});

ちなみに、ブラウザはChromeを使っているのですが、ツールバーの表示->開発/管理->デベロッパーツールより、HTTPレスポンスヘッダの内容やリクエストヘッダの内容を確認することができます。

f:id:konoemario:20170704220800p:plain:w500

また、いまさらですが、Webサーバーオブジェクトのメソッドとか、イベントは素敵な公式?ドキュメントがあるのでこちらを参照しています。

HTTP Node.js v0.11.11 Manual & Documentation

こんなペースで大丈夫か、と不安になるのですが今日はここまでにしたいと思います。

次回

tohutokonsome.hatenablog.com