ExpressでWebサーバー構築

# はじめに
Webサーバーを構築する方法はたくさんありますが、私がインプットしたものを共有したいと思います。
Expressを用いることで、アクセス先のパスとアクセスの種類によって処理を柔軟に変更できるサイトを構築できます。



# 準備
この記事で紹介する方法を実現するために、いくつか準備をします。

:::note info
既に環境がある方は省略してください
:::


---


### 1. [Node.js](https://nodejs.org/ja "Node.js")のダウンロード・インストール
### 2. [Git.Bash](https://gitforwindows.org/ "Git for Windows")のダウンロード・インストール

<details><summary>説明</summary>
Git.BashとNode.jsについての細かい説明は割愛しますが、

- Git.BashはNode.jsを利用するため
- Node.jsはJavaScriptをパソコンで実行して、**Webサーバを建てるため**

と認識していただければと思います。
</details>


---


### 3. ディレクトリ(フォルダ)の作成

Webサイトを構築するためのディレクトリを作成します。
![Sampleフォルダ.png.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524071/999980d3-1da4-26d1-8b8e-a355448171ef.jpeg)


---


### 4. ディレクトリにnpmを適用する

GitBashを起動して、作成したディレクトリに移動し、

`npm init`

コマンドを実行します。

nameやversion等どうするか訊かれると思いますが、指定がなければEnterで飛ばしても問題ありません。

<details><summary>説明</summary>

実行すると、ディレクトリ配下に**package.json**ファイルが作成されます。
**package.json**ファイルには、フォルダのバージョン情報や利用しているパッケージ情報などが保存されます。

```
Sample
    - package.json
```

npmとは、Node.jsのパッケージを管理するシステムで、次に紹介するパッケージの利用に使用します。
</details>


---


### 5. expressパッケージをインストールする

作成したディレクトリ内で、

`npm install express`

コマンドを実行します。

<details><summary>説明</summary>

実行すると、ディレクトリ配下に**package-lock.json**ファイルと**node_modules**フォルダが作成され、**node_modules**フォルダにはExpressのパッケージと、パッケージが利用するパッケージが保存されます。
```
Sample
    node_modules
        - パッケージたくさん
    - package-lock.json
    - package.json
```
</details>



# サーバーを建てる

### 1. プログラムを書く

準備は完了しました。まずはサーバーを作成するプログラムをJavaScriptで書いてみましょう。
作成したディレクトリ直下に**index.js**というファイルを作成します。
```
Sample
    - index.js
    - package-lock.json
    - package.json
    node_modules
        - パッケージたくさん
```
作成したら、index.jsファイル先頭に
```javascript:index.js
const express = require('express');   // expressモジュールを読み込み
const app = express();   // expressオブジェクトを作成
const PORT = 3000;   // ポート番号を指定
```
と記述します。

<details><summary>説明</summary>

expressモジュールを読み込み、expressインスタンスをappとして定義しています。 **app**という名前を付けるのが一般的のようです。
appにはexpressフレームワークで用いるメソッドなどが入っています。

ポート番号は3000にしていますが、**1024~65535**であれば基本的に問題ありません。もしうまくいかなければ別のポートにします。
</details>

index.jsファイル末尾には
```javascript:index.js
// サーバーを起動
app.listen(PORT, () => {
    console.log(`ポート${PORT}で待受中...`);
});
```
と記述しておきましょう。これでサーバー作成部分の記述は完了です。

<details><summary>説明</summary>

コンソール出力は必要ではありませんが、サーバーが起動したことを確認するために書いておいたほうがいいでしょう。
起動した際のステータスを書いておいても良いかもしれませんね。
</details>

<details><summary>現在のindex.js全体は以下の通りです。</summary>

```javascript:index.js
const express = require('express');   // expressモジュールを読み込み
const app = express();   // expressオブジェクトを作成
const PORT = 3000;   // ポート番号を指定

// サーバーを起動
app.listen(PORT, () => {
    console.log(`ポート${PORT}で待受中...`);
});
```
</details>


---


### 2. サーバーを起動してみる

サーバーを起動してみましょう。
GitBashを起動して、作成したディレクトリに移動し、

`node index.js`

