Vue+fastifyで外部APIを叩いてみた

# はじめに

Vue.jsでフロントを作るとき、よく **サーバー経由で外部API叩きたい** ってことがあり、今回その実装方法を試してみたのでそのメモです。
Vueとよく一緒に使われるフレームワークとしてexpressがありますが、今回はexpressではなく**fastify**を使ってみました！

そして外部APIとしてkintoneに対してAPIを叩いています。

# fastify とは

後発のNode.jsフレームワークでまだドキュメントやリファレンスは少ないけど、```async/await``` にデフォルトで対応していたり、expressよりパフォーマンスが高かったり結構良さげらしい。
フレームワークの比較については、以下のサイトが参考になります。**express / koa / fastify** について細かく記載されていてわかりやすかったです。

> ▼ Node.jsフレームワークを比較して見えたそれぞれの特徴
> https://www.wantedly.com/companies/company_3239475/post_articles/179467

# 作ったもの

こんな動きをするものです。kintoneのデータがVue上（Web上）で確認できればOKです。あとは好きなようにテーブル表示したりリスト表示したり。
![vue_fastify_kintone.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/749c707e-5037-20cd-2aa5-43e6e5c39c22.gif)

構成はこんな感じです。
そもそもクロスドメイン制約によりWebから直接APIが叩けないので、サーバー側を用意しないといけないです。
<img src="https://docs.google.com/drawings/d/e/2PACX-1vQt2lWmqHN7nakiVSqRbhPQSCbfFKcFdXxVHtv6eY6tGV7k411uyEBqUbbhD7Puvi47qv3M3tUfgMGF/pub?w=800">

# 手順

ざっくり流れを箇条書きで書くとこうなります。

- vue-cliのインストール
- 作業ディレクトリの作成
- Vue側の設定
    - axiosのインストール
    - HelloWorld.vueの修正
    - 実行
- fastify側の設定
    - ツールのインストール
    - index.jsの作成
    - 実行
- 動作チェック

# 全体準備

ではさっそく。まずはvue-cliのインストールからやります。

```bash
$ npm i -g @vue/cli
```

※ すでにグローバルで入っていればインストールは必要ありません。

作業ディレクトリを作って移動します。

```bash
$ mkdir my_project; cd my_project
```

ちなみに、これから作成するディレクトリ構成はこんな感じになります。

```
my_project/
  ├ front/ #フロントエンド用
  └ back/ #バックエンド用

※ node_modules関連は書いてませんがそれぞれ存在します。
```

# Vue側（フロントエンド側）の設定

```bash
$ vue create front
```

vueの雛形が生成されます。今回はVueからfastifyに対してのリクエストにaxiosを使うのでそれもインストールします。

```bash
$ cd front
$ npm i --save axios
```

```src > components > HelloWorld.vue``` を修正します。

```vue:HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <button @click="post">データ取得</button>
    <p>{{ kin }}</p>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  name: 'HelloWorld',
  data() {
    return {
      kin: ''
    }
  },
  props: {
    msg: String,
  },
  methods: {
    async post() {
      const kintoneData = await axios.post('http://localhost:3000/getData', {app: 836, id: 20});
      this.kin = kintoneData;
      console.log(kintoneData);
    }
  }
}
</script>
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
```

せっかくなのでVueからfastifyへオブジェクトを渡してそれをパラメータにAPIを叩くようにしてみました。
テンプレそのまま利用しているのであれですが、変更している点としては、

- HTMLのいらない部分を削除
- HTMLにボタン配置
- axiosのインポート
- ボタンとメソッドの紐付け

とかです。
※ 本当はapi.jsとか別途作ってコンポーネント化するべきだと思いますが、今回はシンプルに。

## フロントエンドの実行

修正ができたら、 ```ｎpm run serve``` で実行します。多分 **http://localhost:8080** でアクセスできると思います。

# fastify側（バックエンド側）の設定

必要なツールのインストールをします。

