Vue.js、AWS Amplifyおよびboto3でサンプルアプリを作ってみる（第一回：Vue.jsセットアップ編）

フロントエンド初学者です。
Vue.jsの勉強のためにインストールからアプリ公開まで一通りやってみたので、手順とハマリどころをメモ。

## やりたいこと
- Vue.jsをフロントエンドにしたデータカタログアプリ（のサンプル）を作る
- せっかくなのでAWS Amplifyも使ってみる
- バックエンドはPython 3 + boto3※で作る
- Amazon API Gateway、AWS Lambda、AWS Glueでサーバーレスにやる（EC2やEC2的なものには最後まで触らないで済ませる）

※ AWSのPython用SDK。

## 完成品イメージ
<img width="1162" alt="スクリーンショット 2020-05-08 00.28.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/b5a68403-fa3d-5c57-7947-acfae55ac62c.png">

## 道具の選定
それぞれのパーツについて、使う道具を選んでいく。

- フロントエンド
  - とっつきやすそうという理由で**Vue.js**をチョイス。
  - UIパーツは**Element UI**。
- バックエンド
  - 多少土地鑑があるという理由で**Python**。2系は死んでしまったので3系で。
  - フロントエンドから直接AWSサービスを叩く2 Tierではなく、API GatewayとLambdaを挟んだ**3 Tier**で構成。色んな言語に手を出すと構文がごっちゃになりがちなので、ロジックはPythonとboto3に一本化する。
  - AWS Web公開四点セット（Route 53、CloufFront、S3、Certificate Manager）はあえて使わず、**AWS Amplify**に任せてみる。
  - AWS CICD四点セット（CodeCommit、CodeBuild、CodeDeploy、CodePipeline）も使わず、これもAmplifyで簡素化（厳密にはCodeCommitだけは使用）。
- 開発環境
  - Cloud9も考えたが、あえて手元のMacを汚す覚悟で以下に決定。 
     - MacOS Catalina
     - Visual Studio Code
     - Python 3.8
         - `alias`で`python`を`python3`にリンク
         - `pip`も同様に`pip3`にリンク
     - AWS Amplify

## Step by Step

### 1. 作業フォルダを作成してgit clone
一番最初にやること。
なおclone元はCodeCommitレポジトリ（以下はレポジトリ名を`my-amplify-app`とした例）。
実際にはレポジトリの作成やgit認証等諸々の前フリがあるが、本筋から外れるのでここでは省略。

```
% mkdir ~/SPA
% cd ~/SPA
% git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/my-amplify-app
```

