Node.jsとExpressでローカルサーバーを構築する(2) ―Expressでルーティング―

**リンク一覧**

1. [Node.jsとExpressでローカルサーバーを構築する(1) ―Node.jsとnpmの導入―](https://qiita.com/koedamon/items/37ea8e9175cf0fd62371)
2. Node.jsとExpressでローカルサーバーを構築する(2) ―Expressでルーティング―（本記事）
3. [Node.jsとExpressでローカルサーバーを構築する(3) ―JSONを返すスタブAPI―](https://qiita.com/koedamon/items/e8b3482811f275264592)
4. [Node.jsとExpressでローカルサーバーを構築する(4) ―他サーバーから画像を取得する―](https://qiita.com/koedamon/items/122d009327e138caded2)

# 概要
## この記事の概要
- 目的
  - Node.jsとExpressを利用して、PC上にローカルサーバーを立ち上げる
- 本記事のゴール
  - ブラウザで「localhost:8080」にアクセスすると、HTMLファイルが取得できる
  - HTMLファイルからリンクしている、CSS,JS,IMGファイルも取得できる
- 対象者
  - WEBフロント担当者
  - HTML,CSS,JavaScript(es2015含む)の基本的な構文を理解している人
  - HTTP通信、GET、POSTなどについて、ある程度理解している人（ざっくりで良いです）
  - 黒い画面にコマンドを打ち込むことに抵抗がない方
- 環境・バージョン
  - Windows10
  - Node.js(推奨版) 10.15.01
  - npm 6.4.1
  - Express 4.16.4

## フレームワークの利用
Node.jsのコアモジュールは、最低限の機能に留めた簡素なものです。
リクエストに対して適切なレスポンスを選択するルーティング作業などを一から書くのは少々面倒そうなので、Expressというフレームワークを利用したいと思います。
webアプリケーションを構築するのに便利なものがいろいろ詰まっており、公式サイトは一応日本語版も存在します！（2019年2月現在、APIリファレンスは翻訳されていません）
[Express（日本語）](https://expressjs.com/ja/)

なお、Eexpressを利用したWEBアプリを制作する際の雛形を生成してくれる、`express-generator`なる便利ツールが存在します。
ざっくりと仕組みを把握したら、次からはそういったツールを利用して構築すると良いかと思います。
[Express のアプリケーション生成プログラム](https://expressjs.com/ja/starter/generator.html)
今回は、単純に予め用意された静的ファイルを返すだけの機能しか求めていないので、見送ります。

# Expressのインストール
npmを利用してインストールします。
プロジェクトの作業用フォルダに移動して、下記コマンドを実行します。
「`npm`さん、`express`をインストールしてください。その際、`package.json`に記帳してください。」

```
$ npm install express --save
```

`--save`が、`package.json`への書き込みを指示するコマンドです。
インストールが無事完了すると、`package.json`は下記のようになります。

```json
{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.4"
  }
}
```

`dependencies`（依存関係）の項目に、`express`の名前とインストールしたバージョンが記載されています。
そして、作業フォルダ内に`node_modules`というフォルダが出現しています。 
このプロジェクト用にインストールしたパッケージのファイル群は、ここへ格納されます。
もう一つ、`package-lock.json`というファイルも作成されています。
このファイルは依存関係をもっと厳密に管理するためのものですが、とりあえず放っておきましょう。（削除はしないで）
気になる方はこちらの質問の回答をご覧ください。
[npm-package-lock-json-がなぜ必要なのかがわからない | stackoverflow](https://ja.stackoverflow.com/questions/42788/)

**devDependencies**
上記では、`dependencies`に記録されていますが、よく似た名前の`devDependencies`という項目もあります。
本記事では一貫して`dependencies`のみ扱いますが、npmインストールに関する記事では`devDependencies`もよく登場しますので、下記記事を一読されることをお勧めします。
[【いまさらですが】package.jsonのdependenciesとdevDependencies - Qiita](https://qiita.com/chihiro/items/ca1529f9b3d016af53ec)

# サーバーを構築する
## フォルダとファイルの準備
まずは、静的ファイルたちを用意しておきましょう。作業フォルダに以下の構成でフォルダとファイルを準備します。

```
sample/
  ├　public/
  │    ├ css/
  │    │   └ sample.css 
  │    ├ js/
  │    │   └ sample.js 
  │    ├ img/
  │    │   └ sample.png 
  │    └ index.html
  └ app.js
```

`/public/index.html`には、css・js・imgファイルへのリンクを貼っておきます。（ルートパスで）

```html
<!DOCTYPE html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>TEST</title>
    <link rel="stylesheet" href="/css/sample.css">
  </head>

  <body>
    <h1>Hello World!</h1>
    <p id="hoge"></p>
    <div>
      <img src="/img/sample.png">
    </div>
    <script src="/js/sample.js"></script>
  </body>
</html>
```

`/public/css/sample.css`と`/public/js/sample.js`にて、適当なコードを記述します。

```css
/* /public/css/sample.css */
h1 {
  font-size: 1.5rem;
  color: #0000ff;
}
img {
  max-width: 100%;
}
```

```js
/* /public/js/sample.js */
{
  const el = document.getElementById('hoge');
  el.innerText = 'HAHAHAHAHAHAHA!!!!';
}

```

## WEBサーバーのアプリケーションファイルを作成する
### app.jsファイルの概要
`/app.js`にサーバーの処理を記述していきます。

```js
/**
 * /app.js
 */ 
// express モジュールのインスタンス作成
const express = require('express');
const app = express();
// パス指定用モジュール
const path = require('path');

// 8080番ポートで待ちうける
app.listen(8080, () => {
  console.log('Running at Port 8080...');
});

// 静的ファイルのルーティング
app.use(express.static(path.join(__dirname, 'public')));

// その他のリクエストに対する404エラー
app.use((req, res) => {
  res.sendStatus(404);
});

```

先ほどインストールした`express`のモジュールを読み込みます。
`http`モジュールでは`http.createServer`メソッドでサーバを生成していましたが、`express`は読み込んだモジュールをそのまま実行して、生成しています。

```js
const express = require('express');
const app = express();
```

そして生成されたサーバオブジェクトの`listen`メソッドを実行してリクエストの受付を開始します。
1番目の引数はポート番号、2番目の引数は開始後のコールバック関数です。

```js
app.listen(8080, () => {...
```

[公式ガイド：Express Hello Worldの例](https://expressjs.com/ja/starter/hello-world.html)

### Expressでルーティング

ここまでは`http`モジュールを利用した場合とそう変わりません。次のコードで、Expressを利用したルーティングを行っています。

```js
app.use(express.static(path.join(__dirname, 'public'))));
```

**useメソッド**
`use`メソッドはルーティグを行うミドルウェア（中間処理を行う関数）を受け取ります。自分で書くことも出来ますが、ここでは`express`の静的メソッド`static`を利用します。 
このメソッドに、静的ファイル群のルートパスとなるフォルダのパスを渡すと、その配下に格納されているファイルに対するリクエストを、よしなに捌いてくれるミドルウェアを生成してくれます。

**pathモジュール**
`static`メソッドに引き渡しているところで利用している`path`モジュールは、Node.jsのコアモジュールです。ファイルパスの文字列を操作するためのツールが含まれています。ファイル自体の操作は出来ません。
[node.jsでパスの操作 | 山本隆の開発日誌](https://www.gesource.jp/weblog/?p=8199)
[公式リファレンス：Path（英語）](https://nodejs.org/api/path.html)

**__dirname**
`__dirname`は、Node.jsで用意されている事前読み込み不要のモジュールで、記述されたファイルのパスを返します。
`app.js`が`C:/sample/app.js`にある場合、`C:/sample`が返ってきます。
そしてそのパスと、静的ファイルが格納されているフォルダ名`public`を`path.join`メソッドでつなげて完全なパス文字列`C:/sample/public`を生成しています。

整理をすると、

1. `public`フォルダまでのパス文字列を作成
2. 1.の文字列を`express.static`メソッドに渡して静的ファイルをルーティングするミドルウェアを作成
3. 2.のミドルウェアを`app.use`メソッドに渡して、`8080`へのアクセス時に利用されるようにする

これにより`public/`が実質サイトのルートとなります。
そのため、`localhost:8080/`へのアクセスは、`public/`直下の`index.html`が返されます。
ルートパスで`/common/css/sample.css`と指定すると、`C:/sample/public/common/css/sample.css`が返されます。

ここでは`static`に丸投げしていますが、もっと細かく「このパスの場合はこのフォルダ」と指定することも可能です。
第一引数に該当のサイトパス、第二引数にミドルウェアを渡します。

```js
app.use(`/fuga/piyo`, express.static(path.join(__dirname, 'moi'))));
```

上記の例では、`/fuga/piyo`へアクセスすると`moi/`フォルダのファイルが返ってきます。

[公式ガイド：ルーティング](https://expressjs.com/ja/guide/routing.html)
[公式ガイド：Expressでの静的ファイルの提供](https://expressjs.com/ja/starter/static-files.html) 

### 404Not Found
最後のコードは、該当ファイルが存在しないときに404エラーを返すように設定しています。「Not Found」の文字列を返すだけの簡素なものです。

[公式リファレンス：res.sendStatus（英語）](http://expressjs.com/ja/api.html#res.sendStatus)![]()


## 動作確認

では、コマンドプロンプト上で下記コマンドを実行します。（作業用フォルダに移動した上で）
「nodeさん、app.jsファイルを実行してください！」

```
$ node app.js
```
これでサーバーが立ち上がりました。コンソールに`Running...`と出力されていると思います。
そして、ブラウザより`localhost:8080`へアクセスしてみます。

![localhost02.gif](https://qiita-image-store.s3.amazonaws.com/0/362737/fc11dd43-3767-4554-763c-d3530cebeeb9.gif)

無事にレスポンスを受け取れました！！
CSS、JS、IMGファイルも実行結果から読み込めていることが分かりますね。

終了する場合は、サーバーを立ち上げるコマンドを実行したコマンドプロンプト上で`Ctrl+C`を入力して、プロセスを終了させます。
サーバー起動中は、起動させたコマンドプロンプト上で別のコマンドを入力することは出来ません。新たにもうひと窓開いてください。


初心者の拙い記事を読んでいただき、ありがとうございました。お役に立てていたら幸いです。
次回は、JSONデータを返すAPIを実装していきたいと思います。

# 参考情報

[Express公式サイト(英語)](https://expressjs.com/)
[Node.jsとExpressでWeb APIを作ってみよう](https://sbfl.net/blog/2018/08/25/nodejs-express-webapi/)