```bash
$ mkdir back; cd back
$ npm init
$ npm i --save fastify fastify-cors nodemon

# kintoneのSDK
$ npm i @kintone/rest-api-client
```

- **fastify**: Node.js フレームワーク
- **fastify-cors**: fastifyをCORS対応させるためのもの
- **nodemon**: ファイルを監視して変更があったらスクリプトを再実行してくれるやつ。便利。
- **@kintone/rest-api-client**: kitnoneのAPIを叩きやすくするツール。kintone使わないなら必要ないです。

バックエンドで実行させるJSファイルを作ります。

```bash
$ touch index.js
```

中身はこんな感じ。3000ポートを使ってます。

```javascript:index.js
const fastify = require('fastify')();
fastify.register(require('fastify-cors'));

fastify.post('/getData', async (request, reply) => {
  // ここに外部APIへのリクエストを書く
  
  // 引数のreplyを使ってWeb側へデータを渡す
  reply.send({message: 'Hello World!'});
});

fastify.listen(3000);
```

kintoneへデータ取得のAPIを叩く処理を書くとこんな感じ。

```javascript:index.js
// kintoneの設定
const {KintoneRestAPIClient} = require('@kintone/rest-api-client');
const client = new KintoneRestAPIClient({
  baseUrl: 'https://｛subdomain｝.cybozu.com',
  auth: {
    apiToken: '{api_token}'
  }
});

const fastify = require('fastify')();
fastify.register(require('fastify-cors'));

fastify.post('/getData', async (request, reply) => {
  // requestでVue側からオブジェクトを受け取る
  const data = await client.record.getRecord({app: request.body.app, id: request.body.id});
  console.log(data);
  reply.send({message: JSON.stringify(data)});
});

fastify.listen(3000);
```

```npm start```でnodemonを使ってindex.jsが動くように、package.jsonを修正します。

```json:package.json
~~
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "./node_modules/nodemon/bin/nodemon.js index.js"
  },
~~
```

## バックエンドの実行

```npm start``` すれば、3000ポートで待機されます。
nodemonを使うことで、index.jsを修正すると自動で ```npm start``` が再度走るのでとても楽です。

## fastify側（バックエンド側）だけでの動作チェック

fastifyのメソッドを **get** に変更すれば、ブラウザ上で簡単に動作チェックもできます。

```javascript:index.js
const fastify = require('fastify')();
fastify.register(require('fastify-cors'));

fastify.get('/test', async (request, reply) => {
  // ここに外部APIへのリクエストを書く

  // 引数のreplyを使ってWeb側へデータを渡す
  reply.send({message: 'Hello World!'});
});

fastify.listen(3000);
```

```npm start``` して、 **http://localhost:3000/test** にアクセスして、 ```reply.send()```の内容が表示されていればOKです。
※ ```/test```部分はコード内で指定しているものに適宜変更してください。
<img src="https://docs.google.com/drawings/d/e/2PACX-1vR6lPMeK23oTxG4gvHB5o38S_vj0TTZse7CZs4MaUSaZr2DO5m8rxAIERlrUm_CS22ixoIEEUu9H_8A/pub?w=800">


# さいごに

雰囲気はexpressと変わらないですね。やはりasync/awaitがデフォルトで使えるのが強い。
パフォーマンスについてはそこまですごいもの作らないから正直わからないです(´-ω-`)

今回はｌocalhostで作成していたので、ngrokとか使ってhttps通信できるようにもしてみたい。Webhookとか受け取ってみたい。
実装できたらまた記事化します。

それでは！≧(+･` ཀ･´)≦

## 余談

express の解説記事を探している中で、不覚にも以下のサイト内の画像につい笑ってしまった
https://techacademy.jp/magazine/16119

> **田島さん、めっちゃスルーするやん！！**

<img width="847" alt="スクリーンショット 2020-06-14 23.17.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153051/60197664-9060-6a13-86ab-d0b6a511dcaa.png">