初心者向け学習方法一覧はこちら
はじめに
本記事ではNode.jsで利用できるパッケージを使ってWeb APIサーバを作成する方法を解説します。 サンプルとして、クライアントとサーバーが通信して遊べるFizzBuzzゲームを作成します。 パッケージを利用することで効率的に開発することが可能です。
Node.jsについての詳細な解説はこちらの記事
Node.jsとは?
Node.jsはサーバーサイドのJavaScriptの実行環境です。 Node.jsの登場によりWebページのブラウザ上のコンテンツだけではなく、サーバーサイドの処理もJavaScriptで記述できるようになりました。
Node.jsは大量のアクセスをリアルタイムに処理する能力が高く、Webサイトだけではなくアプリ開発にも使用されています。
また、フレームワークやライブラリを管理する仕組みも含まれていて多くのフレームワークやライブラリがNode.jsの仕組みを利用しています。
クライアント・サーバーシステムとは?
クライアント・サーバーシステムとは、データや処理結果をリクエストするクライアントとリクエストを受けて結果を返すサーバーという2つの役割に分けてシステムを構築する仕組みのことです。
Webページを閲覧するときはクライアント端末(PCやスマホ)のブラウザからURLでリクエストを送ります。 サーバーはリクエストの内容を確認してレスポンスを返します。 Webページへのリクエストを受け付けてレスポンスを返すサーバーを「Webサーバー」と言います。
Webページの閲覧以外にもクライアント・サーバーシステムで稼働しているシステムはたくさんあります。
Web APIとは?
API(Application Programming Interface)とはアプリケーションの機能を外部に連携するための仕組みのことです。 Web APIはAPIの中でもHTTP通信などのWeb技術を用いて構築された外部サービスの情報を受け取ることができるものです。
Web APIについては詳しく解説している記事がありますので、こちら もご覧ください。
FizzBuzzアプリを作ろう
FizzBuzz問題とは?
エンジニアの最初の腕試しによく使われる問題です。 数字を1から順にカウントアップしていきますが、数字が3の倍数のときは「Fizz」、5の倍数のときは「Buzz」を表示します。 そして3の倍数かつ5の倍数、つまり15の倍数の場合は「FizzBuzz」と表示します。
今回はこのFizzBuzz問題をクライアントとサーバーが通信して遊べるアプリを作成します。
まずは「FizzBuzz」というフォルダを新規作成します。 次にこれから説明する手順に従ってフォルダ内にモジュールをインストールして準備をしてから、必要なファイルを作成していきます。
最終的なフォルダとファイルの階層関係はこのようになります。
モジュールを使おう
モジュールとは?
ここでいうモジュールとはNode.jsで使用されるnode moduleのことを指します。 node moduleはnmpコマンドを使用してインストールが可能な様々な機能を提供してくれるモジュールのことです。 今回は「express」と「multer」というモジュールを使用します。
- express
expressはnode moduleの中でもよく使われているサーバー作成を支援してくれるモジュールです。 サーバに関する記述や、リクエストのやり取りに関する記述を簡潔に表すことが可能となります。 expressを活用することでNode.jsの開発効率が劇的に良くなるとも言われています。
- multer
multerはNode.jsのミドルウェアの1つで、クライアントからのデータ受け取りを支援してくれます。 サーバーにファイルをアップロードする際にも使えます。
npmでモジュールをインストールする
先ほど作成した「FizzBuzz」フォルダ内にモジュールのインストールを行います。
FizzBuzzフォルダを選択して右クリックメニューの「統合ターミナルで開く」をクリックしてターミナルを起動します。
最初にnpm管理の初期化を行います。下記のコマンドを実行します。
% npm init -y
次にexpressとmulterをインストールします。 下記のコマンドを実行します。
% npm -i express multer
引数の-iはインストールを意味します。 インストールするモジュールは一括で指定しています。文字間の半角スペースを忘れないようにしてください。
コマンドを実行するとフォルダ内にnode_modulesフォルダ、package-lock.json、package.jsonが生成されます。
test.js
// モジュール準備
const express = require("express");
const app = express();
// エンドポイント
app.get("/", function (_, res) {
res.send("Hello");
});
// サーバーを起動する
const port = 3000;
app.listen(port, function () {
console.log("Node.js Server Started http://localhost:" + port);
});
モジュールの動作を確認してみましょう。
expressを利用してWebサーバーを立てます。 test.jsという新規ファイルを作成して、下記のコードを記述しましょう。
// モジュール準備
const express = require("express");
const app = express();
// エンドポイント
app.get("/", function (_, res) {
res.send("Hello express");
});
// サーバーを起動する
const port = 3000;
app.listen(port, function () {
console.log("Node.js Server Started http://localhost:" + port);
});
エンドポイント(アクセス先)に指定している ”/” はサーバーのURLそのままという意味があります。今回は、サーバーのURLに直接アクセスしたら「Hello express」という文字列が表示されるようにエンドポイントを設定しました。
また、サーバーを起動するポート番号(アクセスする入り口)を3000番に設定しています。こうすることで『http://<サーバーのURL>:<ポート番号>/』のURLで自分の作成したWebサーバーにアクセスすることができるようになります。
ファイルを保存したらVSCodeのターミナルで実行しましょう。
% node test.js
コマンドを実行したら、Webブラウザで「http://localhost:3000/」にアクセスしてみましょう。 Hello expressが表示されます。
動作確認後はVSCodeのターミナルから起動したサーバを停止しておきましょう。 Windowsではctrl + c、MacOSではcontrol + cで停止させられます。
ここからは実際にFizzBuzzアプリを作成していきます。
まずはサーバー側の処理を作成します。
server.jsを新規作成して下記のコードを記述してください。 「// TODO」とコメントを記載している箇所は、後ほど内容を作成します。
// モジュール準備
const express = require("express");
const multer = require("multer");
const app = express();
app.use(multer().none());
// 静的コンテンツ(HTMLファイル)の返却準備
app.use(express.static("public"));
// 現在の数値を管理
let num = 0;
// ゲーム開始用エンドポイント
app.get("/api/start", function (_, res) {
// TODO
});
// ゲーム進行用エンドポイント
app.post("/api/game", function (req, res) {
// TODO
});
// サーバーを起動する
const port = 3000;
app.listen(port, function () {
console.log("Node.js Server Started: http://localhost:" + port);
});
エンドポイント(アクセス先)をゲーム開始用エンドポイント("/api/start”)とゲーム進行用エンドポイント("/api/game”)の2つを用意しています。
今回はFizzBuzzのゲーム中に、現在の数値がいくつなのかをサーバー側で管理する必要があります。そのため、数値を保存してエンドポイントで利用するための「num」という変数を定義しています。
次に、ゲーム開始用エンドポイントの処理を作成します。 最初にクライアント(画面)から「開始」のメッセージが送信された際に動作します。 「// TODO」とコメントを記載した箇所を書き換えます。
~~~ 省略 ~~~
// ゲーム開始用エンドポイント
app.get("/api/start", function (_, res) {
num = Math.floor(Math.random() * 2);
if (num === 0) {
res.send({
systemMessage: "あなたから開始です",
resMessage: "(答えてください)",
});
} else {
res.send({
systemMessage: "あなたの番です",
resMessage: "1!",
});
}
});
~~~ 省略 ~~~
『req.body.answer』でクライアント(画面)から送信された答え(answer)を受け取っています。受け取った値がFizzBuzzのルールに合致しているかを確認し、確認結果に応じた内容をクライアントに返却します。
尚、今回はコンピュータは絶対に負けないプログラムとしており、ユーザがどこまで続けられるかを競うゲームとなっています。
次にクライアント側を作成します。 publicフォルダを作成し、その中にindex.htmlを新規作成します。
最初に、HTML(内容)を作成します。 「// TODO」とコメントを記載している箇所は、後ほど内容を作成します。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>FizzBuzz</title>
<style>
// TODO
</style>
</head>
<body>
<h1>FizzBuzz</h1>
<p>現在の状況</p>
<p><span id="msg-answer">(待っています)</span></p>
<p>
<span id="msg-system">START を 押して開始してください</span>
</p>
<hr />
<p>
<input type="number" id="input-num" placeholder="数" />
<button type="button" onclick="fetchAPIWithNumber()">数で答える</button>
</p>
<p>
<button type="button" onclick="fetchAPI('Fizz')">Fizz</button>
<button type="button" onclick="fetchAPI('Buzz')">Buzz</button>
<button type="button" onclick="fetchAPI('FizzBuzz')">FizzBuzz</button>
</p>
<hr />
<button type="button" class="button-start" onclick="start()">START</button>
<script>
// TODO
</script>
</body>
</html>
FizzBuzzアプリで必要な内容は「ゲーム開始を宣言」「現在のゲーム状況を表示する」「ユーザが答えをサーバに送る」の3つです。ここでは<hr>タグで境界線を表示しながら、3つの内容を作成しました。
次に、CSS(見た目)を作成します。 「// TODO」とコメントを記載した箇所を書き換えます。
~~~ 省略 ~~~
<style>
body {
width: 60%;
margin: auto;
text-align: center;
}
input[type="number"] {
font-size: large;
width: 70px;
height: 1.9rem;
text-align: center;
}
#msg-system {
color: red;
}
#msg-answer {
display: block;
padding: 20px;
font-size: xx-large;
border: solid 1px;
}
button {
padding: 8px;
border: none;
border-radius: 5px;
cursor: pointer;
background-color: turquoise;
}
.button-start {
background-color: greenyellow;
}
</style>
~~~ 省略 ~~~
idを指定して見た目を変更する場合は先頭に「#」、classを指定して見た目を変更する場合は先頭に「.」を忘れないようにしましょう。今回はアプリのため、bodyタグ(表示部)の横幅を画面全体の60%とし、コンテンツを中央部に寄せるように設定しています。
最後に、JavaScript(動作)を作成します。 「// TODO」とコメントを記載した箇所を書き換えます。
~~~ 省略 ~~~
<script>
function start() {
return fetch("./api/start")
.then((res) => res.json())
.then((v) => {
document.getElementById("msg-system").innerHTML = v.systemMessage;
document.getElementById("msg-answer").innerHTML = v.resMessage;
});
}
function fetchAPI(answer) {
const body = new FormData();
body.append("answer", answer);
return fetch("./api/game", {
method: "POST",
body,
})
.then((res) => res.json())
.then((v) => {
document.getElementById("msg-system").innerHTML = v.systemMessage;
document.getElementById("msg-answer").innerHTML = v.resMessage;
});
}
function fetchAPIWithNumber() {
const inputNum = document.getElementById("input-num").value;
fetchAPI(inputNum);
}
</script>
~~~ 省略 ~~~
start()関数はサーバのゲーム開始用エンドポイント("/api/start”)に『ゲーム開始』メッセージを送信し、サーバーから受け取った結果を画面に表示しています。 『document.getElementById(ID名).innerHTML』に値を設定することで、指定したIDが設定されているHTML内容の書き換えを行っています。
fetchAPI(answer)関数とfetchAPIWithNumber()関数は、ゲーム中にサーバーのゲーム進行用エンドポイント("/api/game”)にユーザの答えを送信する関数です。 数値で回答した場合はテキストエリアに入力されている値を、ボタンで回答した場合はボタンに設定されている文字をサーバーに送信しています。
VSCodeのターミナルからserver.jsを起動します。
コマンドを実行したら、Webブラウザで「http://localhost:3000/」にアクセスしてみましょう。
FizzBuzzアプリの遊び方
STARTボタンをクリックするとゲーム開始です。
どちらから開始するかはランダムで決まります。 3の倍数でも5の倍数でもない場合は、答える数を指定して「数で答える」ボタンをクリックします。 倍数の場合は「Fizz」「Buzz」「FizzBuzz」ボタンをクリックして答えます。
すぐにサーバー側の返答が帰ってきます。 Fizz、Buzz、FizzBuzzもしくは数字の答えが表示されます。
ユーザが失敗するまで続きます。 失敗した場合は、どこで間違えたのか数字を表示してから待機状態に戻ります。
FizzBuzzアプリを改良してみよう
このままでは遊びにくいのでアプリを改良してみましょう。 例えば以下のような改良点があります。
- 現在の数値を表示する
- 数値のinputにサーバーから返却された現在の数値を設定する →入力が不要になる
- ランダムでコンピュータがミスをする
- ハイスコアを記録する
サーバー側の処理だけでなく、画面の見た目も変えたら面白く遊びやすくなるかもしれません。 色々と試してみましょう。
他にもできること
モジュールを利用すると他にもできることがたくさんあります。
例えば先ほど使用したexpressではWebページの入力チェックが可能です。 入力チェックにもいくつかありますが、express-validatorには必須入力や項目が一致しているかだけではなく、特定の形式であるか(クレジットカードやメールアドレスなど)などJavaScriptでチェックするには複雑なコードが必要になるものも用意されています。
他にもユーザ認証の仕組みを簡単に実装するモジュールや、サーバ内のデータベースと通信してデータを検索・追加が可能なものなどもあります。 npmで利用可能なモジュールは種類も豊富なので、目的に合ったものを探してみましょう。 npmパッケージが登録されているリポジトリで検索が可能です。 https://www.npmjs.com/
まとめ
今回はパッケージを利用してクライアント・サーバーシステム型のFizzBuzzアプリを作成しました。 ゲームとしては改良の余地がまだまだありますので、いろいろな機能を追加してみましょう。
また、このアプリを応用すればゲームだけではなくさまざまなサービスを作れます。 今回できるようになったことを組み合わせたらどんなサービスが作り出せるか考えてみるのも面白いですよ。
プログラミングスクールの選び方
転職を検討中の方向け
フリーランス・副業で活躍したい方向け
教養・キャリアアップしたい方向け
給付金について詳しく知りたい方向け