Express.jsでミニマムなローカルサーバ構成

# 目次
- [概要](#概要)
- [環境構築](#環境構築)
- [Express.jsのみでAPIを作る方法](#expressjsのみでapiを作る方法)
- [Express.jsをNuxt.jsで利用してみる](#expressjsをnuxtjsで利用してみる)
- [Nuxt.jsに設置したjsonファイルから結果を取得するAPI](#nuxtjsに設置したjsonファイルから結果を取得するapi)
- [Nuxt.jsに設置したjsonファイルにデータを書き込むAPI](#nuxtjsに設置したjsonファイルにデータを書き込むapi)

***


# 概要
簡易的なREST APIをサクッと作りたい・・・。
しかし、その為にバックエンドエンジニアの方にお願いしたり、PHPを調べながら書いたりしたくない！
自分でちゃちゃっとJSで書きたい！！
Express.jsは、そんな人向けのNode.js（サーバサイドJS）のフレームワークです。

# 環境構築
```
npm i express  
もしくは、  
Nuxt.jsの環境構築時にExpress選択 ← おすすめ
```

# Express.jsのみでAPIを作る方法
Express.jsの基本的な使い方は下記の通り。  
1. モジュールをロードしてインスタンス化
2. ポート番号を指定して待受開始
3. アプリケーションの処理を記述
  
ブラウザから /api/list/ にアクセスし、結果を表示する様なapiを作りたい場合、下記のようになる。

```js

// 1.expressモジュールをロードし、インスタンス化後、変数appに代入
const express = require('express')
const app = express()

// 2.listen()メソッドを実行し、3000番ポートで待ち受け
const server = app.listen(3000, () => {
  console.log(`node port:${server.address().port}`)
})

// ---------- ↑ここまでが基本 ----------
// 仮の配列を作成
const list = [
  {id: 1, keyword: 'test1'},
  {id: 2, keyword: 'test2'}
]

// 3.urlに応じた処理を記述
// app.getとした場合は、getリクエスト。
// app.postとした場合は、postリクエストの時に動作する。
app.get('/api/list/', (req, res, next) => {
  // 定義したデータを返す
  res.json(list)
})

```

# Express.jsをNuxt.jsで利用してみる
Nuxt.jsの環境作成時に **Express** を選択した場合は、server/index.js に Express.js を記述するためのファイルが作成される。  
※**npm run dev**実行時は、このserver/index.jsが読み込まれる。  
  
Nuxt.jsからExpress.jsを利用する場合は、**APIを作る方法で記述した1,2は記述済み(^^)**  
早速、URLをブラウザに入力し、HelloWorldを表示するAPIを作ってみる。  

## Nuxt.js + Express.js = 😣
上記を踏まえ、簡単♪簡単♪と思って、以下のようにserver/index.jsに書き、  
ブラウザでアクセスすると・・・

```js

app.get('/api/', (req, res, next) => {
  res.json({'api': 'test'})
})
```
  
**404エラー**  

Why!!!???  
  
LIGの記事を読んでみると、
[Nuxtに「serverMiddleware」を設定して、API サーバ的な動きをさせてみた](https://liginc.co.jp/438249)  
  
公式を読んでみると、
[API: serverMiddleware プロパティ](https://ja.nuxtjs.org/api/configuration-servermiddleware/)
どうやら**serverMiddleware**を利用すれば、理想としている簡易APIが作れそうだ！
早速手順にそって、簡易APIを作ってみる！
  
## Nuxt.js + Express.js + serverMiddleware = 😆
### api記述用ファイルを準備
1. apiディレクトリをNuxtプロジェクト直下に作成
2. api/index.jsを作成
3. api/index.jsに以下を記述

```js

const express = require('express')
const app = express()

app.get('/', function(req, res) {
  res.send('HelloWorld');
});

module.exports = {
  path: '/api/',
  handler: app
};
```
  
※この時点で、**npm run dev**でローカルサーバを立ち上げ、  
http://localhost:3000/api/ にアクセスしてもPage Not Foundと表示される。

### serverMiddleWareを設定
nuxt.config.jsに、上記で作成したapi/index.jsを読み込む様に追記する。

```js
module.exports = {
  serverMiddleware: ["~/api/"],
}
```

npm run dev でサーバ再起動後、ブラウザで下記にアクセス。
http://localhost:3000/api/
  
**HelloWorld** と表示された！！😆

# Nuxt.jsに設置したjsonファイルから結果を取得するAPI
## やりたいこと
1. Nuxt.jsディレクトリ内に、jsonファイルを設置
2. ブラウザでapiのURLにアクセスするとjsonの内容が表示される

## 準備
**※serverMiddleWareは設定済み**
1. Nuxt.jsプロジェクト直下に、databaseというディレクトリを作成
2. database/list.json というjsonファイルを作成
3. list.jsonに仮データとして、下記を記述

```js
[
  {
    "key": "A1",
    "name": "test"
  }
]
```

## api/index.jsの設定

以下を記述

```js
const fs = require('fs')

app.get('/list/', (req, res) => {
  fs.readFile('${__dirname}/../database/list.json', 'utf-8', (err, data) => {
    if(err) {
      res.status(500).send(err)
    } else {
      console.log('data',data)
      res.status(200).send(data)
    }
  })
})
```
↓元々のソースのこの部分は間違い！！
requireは、最新の状態ではなく、ソース読み込み時の状態のため、
常に最新を読みたい場合のファイル読み込みは、 **fs.readFile** で！
~~const list = require('../database/list.json')~~
~~res.send(list)~~
  
npm run devでローカルサーバを立ち上げ、 http://localhost:3000/api/list/ にアクセス。

表示された！😆

```js
[
  {
    key: "A1",
    name: "test"
  }
]
```

## /api/list/◯◯ の様なurlで動的に処理する場合
パス部分に*、コールバック関数のreq.paramsを利用すれば、urlの `/list/◯◯` の◯◯の部分を取得可能。

```js
app.get('/list/*', (req, res) => {
  console.log(req.params)
})
```
/list/1は、 `{ '0': '1' }` と出力される。
  
もう少し厳密に、◯◯部分を取得したい場合は、 `:` を利用する。 

```js
app.get('/list/:id/:operation?', (req, res) => {
  console.log(req.params)
})
```

`?` は未指定でもokという意味。`?` を記述しない場合、  
/list/aaa/bbb はokだが、 /list/aaa といったurlは404扱いになる。  
  
/list/1は、 `{ id: '1', operation: undefined }` と出力される。  
/list/aaa/bbbは、 `{ id: 'aaa', operation: 'bbb' }` と出力される。


# Nuxt.jsに設置したjsonファイルにデータを書き込むAPI
## やりたいこと（一旦、通信部分は省く）
指定のファイルに、オブジェクト形式のデータを追加する。
→ ファイル書き込みが出来ないといけない。  
  
## api/index.jsに記述
ファイル読み込みと同じくファイル操作系は、 **fsモジュール** を利用し、下記の様な処理手順を踏む。  
1. fs.readFileでｊsonの内容を読み込む
2. 読み込んだ内容をjsonオブジェクト化
3. 追加処理（本来は、postで受け取った値を追加する）
4. 最新の内容を fs.writeFileSync で書き込む

ソースの内容を抜粋すると以下の様になる。

```js
const express = require('express')
const app = express()
const fs = require('fs') // fsモジュールをロード

app.get('/create/', (req, res) => {

  // fs.readFileでｊsonの内容を読み込む
  fs.readFile(`${__dirname}/../database/list.json`, 'utf-8', (err, data) => {
    if(err) {
      res.status(500).send(null)
    } else {
      // 読み込んだ内容をjsonオブジェクト化
      const jsonObject = JSON.parse(data)

      // 追加処理（本来は、postで受け取った値を追加する）
      jsonObject['A3'] = { 'key': 'A3' }

      try {
        // 最新の内容を fs.writeFileSync で書き込む
        fs.writeFileSync(
          `${__dirname}/../database/list.json`,
          JSON.stringify(jsonObject, undefined, '  ')
        )
        res.status(200).send('ok')
      } catch(e) {
        res.status(500).send(null)
      }
    }
  })
})
```

fsモジュールを利用して、ファイル操作を行う際、  
ファイル読み込みには、 **readFile** , **readFileSync** があり、
ファイル書き込みには、 **writeFile** , **writeFileSync** がある。  
  
それぞれの違いは、同期か非同期かというところ。

Sync系は処理がシンプルに書けるが、Node.js特有のノンブロッキングIOが利用できない。
非同期系は、ノンブロッキングIOが利用出来るが、複雑な処理になると、コールバック地獄になりがち。
なので、同期か非同期かはそれぞれ利用するタイミングを考える必要がある。