コマンドを実行します。
コンソール出力を記述していれば、
```
ポート3000で待受中...
```
などと出力されます。これが表示されていれば、**サーバーは無事起動できています**。
サーバーが無事起動できていることが確認出来たら、一度`Ctrl`+`C`で停止しておきましょう。



# 要求に対して応答させる
サーバーが起動できることは確認しました。
次は利用者からの**要求に対して処理を行い、応答を返せる**ようにします。

<details><summary>説明</summary>

サーバーが提供するサービスに対して、利用者を**クライアント**といいます。
クライアントには様々なものがありますが、今回のように、Webサイトを提供するサーバーに対しての主なクライアントは**Webサイトにアクセスする人**(が利用するブラウザアプリ)のことを言います。
</details>

サーバー起動部分の手前に、
```javascript:index.js
// ホームページに対してGET要求があった際の処理
app.get('/', (req, res) => {
    res.send(`/ に ${req.method} 要求を受けました！`);
});

// /nextに対してGET要求があった際の処理
app.get('/next', (req, res) => {
    res.send(`/next に ${req.method} 要求を受けました！`);
});
```
と記述してみましょう。

<details><summary>説明</summary>

 **app.get()** は、**第一引数のパスに対してGET要求が来たら第二引数のコールバック関数を実行する関数**です。

この他にも**POST要求にはpost**()や**PUT要求にはput**()、**DELETE要求にはdelete**()など、様々な要求に対する処理を記述するメソッドがあり、基本的にはこのような記述を羅列して、**要求と要求のあったパスの組み合わせ**で処理を別々に書いていきます。これを**ルーティング**といいます。

上の場合、第一引数は`/`、自分のパソコンのブラウザから見る場合、`localhost:3000`
下の場合、第一引数は`/next`、自分のパソコンのブラウザから見る場合、`localhost:3000/next`
へのGET要求に対する処理を記述しています。

第二引数の関数には**リクエスト情報が入ったインスタンス**と、**レスポンス情報が入ったインスタンス**が渡されます。
この場合、**req**という変数にリクエストインスタンス、**res**という変数にレスポンスインスタンスが入っており、resのsend()というメソッドでreqのmethodというプロパティの内容を送っています。
send()やmethodに関しては後述します。
</details>

<details><summary>現在のindex.js全体は以下の通りです。</summary>

```javascript:index.js
const express = require('express');   // expressモジュールを読み込み
const app = express();   // expressインスタンスを作成
const PORT = 3000;   // ポート番号を指定

// ホームページに対してGET要求があった際の処理
app.get('/', (req, res) => {
    res.send(`/ に ${req.method} 要求を受けました！`);
});

// /nextに対してGET要求があった際の処理
app.get('/next', (req, res) => {
    res.send(`/next に ${req.method} 要求を受けました！`);
});

// サーバーを起動
app.listen(PORT, () => {
    console.log(`ポート${PORT}で待受中...`);
});
```
</details>

この状態で`node index.js`コマンドでサーバーを起動し、
お使いのブラウザのアドレスバーに

`localhost:3000`

と入力してみると、ブラウザの画面に
![応答確認.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524071/89f44b77-f8d0-57ac-0035-ca6eeeb82b99.jpeg)
と表示されます。

`localhost:3000/next`

と入力してみると、
![next応答確認.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524071/3b59acf1-3cbf-5b6f-2981-536904b6a51f.jpeg)
と表示されます。

<details><summary>説明</summary>

今回行なったのは、

**クライアント側　：　ブラウザからlocalhostの3000番ポート(建てたサーバーのルート)にGET要求を送る
サーバー側　：　「/」というパスへGET要求が届く
サーバー側　：　要求に対して文字列を返す
クライアント側　：　返された文字列をブラウザ画面に表示する**

**クライアント側　：　ブラウザからlocalhostの3000番ポート(建てたサーバーのルート)の/nextにGET要求を送る
サーバー側　：　「/next」というパスへGET要求が届く
サーバー側　：　要求に対して文字列を返す
クライアント側　：　返された文字列をブラウザ画面に表示する**

という動作です。
</details>



# Expressのメソッド・プロパティ

Expressの基本的な使い方は以上です。
Express特有のオブジェクトから呼び出せる主なメソッドやプロパティは以下のものがあります。


## Expressインスタンス
Expressインスタンスには、主に以下のものがあります。
インスタンスはappという変数に定義しています。