### 2. Vue.jsのインストール
[公式](https://jp.vuejs.org/v2/guide/installation.html)を参考に、手元のMacにVue.jsとVue CLI 3（@vue/cli）をインストール。

```
% brew upgrade npm
% npm install -g @vue/cli
```

インストール手順やVue CLIの概念理解はこのあたりを参考にさせていただきました（感謝）。

https://qiita.com/y-tsutsu/items/67f71fc8430a199a3efd
https://qiita.com/Junpei_Takagi/items/603d44f7885bd6519de2
https://qiita.com/teraco/items/74a6104d3e201c4f654e

### 3. プロジェクトの作成
Vue.jsと@vue/cliをインストールできたらプロジェクト（`frontend`）を作成。最新のお作法に従って、`vue　init`ではなく`vue create`を使う。
vue routerもこの時にインストール（`npm install vue-router`で後からインストールもできる）。vuexは大規模開発用らしいのでスキップ。

```
% cd my-amplify-app
% vue create frontend
```

プロジェクトを作成したらプロジェクトフォルダ直下に移動。

```
% cd frontend
```

本来は以降ここで作業、となるはずだったが、Amplifyでやる前にCodeBuildでも一通りパイプラインを試してみようと思い立ち、結果ハマる。
詳細は省くが、CodeBuildで使用するビルド設定ファイル`buildspec.yml`がレポジトリ直下に`package.json`を要求したため、何をどうしてもビルドエラーに。。。最終的に、プロジェクトフォルダ配下の全ファイルをレポジトリ直下（`~/SPA/my-amplify-app/`）に移動することで無理矢理動かした。
他のやり方もあるかも知れないが、ここでこれ以上時間を使いたくなかったため、以後レポジトリ直下＝プロジェクトフォルダとすることに決定。

```
% mv ./* ../
% cd ..
% rmdir frontend
```

vue routerについては、以下も参考にさせていただきました（感謝）。

https://qiita.com/567000/items/d6a7c694a370dc92e774
https://qiita.com/hshota28/items/765cf903f055754f7557

### 4. Element UIのインストール
いい感じのUIを作れるようになるフレームワーク、[Element UI](https://element.eleme.io/#/en-US)をインストール。
`package.json`のあるプロジェクトフォルダ直下（ここではレポジトリ直下）で作業する。

```
% vue add element
```

基本デフォルトで、ロケールのみjaに変更する。
ちなみに、vue routerを手動インストールする場合は、Element UIより前にやっておいた方が無難。逆だと`App.vue`が上書きされてしまい都合が悪い。

### 5. 起動確認
`npm run serve` で起動確認。
万事うまく行っていれば、これでElement UIが有効になった状態で`http://localhost:8080`から開発用ページにアクセスできるはず。

```
% npm run serve
```

`npm run serve`はあくまで開発用なので、本番コードを生成するには`npm run build`によるコンパイルが必要とのこと。そこで生成されたJavascriptコードが`index.html`から呼び出されて動くわけだ。ふむふむ。
ということで、ついでにビルドの素振りもやっておく。この時点で何らかのエラーが出るようだと、CodeBuildかAmplifyかを問わずデプロイも失敗するので、やっておいて損はない。

```
% npm run build
```

### 6. ここまでのコミット
初期セットアップができたので、いったんコミットしておく。
一人作業なのでブランチは切らずにmasterへ。

```
git add .
git commit -m "Initialized"
git push -u origin master
```

### 7. vue routerとElement UIを構成し、画面遷移のベースを作成
vue routerとElement UIをインストールした時点で、`src/main.js`が修正されている。
これと、src周辺のフォルダ構造に一部手を加え、動くようにしていく。
最初に、完成品はこちら。

```javascript:src/main.js
import Vue from 'vue'
import App from './App.vue'

// vue router
import router from './router'

// Element UI
import './plugins/element.js'

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

```

まず、古いサイトではインポート元として`router.js`をポイントしていたりするが、現在（2020/5）は`router/index.js`なので`import router from ./router`とするのが正しい。うまく読み込めない場合は`src`からパスを確認すること。

vue routerを設定したら、あとは`components`なり`views`なりのフォルダを`src`配下に切って、ルート先の`XXX.vue`ファイル群を置いていく。これにより、`App.vue`をいわばホームディレクトリとして、様々なページをスムーズに遷移させることが可能になる。`router/index.js`は例えば以下のように書いていく。

```javascript:router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/components/Home.vue'
import Dataset from '@/components/Dataset.vue'

...（中略）...

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/dataset',
    name: 'Dataset',
    component: Dataset
  },

（後略）...
```

ちなみに各パスは相対パスで指定可能だが、`@`とするとsrcの代替とそこからの絶対パス指定もできる。以下は同値。

```
../src/components/Home.vue
@/components/Home.vue
```

あとは`App.vue`でElement UIを組み合わせながら各ルート先を表示するためのUIコンポーネントを作っていく。
ここでは`el-menu`を使っているが、他のElement UIコンポーネントも、使い方は難しくはない。[公式](https://element.eleme.io/#/en-US/component/quickstart)のサンプルコードを参考に、あれこれ試してみると理解できる。

```vuejs:App.vue
<template>
  <div id="app">
    <div>
    <img alt="Vue Logo" src="@/assets/gluelogo.png/" width="60" height="60">
      <h1>Data Catalogue Explorer</h1>
      <el-menu :default-active="activeIndex" mode="horizontal" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" router>
        <el-menu-item index="home" :route="{ name:'Home' }">ホーム</el-menu-item>
        <el-menu-item index="dataset" :route="{ name:'Dataset' }">データセットの一覧を見る</el-menu-item>

...（中略）...

      </el-menu>
      <router-view />
    </div>
  </div>
</template>

<script>

export default {
  name: 'app',
  data () {
    return {
      activeIndex: this.$route.name
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

```

このようにして、まずは画面構成を作っていく。適当なタイミングで動確（`npm run serve`）し、コミットしておくと効率がよい。

ある程度準備したら次はロジック作成とデプロイだが、長くなってきたので今回はここまで。

次回は、Amplifyをインストール・構成し、AWSのバックエンドリソースとCICDパイプラインを準備するところまで、その次ではaxiosをインストールしてAPI（API Gateway + Lambda）を呼び出し、Element UIのTableコンポーネントに投入して一応の完成を見るところまでをまとめたい。まとめられるといいな。