Nuxt.jsには、serverMiddlewareという機能があります。この機能を利用するとNuxt.js内部でAPIサーバを構築することができます。今回は、serverMiddlewareと複数のAPIサーバとやりとりする際の構成とその際の注意点について紹介します。

Backends For Frontends(BFF)とは

BFFとは、Backends For Frontendsのことで、名前の通りフロントエンド専用のバックエンドです。フロントエンド向けに公開されたAPIで、その処理の中では、APIコールを行ったり、フロントエンドが必要するとデータへの変換などをおこないます。

nuxt.jsのserver middlewareを使う構成

nuxt.jsでは、server middlewareを使うことでapiを実装することができます。nuxtjs/proxyを使うことで、特定のパス例えば’/api’へのアクセスをserver middlewareに転送することができます。これらの機能をあわせると下記のような構成を作ることができます。

簡単にそれぞれの例を見ていきましょう。

server middlewareの例

別のサービス(http://localhost:8080)にあるところからデータを取得して、画面専用のデータを生成するようなイメージを想定しています。

 
import express,
{ 
  Request,
  Response
}
from 'express'
import axios from 'axios'

const app = express()

// for parsing application/json
app.use(express.json())
// for parsing application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }))

app.get('/api/test', async (_req: Request, res: Response) => {
  // res.send('hello world!')
  const reqUrl = 'http://localhost:8080'
  const resData = await axios.get(reqUrl)
  res.send(resData.data)
})

app.get('/api/500error', async (_req: Request, res: Response) => {
  const reqUrl = 'http://localhost:8080/500error'
  const resData = await axios.get(reqUrl)
  console.log(resData.status)
  res.send(resData.data)
})

export default app

設定ファイル(nuxt.config.js)

proxyの設定とserverMiddlewareの設定を追加します。serverMiddlewareは、パスごとに処理するハンドラを分けることもできますが、今回は、/apiへのリクエストは、すべてexpressで作成しているserver middlewareへ転送するような設定になっています。

 
  // Axios module configuration: https://go.nuxtjs.dev/config-axios
  axios: {
    proxy: true,
    debug: true,
  },
  proxy: {
    // serverMiddlewareへ転送する
    '/api/': {
      target: 'http://localhost:3000',
    },
  },
  serverMiddleware: [
    '~/src/server',
  ],
}

外部サービスの例

下記は、外部サービスの例です。500エラーや正常応答を返すだけのシンプルなAPIサーバです。

 
import express,
{ 
  Request,
  Response
}
from 'express'
import cors from 'cors'

const app = express()
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

app.get('/', (_req: Request, res: Response) => {
  res.send('Hello')
})

app.get('/500error', (_req: Request, res: Response) => {
  res.status(500).send({error: 'error'})
})

app.listen(8080, () => {
  console.log('Example app listening on port 8080!')
})

server middlewareでのエラハンドリングを忘れると

先程紹介したサンプルコードは、server middlewareでエラハンドリングを行っていません。もう一度下記のコードをみてみましょう。

 
app.get('/api/xxxx', async (_req: Request, res: Response) => {
  const reqUrl = 'othres serviceエンドポイント'
  const resData = await axios.get(reqUrl)
  console.log(resData.status)
  res.send(resData.data)
})

外部サービスがエラーを返した場合のエラーをハンドリングしていません。例えば、外部サービスから500エラーが返却されるとexceptionが発生するので、res.send()が呼ばれずに、このAPIコール利用者は、応答待ちになってしまいます。

駆け足になりましたが、nuxt.jsでserver middlewareを使ってbffを導入する方法とその際の注意点について紹介しました。お疲れ様でした。