バックエンド
EC2インスタンス上でexpressを動かし、アプリケーションのbackend環境を構築する。
ここでは例としてアプリケーションapp
を作る
環境構築
AMI:Ubuntu18.04、IP:x.x.x.x の場合
$ sudo apt-get update
$ sudo apt-get install nodejs
$ sudo apt-get install npm
$ sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10
$ sudo npm install -g express
$ sudo npm install -g express-generator
$ express --view=pug app
$ cd app
$ npm install
$ npm start
> app@0.0.0 start /home/ubuntu/app
> node ./bin/www
AMI:AmazonLinux2、IP:x.x.x.x の場合
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
$ . ~/.nvm/nvm.sh
$ nvm install node
$ sudo npm install -g express
$ sudo npm install -g express-generator
$ express --view=pug app
$ cd app
$ npm install
$ npm start
> app@0.0.0 start /home/ubuntu/app
> node ./bin/www
app/bin/wwwファイルでポート番号を指定できる。デフォルトではポート3000なので、ブラウザからアクセスして確認できる。
APIの作成
app下にindex.js
を作成し、以下を記述。
// expressモジュールを読み込む
const express = require('express');
// expressアプリを生成する
const app = express();
// ルート(http://x.x.x.x:3000/)にアクセスしてきたときに「Hello」を返す
app.get('/', (req, res) => res.send('Hello'));
// ポート3000でサーバを立てる
app.listen(3000, () => console.log('Listening on port 3000'));
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// urlencodedとjsonは別々に初期化する
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.post('/', function(req, res) {
console.log(req.body);
res.send('POST request to the homepage');
})
// ポート3000でサーバを立てる
app.listen(3000, () => console.log('Listening on port 3000'));
$ node index.js # 実行
Listening on port 3000
POSTメソッドでは、body-parser
モジュールを用いてJSONで取得する。
テスト
APIを叩く。
ブラウザから(GET)
x.x.x.x:3000/
にアクセス。
コンソールから(POST)
$ curl -X POST http://x.x.x.x:3000/ -H "Accept: application/json" -H "Content-type: application/json" -d '{ "name" : "tanaka" }'
フロントエンド
環境構築
vueの環境構築はこちらの記事で書いた通りなので省略。
フロントエンドから外部APIを叩く
デフォルトのAboutページにボタンをつくり、押したら非同期で外部API(httpbin)を叩くようにしてみる。
必要なものをいれる。
$ npm install axios vue-axios
import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import axios from 'axios' //追記
import VueAxios from 'vue-axios' //追記
Vue.config.productionTip = false
Vue.use(VueAxios, axios) //追記
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
<template>
<div class="about">
<h1>This is an about page</h1>
<button @click="clicked" >Call API</button>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Emit } from 'vue-property-decorator';
@Component
export default class About extends Vue {
private clicked():void {
this.axios.get('https://httpbin.org/get')
.then((response) => {
console.log(response);
})
.catch((e) => {
console.log(e);
});
}
}
</script>
consoleにデータが来てれば成功。
フロントエンドからexpressの内部APIを叩く
上のコードのURLをそのままhttp://x.x.x.x:3000
とすると以下のCORSのエラーが出る。
Access to XMLHttpRequest at
http://x.x.x.x:3000/
from originhttp://x.x.x.x:8080
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CORS(Cross-Origin Resource Sharing)とは何か?
あるオリジンで動いている Web アプリケーションに対して、別のオリジンのサーバーへのアクセスをオリジン間 HTTP リクエストによって許可できる仕組み
引用) https://qiita.com/att55/items/2154a8aad8bf1409db2b
どうしたらいいか
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// CORSを許可する
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
// OPTIONSでメソッドがバレないようにする。 (?)
if ('OPTIONS' === req.method) {
res.send(200)
} else {
next()
}
});
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
// POST
app.post('/', function(req, res) {
console.log(req.body);
res.send('Hello');
})
// GET
app.get('/', (req, res) => res.send('Hello'));
app.listen(3000, () => console.log('Listening on port 3000'));
上記のコードにしてフロントとバックを起動後、GETでコールしてみる。
$ cd app
$ node index.js #バックエンド起動
$ cd front
$ npm run serve #フロントエンド起動
コンソールに以下が得られたら成功。
{data: "Hello", status: 200, statusText: "OK", headers: {…}, config: {…}, …}
Appendix
EC2インスタンスに置いたvueファイルを更新するのにいちいちscp
とかvi
とかしてるのはだるすぎるのでVSCodeから直接SSHでいじるための方法。
VSCode拡張機能であるremote development
を入れるて以下に設定ファイルを書いておく。
Host 任意の接続名 //configには何個も接続先とキーとかの情報を書けるのでそれらを区別する名前。
HostName x.x.x.x
User ec2-user
Port 22
IdentityFile /Users/xxx/.ssh/hoge.pem
参考
- Amazon Linux2 への nvm と npm のインストール
https://qrunch.net/@dr3mms/entries/66FDqVNl3CoNvvCH - Node.jsとExpressでWeb APIを作ってみよう
https://sbfl.net/blog/2018/08/25/nodejs-express-webapi/ - Ubuntu でapt を使用してNode.js をインストールする3 つの方法(Ubuntu 15.04, Ubuntu 14.04.2 LTS)
https://qiita.com/TsutomuNakamura/items/7a8362efefde6bc3c68b - NodeJSでWebアプリケーション開発 – Express編
https://avinton.com/en/academy-2/webapp-with-node-express/ - node.js + expressでPOSTを受け取る & POSTパラメータをJSONで取得する
https://qiita.com/ktanaka117/items/596febd96a63ae1431f8 - vue-cliでaxiosを使用する(設定から使用方法まで)
https://qiita.com/right1121/items/092ac7ff747e1c47b2b1 - なんとなく CORS がわかる...はもう終わりにする。
https://qiita.com/att55/items/2154a8aad8bf1409db2b - express.jsのcors対応
https://qiita.com/chenglin/items/5e563e50d1c32dadf4c3 - expressにてCORSを許可する
https://qiita.com/tomoya_ozawa/items/feca4ffc6217d585b037