アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

Nuxt.jsのSPAをAmplify Consoleでホストする。めっちゃ簡単だった!

morishitaです。

以前、次のエントリを書きました。

tech.actindi.net

このとき作ったNuxt.jsのアプリケーションはその後、 リニューアルして2019年4月からはいこーよ!こどもBIRTHDAYとして利用しています。

birthday.iko-yo.net

今後は対象地域と施設を増やして拡充していく予定です。
それに伴い開発が活発になるのでステージング環境や 施設の方に予め確認いただくプレビュー環境もちゃんと準備する必要が出てきました。

上記エントリで紹介した環境を拡張しても良かったのですが、 せっかくなので東京リージョンでも使えるようになったAWS Amplify Consoleを使ってみました。

aws.amazon.com

Amplify Consoleとは

AWSが開発しているAmplifyというフレームワークがあります。
ReactやAngular、Vue.jsのアプリケーションをフロントエンドとして、 AppSync、DynamoDB、Cognitoなどのバックエンドの構築までをCLIで行えます。
フルスタックのサーバレスアプリケーションの構築から継続的なデプロイまでできてしまう超便利ツールです。

Amplifyフレームワークでは大量に設定やAppSyncのスキーマ定義のファイルが生成されます。
一部の生成ファイルは一緒に生成される.gitignoreでリポジトリに入れないように設定されます。
複数人で開発するとなるとリポジトリに入らないファイルを個別に持つのも良くないので Amplify CLIを実行する環境、生成されるファイル群を管理する仕組みを作る必要があります。
それがちょっと面倒だなぁと思っていました。

Amplify Consoleはそんな面倒を解決してくれるサービスです。
GithubなどのリポジトリにPushすると連携して、ビルド、デプロイしてくれます。
デプロイに利用するサーバ等を直接管理することのないフルマネージドのサーバレスサービスで次の機能をしてくれます。

  • 複数のブランチでそれぞれ別個にビルド、デプロイが可能
  • カスタムドメインで運用でき、サブドメインもつけ放題
  • ブランチごとにBASIC認証をかけられる
  • Amplifyフレームワークのアプリケーションならばバックエンドも構築できる
  • フロントエンドはCDNを利用して配信してくれる

プロトタイピング程度なら便利で使えるなぁという印象だったAmplifyをプロダクションでも使ってみようかなと思わせる、Amplify Consoleはそんなサービスです。

Amplify Consoleでアプリを作ってみる

いこーよ!こどもBIRTHDAYのアプリケーションの構成は次のとおりです。

  • Nuxt 2.8.1 + @nuxt/typescript
    • mode: 'spa'の静的サイト
  • Typescript 2.8.0

これをビルド・デプロイするまで流れを説明します。

アプリを設定する

最初にリポジトリと接続します。
リポジトリサービスを選択すると、OAuthの認証を促されるので従います。

f:id:HeRo:20190610110648p:plain

リポジトリとブランチが選択できるようになるので選びます。

f:id:HeRo:20190610110707p:plain

アプリ名をつけて、ビルド設定を行います。
React、Angular、Vue.jsなどは自動で認識してビルド設定を自動で作ってくれます。
ソースにGulpfileを含んでいたのでそれを使うと判定されたようです。

f:id:HeRo:20190610110725p:plain

独自にビルド処理を定義するならば、リポジトリにAmplify.ymlを作成します。

前述のGulpfileはビルド成果物のS3へのコピーなどといったデプロイ処理を行っています。それはAmplify Consoleに任せるので、次の処理だけするように変更したAmplify.ymlを用意しました。

  • yarn install
  • yarn run build
  • スラックへの通知(scripts/notify-deploy-to-slack.js

実際のAmplify.ymlは次のとおりです。

version: 0.1
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands:
        - yarn run build
    postBuild:
      commands:
        - node scripts/notify-deploy-to-slack.js
  artifacts:
    baseDirectory: dist/
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*

上記ファイルを追加して、再度アプリを作成しようとすると次のようにAmplify.ymlが認識されます。
環境変数API_URL_BROWSER1も設定します。
環境変数はアプリの作成のときでなくてもあとでいつでも追加できます。
特定のブランチでのみ値を変更することも可能です。

f:id:HeRo:20190610110750p:plain

最後に設定内容を確認します。

f:id:HeRo:20190610110808p:plain

すると処理が開始されます。

f:id:HeRo:20190610110826p:plain

しばらく待つと、処理が完了します。

f:id:HeRo:20190610110845p:plain

スクリーンキャプチャの下のリンクからデプロイしたアプリケーションにアクセスできます。
今後、対象ブランチはリポジトリにPushするたびにビルド・デプロイされます。

以上でSPAを継続的にビルドしデプロイする環境ができました。
簡単ですね。

リダイレクト設定

実はここまでの設定ではクライアント側でリクエストパスのルーティングを行うSPAの場合にはちゃんと動かないと思います。
ドメインルートからの遷移では問題ないのですが、それ以外のパスへダイレクトアクセスされると実体のファイルがないので Not Found になります。

これを解決するためにリダイレクト設定を行います。
左ペインの「書き換えて、リダイレクト」というを選択します(機械翻訳でしょうか?変な日本語ですね)。

デフォルトでは次の画像のように設定されています。

f:id:HeRo:20190610110908p:plain

編集・追加はWebフォームでできるようになっています。

f:id:HeRo:20190610110924p:plain

「テキストエディタで開く」と次のようなダイアログ中にJSONで設定が表示されます。この中で編集できます。

f:id:HeRo:20190610110940p:plain

ただ、いまいち使いづらいので、別のところで書いた設定をコピー&ペーストするほうがいいと思います。

Nuxt.jsのSPAではどう設定すればいいか?

クライアントでルーティングを行うSPAではどのパスへのアクセスもアプリケーションのエントリポイントとなるHTMLファイルを返す必要があります。
一方、CSSその他のファイルはそのまま処理してレスポンスする必要があります。

公式ドキュメントリダイレクトを使用する - AWS Amplifyに一応、SPAの場合の設定例が記述されているのですが、それではうまく動作しませんでした。

次のように設定するとうまく動作しました。

[
    {
        "source": "</^((?!.(css|gif|ico|jpg|js|png|txt|svg|woff|ttf)$).)*$/>",
        "target": "/",
        "status": "200",
        "condition": null
    }
]

これで、Amplify Consoleによる Nuxt SPAのビルド、デプロイ、配信が完成です。

独自ドメイン設定

さて、ここまでの操作ではデプロイしたものはAmplify Consoleが自動的に割り当てたドメインで配信されます。
開発環境として使うならいいのですが、本番環境で使うには カスタムドメインを設定して独自ドメインでの配信できるようにしなければなりません。

今回はbirthday.iko-yo.net で公開するので、それを設定します。
すでにRoute53のゾーンがあるので、それを選択します。

f:id:HeRo:20190610111054p:plain

サブドメイン名と対応するブランチを指定するとサブドメインも作り放題で増やせます。

設定後、処理が完了するまで、結構時間がかかる場合があります。ちょっと気長に待ちます。
終わるとRoute53にもCNAMEレコードが追加されています。

f:id:HeRo:20190612084039p:plain

以上で本番環境を独自ドメインを使ってAmplify Consoleで運用できます!

ブランチの追加

今回、Amplify Consoleを使ってみようと思った動機はmasterだけでなく複数のブランチで個別の環境を用意したいからでした。
それを実現するためにブランチを追加してみます。

「ブランチの接続」から別のブランチを追加すると簡単に任意のブランチを別環境にデプロイできるようになります。 f:id:HeRo:20190610111003p:plain

一度設定するとそのブランチへPushすると自動的にデプロイされます。
テストやステージングの環境を作り放題です!

ステージングはBASIC認証をかけたい

本番環境以外は関係者だけが見られるように制限したい場合も多いと思います。
Amplify Consoleならそれも簡単です。

左ペインの「アクセスコントロール」を選択するとBASIC認証の設定を行えます。
全ブランチに共通のusername/passwordを設定できますし、 ブランチごとに別々のusername/passwordを設定することもできます。
社内の関係者向け、社外の関係者向け使い分けることも簡単です。

この機能がAmplify Consoleで一番気の利いた機能だと個人的には思いました2

Amplify Consoleを探る

さて、ここまでSPAアプリケーションを設定してデプロイするまでを説明しました。とても便利なAmplify Consoleですが、どんな仕組みで動いているのでしょうか。

AWS Amplify コンソールのドキュメントには記述はないですが、コンソールに表示される値やログから推測すると次のAWSのサービスが使われているようです。

  • CodeBuild
  • S3
  • CloudFront
  • CloudFormation

NuxtのSPAを S3+CloudFrontでホストする。デプロイはCodeBuildで自動化でやったことと大体同じことがサービス化されているんだなぁと思いました。

これらのリソースが使われていると思われるものの、それぞれのサービスのWebコンソールには現れません。 一般的な管理とは別にAmplifyがプライベートに管理する環境でプロビジョニングされるようです。
なので、利用時には上記のリソースに関しては全く気にすることはありません。

配信にはCloudFormationが利用されているようなのでパフォーマンスやスケーラビリティも心配はなさそうです。

Amplify Consoleの気になるところ

Amplify Consoleはとても簡単で便利に使えるサービスです。
今の所、不満な点は殆どありません。
強いて上げるとすれば次の3点でしょうか。

  • 反映されるまでにちょっと時間がかかる設定がある
  • 標準で用意されている通知手段がメールのみ
  • 料金がちょっと割高っぽい

前者は裏で動いている仕組みが多そうなので仕方ない面もあるとは思うのですが、 カスタムドメイン設定とアクセスコントロール設定は反映に時間がかかる印象です。

AWSはもう個別のサービスに通知機能を実装しないでもいいのではと思います。
SNSのトピックにパブリッシュできればあとはよしなにできるので。
欲を言えばSlackへの通知をサポートしてほしいところです。

コストは?

さて、機能面では控えめに言って超オススメなAmplify Console、気になるコスト面ではどうでしょうか?

S3+CloudFront+CodeBuildで同様の仕組みを構築するとしてコストを比較してみました。 すべて東京リージョンでの料金です。

コスト項目 Amplify Console S3+CloudFront+CodeBuild
ビルド(USD/分) 0.01 CodeBuild: 0.01
ストレージ(USD/GB月) 0.023 S3: 0.025
ホスティング(USD) 43.9 CloudFront: 33.8

Amplify Consoleのビルド環境は4 vCPU, 7GB memoryと表示されるのでそれに相当する CodeBuildの料金と比べました。しかし、Nuxtのビルド程度なら一番小さい2 vCPU, 4GB memoryのCodeBuildで十分なのでビルドについては割高だと思います。

ストレージはAmplify Consoleのほうがややお得。しかし全体に占める割合が小さいと思われます。

ホスティングは1MB/リクエストのサイズのページを10000PV/日、30日、HTTPSで配信したときの概算料金です。
これはトラフィックが増えれば(=サイトが成長すれば)支配的なコストとなると思います。
Amplify Consoleはやはりちょっと割高ですね。

まとめ

NuxtのSPAを S3+CloudFrontでホストする。デプロイはCodeBuildで自動化で AWSの各種サービスを自前で連携させて環境を作ったのがバカバカしくなりました。
それほどAmplify Consoleは簡単に使え、便利なサービスです。

運用に関する作業コストははとても小さいので、それが配信のホスティングコストを相殺できると考えられるならオススメサービスです。

最後に

いこーよ!子供BIRTHDAYは毎月第3土曜日にその月生まれのお子様が入場無料になったりするお得クーポンを配布しているサービスです。
夏には地域を拡大してリニューアル予定なのでぜひご利用ください。

birthday.iko-yo.net

アクトインディではそんなパパ・ママ向けのお得サービスを一緒に開発したいエンジニアを募集しています。

actindi.net


  1. https://axios.nuxtjs.org/options#browserbaseurl

  2. CloudFront+S3でこれをやろうとするとLambdaを作って設定したりしないといけないので面倒ですよね。