NEXTJS & node expressでapiサーバー構築をしてみた

NEXTJS(client)環境にnodeサーバー(API)を構築しAPIが叩ける環境構築をしてみた。

nodejsの特徴

  • Google ChromeのJavaScriptエンジン(V8 Engine)に基づいて作られた、サーバー側のプラットフォーム
  • 高性能ネットワークサーバー
  • シングルスレッド(Single Thread)のイベントループ(Event Loop)ベース
  • 非同期I/O処理(Non-Blocking I/O) など…

Expressとは

Express.jsはNode.js環境でWeb applicationやAPIを構築を簡単にできる人気のプレイムワークだ。

Express インストール

想定するディレクトリー

api //- api server
 ├── package.json
 └── server.js 
client //- NEXTJS project
 | 
 ...省略...

apiディレクトリー直下から実行npmを利用する宣言後3つのパッケージをインストール

$ npm init
$ npm install express nodemon concurrently

NEXTJS プロジェクト作成

npx create-next-app

apiディレクトリーのpackage.jsonにNEXTJS用サーバーとnode用サーバー両方のサーバーのコマンド定義

package.json
{
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "client": "cd ../ && cd client && npm run dev",
    "server": "nodemon ./server.js localhost 3080",
    "dev": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\""
}
terminal
$ npm run client //- NEXTJSのサーバーが立ち上がる
$ npm run server //- ノードサーバーが立ち上がる
$ npm run dev //- 両方立ち上がる
./api/server.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();

const port = process.env.PORT || 3080;

app.use(bodyParser.urlencoded({ extended: true }));

const allData = [
  {
    id: 1,
    name: '山田 二郎',
    birthday: '20000812',
    sex: '男',
    jab: '大学生',
  },
  ..省略...
];

app.use(bodyParser.json());

app.get('/api/members', (req, res) => {
  res.send(allData);
});

app.listen(port, () => console.log(`Listening on port ${port}`));

3080ポートの/api/memberに接続するとJSONデータにアクセスすることができた。

node-server-testdata

NEXTJS設定

APIのURLは用意できたのでAPIを習得してみた。 まず、components直下にAPIから習得するデーターをセッティングするコンポーネントを作成した。

components/Member.tsx
import React from 'react'
interface Props {
  id: number,
  name: string,
  birthday: string,
  sex: string,
  jab: string,
}
export const Member: React.FC<Props> =({
  id,
  image,
  name,
  birthday,
  gender,
  jab,
}) => {
  return (
    <div>
        <h2>{name}({id})</h2>
        <p>{birthday}</p>
        <p>{sex}</p>
        <p>{jab}</p>
    </div>
  )
}

export default Member

あと、indexにコンポーネントを表示する作業をした。 nodejsのサーバーポート3080にしたのでAPIのURLhttp://localhost:3080/api/membersになるはず…だと思ったが..

page/index.tsx
import React, { useEffect, useState } from 'react'
import router from 'next/router'
import Member from '../components/Member'
import axios from 'axios'
interface props {}
export const Index: React.FC<props> = ({
}) => {
  const [ datas, setData ] = useState([])
  const [ isLoding, setIsLoding ] = useState(false)
  useEffect(() => {
    const getBusinessData = async () => {
      setIsLoding(true)
      const url = `http://localhost:3080/api/members`
      const res = await axios.get(url).then()
      setIsLoding(false)
      setData(res.data)
    }
    getBusinessData()
  },[])
  console.log(setData)
  if(isLoding) {
    return <div>Loding......</div>
  }
  return(
    <>
      {
        datas.map((data:any, index) => {
          return(
            <Member
              key={data.id}
              id={data.id}
              name={data.name}
              birthday={data.birthday}
              sex={data.sex}
              jab={data.jab}
            />
          )
        })
      }
    </>
  )
}
export default Index

ローカル確認してみたらAPIデータが上手く習得できなかった… node-server-apierror

何時間かうろうろして解決方法を見つけた。

nextのjsonファイルにproxyを記載すればできるらしい。

client/package.json
"proxy": "http://localhost:3080/", <-追加
"dependencies": {
  ...省略...
}

これで上手くいくはずだが… node-server-apierror 同じエラーだ…

またググってみたらpackage.jsonに記載するのはReactの場合らしい。 NEXTJSの場合はまたproxyサーバーを用意しないといけないみたいだディレクトリーが下記のように変わる。

api //- api server
 ├── package.json
 └── server.js 
client //- NEXTJS project
 ├── server.js <-追加
 | 
 ...省略...

client用のサーバーはclient直下のserver.jsに記載した。

client/server.js
const express = require('express')
const next = require('next')
const { createProxyMiddleware } = require("http-proxy-middleware")

const port = process.env.PORT || 3030
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

const apiPaths = {
    '/api': {
        target: 'http://localhost:3080', 
        changeOrigin: true
    },
}

const isDevelopment = process.env.NODE_ENV !== 'production'

app.prepare().then(() => {
  const server = express()

  if (isDevelopment) {
    server.use(['/api'], createProxyMiddleware(apiPaths['/api']));
  }

  server.all('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(port, (err) => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
  })
}).catch(err => {
    console.log('Error:::::', err)
})

NEXT用のサーバーはポート3030にした。

./client/package.json
"scripts": {
    "build": "next build",
    "server": "cd ../ && cd api && npm run server",
    "export": "next build && next export",
    "dev": "NODE_ENV='development' node server.js",
    "start": "concurrently --kill-others-on-fail \"npm run server\" \"npm run dev\""
  },

クライアントのコマンドも同じくnodeとNEXT両方走るように設定した。

NEXT側のAPIのURLも3080から3030に変更てNEXTを回してもると上手く表示がされるのが確認できた。

apidata表示画面

関連記事

 gatsby シンボルマーク

Gatsbyプロジェクトにnodemailer & netlify functionでcontactフォームを実装。

© 2021 Thunder Fury. All rights reserved.