Help us understand the problem. What is going on with this article?

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

目次


概要

簡易的な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を作りたい場合、下記のようになる。

// 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に書き、

ブラウザでアクセスすると・・・

app.get('/api/', (req, res, next) => {
  res.json({'api': 'test'})
})

404エラー

Why!!!???

LIGの記事を読んでみると、
Nuxtに「serverMiddleware」を設定して、API サーバ的な動きをさせてみた

公式を読んでみると、
API: serverMiddleware プロパティ
どうやらserverMiddlewareを利用すれば、理想としている簡易APIが作れそうだ!
早速手順にそって、簡易APIを作ってみる!

Nuxt.js + Express.js + serverMiddleware = 😆

api記述用ファイルを準備

  1. apiディレクトリをNuxtプロジェクト直下に作成
  2. api/index.jsを作成
  3. api/index.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を読み込む様に追記する。

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に仮データとして、下記を記述

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

api/index.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/ にアクセス。

表示された!😆

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

/api/list/◯◯ の様なurlで動的に処理する場合

パス部分に*、コールバック関数のreq.paramsを利用すれば、urlの /list/◯◯ の◯◯の部分を取得可能。

app.get('/list/*', (req, res) => {
  console.log(req.params)
})

/list/1は、 { '0': '1' } と出力される。

もう少し厳密に、◯◯部分を取得したい場合は、 : を利用する。

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でjsonの内容を読み込む
2. 読み込んだ内容をjsonオブジェクト化
3. 追加処理(本来は、postで受け取った値を追加する)
4. 最新の内容を fs.writeFileSync で書き込む

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

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

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

  // fs.readFileでjsonの内容を読み込む
  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が利用出来るが、複雑な処理になると、コールバック地獄になりがち。
なので、同期か非同期かはそれぞれ利用するタイミングを考える必要がある。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした