Vue.js入門ハンズオン 〜環境構築からS3静的ホスティングで世の中に公開するまで〜

 この記事は、 Vue.js #1 Advent Calendar 2017 - Qiita の1日目です。

 最近(1ヶ月前くらいから)Vue.js を使い始めた初心者です。同じように Vue.js を始める人の少しでも参考になれば、ということで「ことはじめ」的なメモを残しておこうと思います。

 手元の環境でも同じことができるハンズオン形式の記事にしたつもりです。ただ、無意識的に省略してしまっている部分があるかもしれませんので、不明点がございましたら遠慮なくご連絡ください!また、「こうすべき!」という Vue.js プロの方々からのコメントもお待ちしております!

この記事を読むとできるようになること

 この記事では(超)簡単なランディングページを作ることで、Vue.js の基本のキを学びます。具体的には下記の流れになります。

  • 環境セットアップ
  • 新しいコンポーネントの追加
  • 入力値バリデーションの実装
  • Vue.js プロジェクトに Bootstrap を導入する
  • AWS の S3 に静的ホスティングする

将来的に Vue.js と AWS のサーバレス周りのサービスを使って、Webサービスを展開していきたいと考えているため、自分の学習も兼ねてこのような内容にしました。本当は、API GW + Lambda + DynamoDB + SES の構成で、LPサイトに登録してくれた人の保存とメール配信まで作り込もうと思ったのですが、非常に長くなりそうなのでまずはフロント部分までをまとめたいと思います。

環境セットアップ

 まずは、ローカル環境を整えていきます。今回は、Vue CLI と Webpack を用いました。まず、Vue CLI をインストールします。

$ cd (作業ディレクトリ)

$ npm install -g vue-cli

これで vue コマンドが使えるようになりました。

 続いて、サンプルプロジェクト sample を作っていきます。対話形式でプロジェクトの設定をしていきますが、基本的には全てデフォルトで構いません。Enter を押し続けてください。

$ vue init webpack sample

? Project name sample
? Project description first Vue.js project
? Author ketancho
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Setup unit tests Yes
? Pick a test runner karma
? Setup e2e tests with Nightwatch? Yes

サンプルプロジェクトが完成しました。最後に、サービスを立ち上げます。

$ cd sample
$ npm install

# localhost:8080 でサーバを起動する
$ npm run dev

ブラウザで http://localhost:8080/#/ を叩くと、下記のような画面が表示されます。

f:id:ketancho_jp:20171126124150p:plain

 以上がローカル環境構築になります。うまくいきましたでしょうか?ソースコードを修正すると、自動的に修正が反映されます。また、修正が誤っている場合は、 npm run dev したコンソールにエラーメッセージが表示されるので、メッセージを参考に修正してあげてください。

Vue.js のルーティング機能を利用し、新しいページを追加する

 続いて、独自の画面を作っていきます。現在、ルート / にアクセスした場合にしか画面が表示されません。そこで、 /lp にアクセスされた場合に(超簡単な)ランディングページを表示するようにしたいと思います。そのためには、下記のような流れで作業を進めます。

  • コンポーネントの作成
  • ルーティングの設定変更

ルーティング定義はどこで行うか?

 ルーティングは ./sample/src/router/index.js というファイルで、下記のように定義されています。

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})

 では、新しいコンポーネントを追加していきます。ここでは「 /lp にアクセスされたときにLPページを表示する」という場合を例に挙げてみます。

コンポーネントの作成

 まず、新しいコンポーネント用のファイル LP.vue を作成します。

<template>
  <div class="lp">
    こちらはLPページです。
    情報をお求めの方は、下記よりメールアドレスをご登録ください。
    <div>
      メールアドレス:<input placeholder="email@email.com">
      <input type="submit" value="登録">
    </div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        'email': ''
      }
    }
  }
</script>

 続いて、ルーティングの設定を行います。先ほどの ./sample/src/router/index.jsを修正します。

新しいコンポーネントファイルの import

import LP from '@/components/LP' を追加しました。

routes 以下にルーティングの設定を記載

/lp のパス情報を追加します。

    {
      path: '/lp',
      name: 'LP',
      component: LP
    }

最終的に下記のようなコードになりました。

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import LP from '@/components/LP'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/lp',
      name: 'LP',
      component: LP
    }
  ]
})

http://localhost:8080/#/lp にアクセスすると、簡素ではありますがLPページが表示されるかと思います。

入力値バリデーションの実装

 続いて入力値に誤りがある場合は、その旨を伝える機能を実装してみます。先ほどのLPコンポーネントを修正していきます。

バリデーションメッセージの追加

 v-show を使うことで、条件を満たす場合のみ、HTML要素を表示することができます。メールアドレスの下に

<span v-show="!validation.email">メールアドレスの形式が不正です</span>

のような形で、エラーメッセージを追加してください。( validation.email は後ほど実装します。)

バリデーション条件の実装

 では、本題のバリデーションを実装していきます。まず、 input タグの中での入力値をバインドできるようにします。コンポーネントの変数として、 email を下記のような形で定義してください。

  data () {
    return {
      'email': ''
    }
  }

続いて、input タグ側にも修正を加えます。 v-model="email" を追加します。

<input v-model="email" placeholder="email@email.com">

以上で、入力値がバインドされるようになりました。最後に、入力値の検査ロジックを追加します。

  computed: {
    validation () {
      return {
        email: this.email === '' || /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(this.email)
      }
    }
  }

値が空、あるいは、メールアドレスとして正しい入力値である場合のみ true を返します。全体的には、下記のようになりました。

<template>
  <div class="lp">
    こちらはLPページです。
    情報をお求めの方は、下記よりメールアドレスをご登録ください。
    <div>
      メールアドレス:<input v-model="email" placeholder="email@email.com">
      <input type="submit" value="登録">
    </div>
    <div>
      <span v-show="!validation.email">メールアドレスの形式が不正です</span>
    </div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        'email': ''
      }
    },
    computed: {
      validation () {
        return {
          email: this.email === '' || /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(this.email)
        }
      }
    }
  }
</script>

Vue.js プロジェクトに Bootstrap を導入してみる

 上のエラーメッセージでは見栄えが悪いので、Bootstrap を導入してみます。

Bootstrap の導入

まず、 npm コマンドで、Bootstrap を導入します。

$ npm i bootstrap-vue bootstrap@4.0.0-beta.2

 続いて、Vue プロジェクトの中で、Bootstrap を使う宣言をします。 main.js

import BootstrapVue from 'bootstrap-vue'

を追加し、全体としては下記のようにします。

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import BootstrapVue from 'bootstrap-vue'

import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.config.productionTip = false
Vue.use(BootstrapVue)

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})

エラーメッセージを変更する

 では、Bootstrap を使う準備ができたので、デザインを変更していきます。先ほど、

<span v-show="!validation.email">メールアドレスの形式が不正です</span>

としていた部分を、

<span class="errors" v-show="!validation.email">
  <b-alert show variant="danger">メールアドレスの形式が不正です</b-alert>
</span>

のように変更します。見た目が下記のように変わりました。

f:id:ketancho_jp:20171130223324p:plain

少し上の方が空いてしまっていますが、お許しください。

S3へのホスティング

 では、最後にここまで構築してきた Vue プロジェクトを AWS の S3 にホスティングしていきます。

  • Vue.js プロジェクトをビルド
  • S3 バケットの作成および設定
  • S3 へのデプロイ

という流れになります。

Vue.js プロジェクトをビルド

 まず、 npm run build コマンドで Vue プロジェクトをビルドします。すると、 dist というディレクトリ以下にモジュールが生成されます。 dist 以下は下記のようになっており、

$ ls dist
index.html  static

この index.html と static ディレクトリを S3 バケットに入れることで、静的サイトをホスティングすることができます。

S3 バケットの作成および設定

 S3側の設定をしていきます。まずは、バケットを作成します。ここでは、 ketancho-vue-sample というバケットを作成しました。

f:id:ketancho_jp:20171127063329p:plain

 次に、静的ホスティングの設定を行います。作成したバケットの「プロパティ」タブを選択します。

f:id:ketancho_jp:20171127063537p:plain

Static website hosting を選択し、下記のように設定します。

f:id:ketancho_jp:20171127063409p:plain

続いて、バケットポリシーを設定します。

f:id:ketancho_jp:20171127063825p:plain

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::(バケット名)/*"
            ]
        }
    ]
}

S3 へのデプロイ

aws cli を用いて dist ディレクトリを S3 にデプロイします。

aws s3 cp dist/ s3://ketancho-vue-sample --recursive

接続確認

以上で設定完了です。 http://(バケット名).s3-website-ap-northeast-1.amazonaws.com/#/lp にアクセスすると先ほど作成したLPページが見えるのが分かると思います。

まとめと今後

 Vue.js の勉強を通じて得た知識をまとめました。Vue.js に詳しい方でも、S3の静的ホスティングを使ったことがない方が多いと思いますので、少しは新しい知見に繋がれば幸いです。

参考にさせて頂いた外部サイト

  • S3 へのホスティング部分を参考にさせていただきました

https://medium.com/@connorleech/host-a-vue-js-website-on-amazon-s3-for-the-best-hosting-solution-ever-%EF%B8%8F-eee2a28b2506

追記)2018/5/8 に関連記事を書きました :-)

 Vue.js で構築したサイトを S3 に静的ホスティングした上で、Route 53 でドメイン設定して公開するまでの手順についてまとめました。こちらもあわせてご参照いただければと思います。

www.ketancho.net