### app.set('設定項目', '設定内容')

<details><summary></summary>

**Expressフレームワークの設定**を行います。
主な例としては、テンプレートエンジンを利用したファイルを読み込むときに、使うテンプレートエンジンの宣言をするなどです。
```javascript
app.set('view engine', 'ejs');   //例：EJSテンプレートエンジンを利用したい！
```
</details>


### app.use(関数)

<details><summary></summary>

**すべてのリクエストに対して最初に実行する処理を記述**します。
コールバック関数の前に**パスを渡すことで、指定したパスにきたリクエストのみに絞る**ことができます。
主な例としては、クライアントにアクセスさせたいフォルダのパスを指定するときなどです。
```javascript
app.use(express.static(__dirname + 'public'));
```
</details>


### ルーティングの設定

<details><summary></summary>

**リクエストとパスに対応した処理**を記述します。

第一引数で**指定するパスへのGETリクエストに対して実行する処理**を記述します。
第二引数のコールバック関数には
**req : リクエストに関する情報
res : レスポンス送信に関する情報
next : 次に実行したいコールバック関数**
が渡されます。**nextはエラー処理などで利用**されます。nextで利用するコールバック関数は、app.useで定義します。
```javascript
app.get('/', (req, res) => {
    if (req.query.q) {
        res.send(`${req.query.q}についての検索`);
    } else {
        next(new Error('No Search, No Life.'));//検索されていなければエラー
    }
});
```
<details><summary>ルーティング設定メソッドは以下のものがあります。</summary>

```javascript
app.get()   //GET要求
app.post()
app.put()
app.head()
app.options()
app.trace()
app.copy()
app.lock()
app.mkcol()
app.move()
app.propfind()
app.proppatch()
app.unlock()
app.report()
app.mkactivity()
app.checkout()
app.merge()
app.m-search()
app.notify()
app.subscribe()
app.unsubscribe()
app.patch()
app.search()
app.delete()
```
</details>
</details>

### app.listen(ポート番号, 関数)

<details><summary></summary>

指定したポート番号で**Webサーバーを起動**します。
このメソッドを記述しない限り、サーバーは応答しません。
```javascript
app.listen(3000, () => {
    console.log(`ポート3000で待受中...`);
});
```
</details>


## リクエストインスタンス

リクエストインスタンスには、主に以下のものがあります。
インスタンスはreqという変数に定義しています。


### req.query

<details><summary></summary>

クエリストリングに渡された値を含みます。

`?q='abc'`

URLのクエリストリングがこのような場合、

`req.query.q`

といった形で`'abc'`というクエリストリングの値を参照できます。
</details>


### req.method

<details><summary></summary>

リクエストのHTTPメソッドの種類を含みます
GETリクエストならば`'GET'`という値が格納されています。
</details>


## レスポンスインスタンス
レスポンスインスタンスには、主に以下のものがあります。
インスタンスはresという変数に定義しています。


### res.send(レスポンスボディ)

<details><summary></summary>

リクエスト元に対してレスポンスボディの値を返します。返した値はブラウザでは画面に表示されます。
```javascript
res.send('応答です');
```
</details>

### res.render(ファイル <, オブジェクト>)

<details><summary></summary>

送信元に対してテンプレートファイルと任意のオブジェクトを返します。
送信元のブラウザでは、受け取ったテンプレートファイルとオブジェクトからWebページのドキュメントを作成します。
レンダリングできるテンプレートファイルは事前にapp.set()で指定したパスの配下にある必要があり、利用するテンプレートエンジンも登録しておく必要があります。
```javascript
app.set('view engine', 'テンプレートエンジン');
app.set('views', パス);

app.get('/', (req, res){
    const hello = 'こんにちは';
    res.render('home', hello);
});
```
</details>



# さいごに
この記事では私なりの解釈を書きましたが、私はまだまだ勉強中なので、Expressはほとんど理解できていないと思います。
間違ったところ等あれば、ご指摘お願いします！

# 参考文献

https://qiita.com/nekoe/items/06cbe49f64d56d31b793#express%E5%86%85%E9%83%A8%E3%81%AE%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%83%AD%E3%82%B0%E3%82%92%E5%87%BA%E5%8A%9B%E3%81%99%E3%82%8B

https://expressjs.com/