この記事について
この記事ではNode.jsを使ったサーバサイドプログラミングの入門解説を行っています。この記事を通じてWebページの仕組みをしることができます。ターゲットはほかの記事と同様、エンジニアではない方で教養として覚えたいというものですので、ちょっとでも興味がある方は実際に読んでいただけますと幸いです。
前提知識
大変申し訳ないことですが、最低限HTML,コマンドライン,JavaScriptの3つの知識は前提として書いています。
とはいえ、最低限の知識だけで済むようにしています。必要な知識は以下の記事にまとめておりますので不安な方は先にこの3つを確認しつつ読んでください。
Node.jsのセットアップ
今回はNode.jsというミドルウェアを利用します。Node.jsはWEBページ以外のアプリケーション開発でJavaScriptを利用するためのミドルウェアです。公式サイトからインストーラーをダウンロードしてインストールしましょう。トップページにダウンロードリンクがあります。2つありますが、どちらでも問題ありませんが、迷ったらLTSと書かれている方を選びましょう。インストール中に設定がいくつかきかれますが基本はデフォルトのままで問題ありません。
インストール完了したらコマンドラインでnode --versionと打ってみましょう。バージョンがでればインストール成功です。
% node --version
v12.18.3
Node.jsの使い方
まず、Node.jsでのJavaScriptの使い方を解説します。早速index.jsというファイル名で以下のコードを書いてみましょう。
console.log("hello node.js");
書き終わったら、index.jsが置いてあるディレクトリにコマンドラインで移動して以下のコマンドを打ってみましょう。[node ファイル名]でアプリケーションの実行ができます。
% node index.js
hello node.js
console.logという命令で、コマンドライン上に値を出力することができます。Node.jsにおいて、ログ出力などでよく使うので覚えておくと良いでしょう。
サーバアプリケーションを作成する
それではNode.jsをつかってサーバアプリケーションを作ってみましょう。
ライブラリをインストールする
そのままNode.jsの状態でWebアプリケーションをつくることもできますが、ちょっと大変です。しかしながらNode.jsではすでに開発が便利なJavaScriptのライブラリが存在します。今回はそれらを使って開発しますので各種ライブラリをインストールしましょう。
index.jsのフォルダ上で以下のコマンドを打ってみましょう。npmというコマンドは、Node.jsのライブラリを管理するコマンドです。今回はexpress,axio,ejs,body-parserの4つのライブラリをインストールします。※それぞれの使い方は後ほど解説します。
% npm install express axios ejs body-parser
・・・中略・・・
# node_modulesというフォルダができればインストール成功です。
% ls
index.js node_modules package-lock.json
今回はこの4つの紹介に留めますが、Node.jsではすでに様々な便利なライブラリが作られています。様々な方が使い方の記事を日本語でだしていますので、もしも興味がありましたら調べてみてください。
Hello World
それでは実際に開発してみましょう。
まず、index.jsのフォルダにviewsというフォルダを作って、index.ejsというファイルを作成しましょう。
# フォルダ構成
- node_modules
- views
- index.ejs
index.js
index.ejsの中身は以下の内容を記載します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>はじめてのサーバーアプリ</title>
</head>
<body>
<h1>はじめてのサーバーアプリ</h1>
<!-- <%= %> で変数の中身を出力できます。 -->
<p><%= message %></p>
</body>
</html>
index.ejsのファイルの中身はHTMLです。テンプレートエンジンというもので、ウェブサイト上に出力するHTMLのテンプレートを作成しています。<p><%= message %></p>という点がポイントでJavaScriptの本体プログラミング上で定義するmessageという変数を出力します。先ほどインストールしたejsというライブラリは、このテンプレートエンジンを使うためのライブラリです。
続いて、index.jsを以下のように書き換えましょう。書き方のポイントは後述しますが、先ほどインストールしたexpressというライブラリを使ってサーバアプリケーションを開発します。requireという命令がそのライブラリを呼び出す記載です。
var express = require("express");
var app = express();
//viewエンジンをejsであることを設定
app.set("view engine", "ejs");
//アクセスを受け取るURLのパスを指定します。
app.get('/', function(req, res){
var message = "Hello World!";
//Webには出力されず、ログとしてコンソールに出力されます。
console.log("アクセスがありました。");
//出力するテンプレート、テンプレート上の変数にいれる値を設定します。
res.render("index", {message: message});
});
app.listen(80, function() {
console.log("サーバー起動中");
});
記載できたらさっそくアプリケーションを実行しましょう。サーバー起動中と出た後、ブラウザでhttp://127.0.0.1/というURLにアクセスしてみましょう。以下のような画面がでたら成功です。
なお、ブラウザアクセスするたびにコマンドライン上ではアクセスがありましたというログが出されていると思います。このようにしてログ確認もできるようになります。確認ができたらコマンドラインで「Ctrl + C」を押してください。これでアプリケーションを終了できます。
% node index.js
サーバー起動中
アクセスがありました。
アクセスがありました。
index.jsに様々なコードを書きましたが、ポイントはapp.get()の部分です。ここに、具体的にアクセスするURLのパスを指定して、実行する処理を定義します。最後にres.render()で、index.ejsのテンプレート名(.ejsは省略します。)とテンプレート上で出力する変数の値を定義して出力します。
書き方に慣れるためにもうひとつアクセスポイントを定義してみましょう。second.ejsというファイルを作成し、index.jsも修正しましょう。
second.ejsは以下のように記載します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>はじめてのサーバーアプリ</title>
</head>
<body>
<h1>2ページ目</h1>
<!-- <%= %> で変数の中身を出力できます。 -->
<p><%= comment %></p>
</body>
</html>
index.jsは以下のように修正します。
var express = require("express");
var app = express();
//viewエンジンをejsであることを設定
app.set("view engine", "ejs");
//アクセスを受け取るURLのパスを指定します。
app.get('/', function(req, res){
var message = "Hello World!";
//Webには出力されず、ログとしてコンソールに出力されます。
console.log("アクセスがありました。");
res.render("index", {message: message});
});
//アクセスを受け取るURLのパスを指定します。
app.get('/second', function(req, res){
var message = "2ページ目";
res.render("second", {comment: message});
});
app.listen(80, function() {
console.log("サーバー起動中");
});
作成したらアプリケーションを実行してhttp://127.0.0.1/secondというURLにアクセスしてみましょう。以下のような画面がでれば成功です。
このように、app.get()を使ってパスを指定して表示するページの処理をするのがExpressの基本的な使い方になります。
静的ファイルを配信する
Expressはapp.get()を書いて、それぞれのパスにアクセスした時にどんな処理をして表示をするのかを定義します。しかしながら、そもそも動的にejsのテンプレートで出力を変えたりすることのないHTMLファイルや、画像ファイルといった静的なファイルを毎回この形で定義するのは非常に面倒です。そのため静的なファイルを配信できるように設定してみましょう。
まず、index.jsのフォルダに新たにstaticというフォルダを作ってみましょう。staticのフォルダを作成したら、そこに画像はHTML、テキストファイルなど任意のファイルを置いてみましょう。
# フォルダ構成
- node_modules
- views
- index.ejs
- static
- icon.png
- ※その他任意のファイルを置いてみてください。
index.js
staticフォルダを作ったらindex.jsを以下のように修正してみましょう。
var express = require("express");
var app = express();
//viewエンジンをejsであることを設定
app.set("view engine", "ejs");
//静的ファイル配信の設定
app.use('/static', express.static('static'));
//アクセスを受け取るURLのパスを指定します。
app.get('/', function(req, res){
var message = "Hello World!";
res.render("index", {message: message});
});
app.listen(80, function() {
console.log("サーバー起動中");
});
修正は一行だけ、app.use('/static', express.static('static'));という記載です。staticフォルダ以下のファイルを、staticというパスで配信するという設定になります。
設定ができたら、アプリケーションを実行してhttp://127.0.0.1/static/{任意のファイル名}にアクセスしてみましょう。app.get()を定義していなくても確かにブラウザ上からWebページを表示することができるようになります。
システム連携をしてみる
続いてシステム連携をしてみましょう。サーバサイドにおいて、全ての処理を1つのサーバアプリケーションで処理することは稀です。以下の図のようにブラウザ上の表示処理を専門とするフロントエンドサーバ(FE)がバックエンドサーバ(BE)にアクセスして、ユーザーから渡された値をBEに渡したり、逆にBEが配信するデータを取得してFEサーバ内で表示加工して出力したりします。
FEがBEと通信する手段は様々ありますが、代表的なものとして、ブラウザでもアクセスできるURLでWeb通信という形でやりとりする手法があります。この手法をWebAPIといいます。今回は私がこのブログを運営しているサーバ上に、https://miyau5555.info/static/app/server-side-programing-for-non-engineer/apiというWebAPIをつくりました。こちらを使って私のサーバと連携させてみましょう。こちらのURLをブラウザでアクセスするとわかりますが、中身は以下のCSVファイルを出力するだけのWebAPIです。
名前,年齢
山田太郎,21
佐藤拓也,35
田中花子,22
加藤花,19
それではWebAPIにアクセスしてデータを取得し、取得した値を加工して表示させるアプリケーションを作ってみましょう。index.jsとindex.ejsを以下のように書き換えてみましょう。
まず、index.jsです。
var express = require("express");
var app = express();
var axios = require("axios");
var url = "https://miyau5555.info/static/app/server-side-programing-for-non-engineer/api";
app.set("view engine", "ejs");
//アクセスを受け取るURLを指定します。
app.get('/', function(req, res){
axios
.get(url)
.then(function(response) {
// 一行ごとに分解して配列化します。 \n は改行コードを示しています。
var list = response.data.split("\n");
var employeeList = [];
for(var i = 0; i < list.length; i = i + 1) {
// , でさらに分解して配列化します。
item = list[i].split(",");
// オブジェクトとした上で配列に加えます。
employeeList.push({
name: item[0],
age: item[1]
})
}
res.render("index", {employeeList: employeeList});
});
});
app.listen(80, function() {
console.log("サーバー起動中");
});
BEサーバにアクセスするために、axiosというライブラリを使います。このライブラリはJavaScriptのコード上でURLのWebAPIにアクセスして値を取得します。
データ取得後splitというものをつかって分解して配列化し、テンプレートに渡します。
続いて、index.ejsは以下のように修正します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>はじめてのサーバーアプリ</title>
</head>
<body>
<h1>はじめてのサーバーアプリ</h1>
<table>
<!-- <% %> でJavaScriptのコードをそのまま書くことができます。 -->
<%
for(var i = 0; i < employeeList.length; i = i + 1) {
%>
<tr><td><%= employeeList[i].name %></td><td><%= employeeList[i].age %></td></tr>
<%
}
%>
</table>
</body>
</html>
<% %>が新しくでる構文ですが、タグの間でJavaScriptのコードを書くことができます。ここではemployeeListの数分繰り返し処理を行い、employeeListのnameとageを出力していきます。
書き終えたら実行してみましょう。以下のように出力されれば成功です。
フォームからデータを取得する
最後にフォームを使ってユーザーから値を受け取って出力してみましょう。ここでは、ここまでの総集編として、簡単なチャットアプリを作ってみましょう。
まず、index.ejsを以下のように書き換えてみましょう。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>はじめてのサーバーアプリ</title>
</head>
<body>
<h1>はじめてのサーバーアプリ</h1>
<form action="/" method="post">
<input type="text" name="comment">
<input type="submit" value="送信">
</form>
<ul>
<% for(var i = 0; i < list.length; i = i + 1) { %>
<li><%= list[i].comment %><br /><%= list[i].date %></li>
<% } %>
</ul>
</body>
</html>
HTMLのポイントはフォームというタグです。フォームというタグを使って、inputタグのcommentというところに入力された値をサーバに送っています。
続いてindex.jsは以下のように書き換えます。
var express = require("express");
var app = express();
//フォームによるPost送信のデータを受け取る設定
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({
extended: true
}));
var list = [];
//viewエンジンをejsであることを設定
app.set("view engine", "ejs");
//アクセスを受け取るURLを指定します。
app.get('/', function(req, res){
res.render("index", {list: list})
});
//
app.post('/', function(req, res){
//日付を表示するため日付オブジェクトを作成します。
var date = new Date();
//受け取った値を追加
list.push({
date: date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate() + " " + date.getHours() + "時" + date.getMinutes() + "分",
comment : req.body.comment
});
res.render("index", {list: list})
});
app.listen(80, function() {
console.log("サーバー起動中");
});
ポイントはbody-parserという部分とapp.post()です。body-parserとは、ユーザーから受け取った値を簡単に処理することができるライブラリです。様々な使い方ができますが、一旦は今回のような書き方を覚えていただくだけで問題ありません。
app.post()はフォームタグを使ってサーバアクセスした時の処理を定義するものです。フォームを使って取得したcommentの値を、listに格納します。格納後、index.ejsのテンプレートをサイド出力するようにしています。
※厳密にはformタグのactionの属性をgetに変えることでapp.get()で値を受け取ることもできます。ただし、このやり方を解説すると複雑になるため、今回は省略します。興味ある方は調べてみてください。
コードを書き換えたら実行してみましょう。簡単ですが、以下のようにチャットアプリケーションが動けば成功です。
ちなみにlistという変数をデータベースの代わりに使っているため、[Ctrl + C]でアプリケーションを終了してしまうと、サーバ上で保存していた値が消えてしまいます。もしも、永久保存したい場合は前述のシステム連携の手法をつかってバックエンドのデータベースサーバにアクセスして保存したり、今回は解説しませんが、定期的にファイルとして出力保存することで永続化は可能です。
データベースを利用するとなると、SQLを書く必要が出てきます。もしも興味がありましたら下記ページを読んでみてください。
データベースを利用する場合、ライブラリによって使い方が変わりますが、以下のようなSQLをJavaScriptプログラムコードで書いて保存・データ取得をします。データベースを立ち上げる準備が必要なため、詳細は割愛しますが実装イメージをつけていただければと思います。
#mysqlライブラリを使ってmysqlに接続する例です。
#DB接続
var mysql = require('mysql');
var connection = mysql.createConnection({
host : '127.0.0.1', //接続するDBサーバのIPアドレス
user : 'user', //接続するアカウント
password : 'password' //接続するアカウントのパスワード
});
#データ取得
connection.query("SELECT * FROM comment", function (error, results, fields) {
var list = [];
for (var i; i < fields.length; i = i + 1) {
list.push(fields[i].comment)
}
});
#データ保存
connection.query("INSERT INTO comment(comment) VALUES(" + comment + ")", function (error, results, fields) {});
終わりに
今回も駆け足でしたが、JavaScriptによるサーバサイドアプリケーションの最低限の解説でした。アプリケーションには大きく2種類に分けられます。1つはPC内にアプリケーションをインストールして利用するるクライアントアプリケーション。もう一つはサーバとして、外に対してデータ配信や、データ登録を受け付けるサーバアプリケーションがあります。特にWebという観点ではこのサーバアプリケーションを操ることは重要な要素になります。
この記事を通じて少しでもサーバアプリケーションやWEBの仕組みについて理解が深まっていただけたり、興味を持っていただける方がいれば幸いです。最後まで読んでいただきありがとうございました。
Photo by: Matthew Henry