今回は簡単なバックエンドアプリケーションを開発します。
※今回の内容は NodeJSでWebアプリケーション開発 – React編の続きです。そちらを見ていない方は先にご確認ください。
環境
前回と同様です。
Expressアプリケーションの立ち上げ
ExpressはNodeJSでサーバーサイド(バックエンド)アプリケーションを開発する際に用いるフレームワークです。
Expressのアプリケーションジェネレーターを用いて簡単にアプリの雛形を立ち上げることができます。
以下のコマンドを実行してジェネレーターをインストールしましょう。
1 |
npx express-generator |
以下のコマンドでジェネレーターのオプションが確認できます。
1 |
express -h |
実際にアプリ を作成しましょう。
1 |
express --view=pug academy-express-app |
必要なモジュールをインストールします。
1 2 3 |
cd academy-express-app npm insatall |
デフォルトではポート3000で起動するようになっているので
1 |
academy-express-app/bin/www |
のポート3000を指定している箇所を8000に書き換えましょう。
書き換えが完了したらアプリケーションを起動します。
1 |
DEBUG=academy-express-app:* npm start |
ブラウザでlocalhost:8000にアクセスして以下のように表示されれば成功です。
もう少しこの雛形を触ってみましょう。
localhost:8000の後ろに’/users’とつけて再度アクセスしてみましょう。
すると以下のように表示されます。
これは
1 |
academy-express-app/routes/users.js |
の内容を
1 |
academy-express-app/routes/app.js |
内の
1 2 3 4 5 6 |
var usersRouter = require('./routes/users'); . . . app.use('/users', usersRouter); |
でエンドポイント(スラッシュ以下,今回は”localhost:8000/users”の’/users’)に追加しています。
エンドポイントの追加
新しくエンドポイントを追加してみましょう。
academy-express-app/routes/以下にhelloworld.jsを作成し以下の内容をコピーアンドペーストしてください。
1 2 3 4 5 6 7 8 |
var express = require('express'); var router = express.Router(); router.get('/', function(req, res, next) { res.send('Hello World!'); }); module.exports = router; |
そしてapp.jsに以下の二行を追加してください。
1 2 3 4 5 6 |
var helloworldRouter = require('./routes/helloworld'); . . . app.use('/helloworld', helloworldRouter); |
アプリを再起動し’localhost:8000/helloworld’にアクセスしましょう。
画面にHello World!と表示されていれば成功です。
これは何をしているかというと、ブラウザからサーバーに対してhttpリクエスト(GETリクエスト)を飛ばし、サーバーから返ってきたレスポンスが画面に表示されています。
レスポンスは一般的にJSON形式(REST-APIの場合)で返ってきます。それ以外にもHTML形式などがあり、アプリケーションの種類によって異なります。
データの読み込み、レスポンス
バックエンドの役割のうちもっとも大きいものの一つは、フロントエンドで表示する情報をDB等から読み取り、扱いやすい形でフロントエンドに渡すことです。
しかし今回は簡単のためCSVファイルから情報を読み取りレスポンスとして返します。
CSVの扱い
まず必要なモジュールをインストールします。
1 |
npm install csv-parser |
academy-express-app以下にdataディレクトリを作成し、そこにload_csv.jsを作成し、以下の内容をコピーしてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
const fs = require('fs'); const csv = require('csv-parser'); function lead_csv(inputFilePath) { var csv_data = [] var count = 0 return new Promise((resolve, reject)=> { fs.createReadStream(inputFilePath) .pipe(csv()) .on('data', function(data){ try { //perform the operation count ++ csv_data.push(data) } catch(err) { //error handler reject(err) } }) .on('end',function(){ //some final operation resolve(csv_data) }); }) } module.exports = lead_csv; |
そしてdataディレクトリにこちらからダウンロードしたCSVファイルを配置してください。
ルートの追加
routeディレクトリにresult.jsを作成して以下の内容をコピーしてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var express = require('express'); var router = express.Router(); var load_csv = require('../db/load_csv.js') var inputFilePath = './data/jukenresult.csv' /* GET home page. */ router.get('/', function(req, res, next) { load_csv(inputFilePath) .then(function(data){ res.send(data) }) }); module.exports = router; |
そして先ほどのuses, helloworld同様app.jsでresult.jsからルーターをインポートして/resultをエンドポイントに追加しましょう
localhost:8000/resultにアクセスすると以下のようになります。(CSVファイルの内容をJSON形式で返しています。)
Reactアプリケーションの立ち上げ
1 2 3 4 5 |
# academy-express-appがある階層で実行してください。 sudo npm install -g create-react-app create-react-app academy-react-app2 cd academy-react-app2 npm start |
下の画面が表示されれば成功です。
コンポーネントライブラリ
今回もMaterial-UIを使用します。前回同様以下のコマンドでインストールします。
1 2 3 |
npm install @material-ui/core npm install @material-ui/styles |
HTTPリクエストライブラリ
通常のWebアプリケーションにはフロントエンドとバックエンドで通信をする必要があるため、HTTP通信のためのモジュールが必須です。
今回はaxiosというライブラリを使用します。
1 2 |
npm install axios |
雛形の作成
App.jsの中身を以下のように書き換えてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
import React, { useState, useEffect } from 'react'; import './App.css'; import { Paper, Typography, Table, TableBody, TableCell, TableHead, TableRow } from '@material-ui/core' import axios from 'axios'; const apiURL = 'http://localhost:8000' function App() { const [data, setData] = useState([""]) const getData = () => { axios.get(apiURL+'/result') .then(res => setData(res.data)) } useEffect(()=> getData(), []) return ( <div className="App"> <Paper > <br/> <Table> <TableHead> <TableRow> {Object.keys(data[0]).map(key => { return( <TableCell align='right'>{`${key}`}</TableCell> ) })} </TableRow> </TableHead> <TableBody> { //取得したデータの繰り返し処理 data.map( row => { return ( //データの各行内でのオブジェクトのキーごとに繰り返し処理 <TableRow> {Object.keys(row).map(key => { return( //レンダリング <TableCell> {`{row[key]}`} </TableCell> ) })} </TableRow> ) }) } </TableBody> </Table> <br/> </Paper> </div> ); } export default App; |
以下のような画面になれば準備完了です。
もしこの時にCORSに関するエラーが出ている場合はバックエンド側でオリジン間のリソース共有を許可する必要があります。
詳しくはこちらを参照ください。
Expressでこの設置を行うには以下のリンクの内容のように行います。
https://expressjs.com/en/resources/middleware/cors.html
アクテビティ
1、全件のデータを返していますが最初の100件のみ返すようにresult.jsを編集しましょう。
参考:
https://www.w3schools.com/jsref/jsref_slice_array.asp
2、ページ上部にボタンを二つ追加し、表示するデータを変更できるようにしましょう。
(Getリクエストを送る際にlocalhost:8000/resultの後ろに?page=2を付けることでバックエンドに表示したいデータの情報を送ることができます。)
参考:
https://en.wikipedia.org/wiki/Query_string
https://github.com/axios/axios
http://expressjs.com/en/api.html#req.query
3、ページ上部にドロップダウンを置き、Pass or Notの欄にフィルターをかけれるようにしましょう。(フィルター無し、合格のみ、不合格のみ)
参考:
https://material-ui.com/components/selects/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
配置をキレイにしたい場合はGridが便利です。
https://material-ui.com/components/grid/#grid
下のような動作をすればこのアクテビティは完了です。