初心者でもアジャイルにVueとAPIGatewayでチャットアプリを作ってみる


普段はiOSをメインにspring bootやnodejsなど適当に手を出していて **Vue初めての私** でも **アジャイルに（５時間程度？）** VueとAWSのAPIGatewayのWebSocketでチャットアプリ作れましたので手順を残します。


最終的には下記のようなものを作成しました（認証機能をすっとばしましたので公開はしてないです。amplifyを使えばこの認証機能も一瞬でできそうですが。。また投稿者も名前でなく、connectionIdを表示してます :sweat_smile: 人を識別するにはこれでも十分かと。）

![chat.mov-x2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104256/b6c3bed1-a6c5-f805-ab8d-29d5da59e6d2.gif)

# 手順

## バックエンド

[awsの公式のサンプル](https://github.com/aws-samples/simple-websockets-chat-app)をForkし、[connectionIdや名前をbodyに付け加えられるようにほんの少しの修正](https://github.com/LittleWat/simple-websockets-chat-app/commit/7b1cc5b66789ddf3e73890b9965f1623d81cc6cd) だけしました。

CloudFormationを使っているので一瞬でデプロイできます。

使い方は下記記事がわかりやすかったです！
[APIGatewayでWebSocketが利用可能になったのでチャットAPIを構築してみた](https://qiita.com/G-awa/items/472bc1a9d46178f3d7a4)


## フロントエンド 

vueの知識はほぼ皆無ですが下記記事を読んでノリを知って作成しました。（巷には良記事が溢れててありがたい時代です。。）

[Vue.js を vue-cli を使ってシンプルにはじめてみる](https://qiita.com/567000/items/dde495d6a8ad1c25fa43)

[basic-vue-chat](https://www.npmjs.com/package/basic-vue-chat)を使用しました。

手順は

```
vue create basic-vue-chat-with-APIGateway
```

を行って[少々修正](https://github.com/LittleWat/simple-websockets-chat-app/commit/7b1cc5b66789ddf3e73890b9965f1623d81cc6cd)を行っただけです。

最終的なApp.Vueは下記になります。

```App.vue

<template>
  <div>
    <basicvuechat
      :title="'Sample Chat Vue App'"
      :initial-feed="messages"
      @newOwnMessage="onNewOwnMessage"
    />
  </div>
</template>

<script>
import Vue from "vue";
import basicvuechat from "basic-vue-chat";
Vue.use(basicvuechat);

// チャット履歴をためる変数
var feed = [];

let connection = new WebSocket(
  "wss://{YOUR-API-ID}.execute-api.{YOUR-REGION}.amazonaws.com/Prod" // ここを環境に合わせて修正する必要あり
);

// 接続した際のコールバック
connection.onopen = function() {
  // メッセージの送信
  // connection.send(`こんにちは世界`);
};

// エラーが出た場合
connection.onerror = function(error) {
  console.error(error);
};

// メッセージを受け取った場合
connection.onmessage = function(event) {
  const result = JSON.parse(event.data);
  console.log(`onmessage: ${JSON.stringify(event)}`);

  if (result.senderConnectionId == result.receiverConnectionId) {
    console.log("自分の送ったものが届いたよ");
    return;
  }

  var now = new Date();
  feed.push({
    author: result.senderConnectionId, // FIXME: result.name に置き換える
    imageUrl: "",
    contents: result.message,
    date: `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`,
  });
  console.log(`feed: ${feed}`);
};

export default {
  components: {
    basicvuechat,
  },
  data() {
    return {
      messages: feed, 
    };
  },
  methods: {
    onNewOwnMessage(message) {
      console.log(`message: ${message}, messageType: ${typeof message} `);
      connection.send(
        JSON.stringify({
          action: "sendmessage",
          data: {
            message: message,
            name: "マイケル", // FIXME: cogitoなどから名前を取得し設定する
          },
        })
      );
    },
  },
  created() {},
};
</script>

```


## 詰まったところ

JSON.parseやJSON.stringfyせずにエラーになった程度でしょうか。

## 公開するならやるべきこと

当然このままで公開できるはずもなく、下記のようなことを考慮せねばなりません。

- チャットルームの設定（現在は１ルームのみ）
- 認証
- 料金
- etc...


料金に関しては、AWSのAppSync(GraphQL)やFirebaseのCloudFireStoreで行うものと、WebSocketでやるものはどちらがお安いのですかね。
さすがにチャットの履歴をデータベースに保存する分前者がお高いでしょうが、もし履歴を１日程度しか保持しない場合など意外と前者がお安かったりするのですかね :thinking: 。

# まとめ

VueやReactなど最近のフレームワーク使うと、レゴブロックを組み立てるかのように簡単にwebアプリが作れますね。凄い時代です。
部品を作る力というより部品組み立てる力の方が必要そうでしょうか。
（とはいえ部品の仕組みも知らないと細かい調整ができなかったり、ハマった時に抜け出せなくなりそうなので部品の知識も当然必要とは思いますが...）