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用サーバー両方のサーバーのコマンド定義
{
"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 //- 両方立ち上がる
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データにアクセスすることができた。
NEXTJS設定
APIのURLは用意できたのでAPIを習得してみた。 まず、components直下にAPIから習得するデーターをセッティングするコンポーネントを作成した。
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になるはず…だと思ったが..
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データが上手く習得できなかった…
何時間かうろうろして解決方法を見つけた。
nextのjsonファイルにproxyを記載すればできるらしい。
"proxy": "http://localhost:3080/", <-追加
"dependencies": {
...省略...
}
これで上手くいくはずだが… 同じエラーだ…
またググってみたらpackage.json
に記載するのはReactの場合らしい。 NEXTJSの場合はまたproxyサーバーを用意しないといけないみたいだディレクトリーが下記のように変わる。
api //- api server
├── package.json
└── server.js
client //- NEXTJS project
├── server.js <-追加
|
...省略...
client用のサーバーは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にした。
"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を回してもると上手く表示がされるのが確認できた。