2015-01-15

AngularJSで作ったSPAをAWS上の「S3+CloudFront」でお手軽ホスティングして、クラウドサービスってやっぱ素晴らしいなと思った話

最近は、WebAPIやAWSのようなクラウドサービスが普及してきて、バックエンドのサーバーがなくても、Webサービスが公開できるようになってきました。

今回はAWSのS3にあるStatic Website Hosting機能を使ってAngularJSで作成したSPA(Single page application)をホスティングさせてみました。

割とS3でのサイト公開は簡単なので楽勝かと思いきや・・・
いろいろまじめに考えると手こずるものですね。

S3でのSPA公開

S3でのサイト公開は非常に簡単です。次の3ステップで即公開できます。
(「S3 サイト公開」などで検索するといくつか記事がヒットすると思いますので参考にしてください。)

  • S3上にBucketを作成する。
  • AngularJSで作成したSPAをアップロードする。
  • BucketのStatic Website HostingをONにする。

Static Website HostingをONにすることでアクセス可能なURLが取得できます。
アクセスした際に「AccessDenied」エラーになる場合は、アップロードしたファイルのPermissionsEveryoneアクセス可能になっていないことが多いです。

しかし、このEveryoneアクセス可能状態はあまりいい状態ではありませんので、CloudFrontを利用します。
(後で紹介しますが、S3はCloudFront経由のアクセスのみ有効にする設定を推奨します。)

S3のEveryoneアクセス可能はApacheの設定漏れで、ファイル一覧が見えてしまっている感覚に似ていて落ち着きませんw

他にも、S3で公開した場合に問題になりそうな部分について紹介します。

S3でのSPA公開で問題になりそうなところ

S3のStatic Website Hosting機能はお手軽で非常に魅力を感じるのですが、Webアプリケーションを想定した場合、次のような問題がありそうです。

  • アクセスをHTTPSに限定できない。
  • URLに「/」を指定した場合、S3上のフォルダを参照してしまいエラーとなる。(結果「/index.html」まで含める形に・・・)
  • /」以外のURL(「/hoge」とか)でアクセスした場合に403(access denied)エラー(2015/01/20 追記)
  • 他にもあった気がするが、忘れた。

という訳でS3のみのお手軽ホスティングは、コーポレートサイトのような静的コンテンツ向きな気がします。

CloudFrontの利用

そこで利用するのがCloudFrontです。いろいろ探していたら、こちらの記事が参考になりました。ありがとうございます!

[CloudFront + S3]特定バケットに特定ディストリビューションのみからアクセスできるよう設定する | Developers.IO

手順としては次のような形です。

  • CloudFront上にDistributionsを作成
  • Origin Domain NameにS3のBucketを指定
  • Restrict Bucket Accessで「Yes」を設定してS3へのアクセスを制限

これでCloudFront経由でS3へアクセスすることができますが、SPAをホスティングするに当たって追加で以下の設定をしました。

General > Default Root Object

Default Root Objectに「index.html」を設定します。これで「/」でアクセスした際に、エラーにならず「index.html」を呼び出すことができます。

しかも、デフォルトの(*.cloudfront.net)ドメインであればSSL証明書までついてきます。
まじで至れり尽くせりです。

Behaviors > Viewer Protocol Policy

新しいBehaviorを作成してViewer Protocol PolicyにてRedirect HTTP to HTTPSを選択します。これでHTTPでアクセスされた場合に、HTTPSにリダイレクトすることが可能です。
(あまりこだわりなければPath PatternDefault (*)1つで事足りるはず。)

CloudFront利用上の注意点

CloudFrontを利用すると幸せになれるのですが、1点注意点があります。それはキャッシュです。

CloudFrontの本質はCDNなので、コンテンツをキャッシュします。しかもデフォルトでは24hキャッシュを保持するので、S3上にアップロードしたファイルは最大24h変更されません。

Invalidationsを利用してCacheをクリア

CloudFrontにはInvalidationsというキャッシュクリアをする仕組みがあるので、これを使ってCloudFrontに対してキャッシュのクリアを指示します。
(ただ、5〜10分くらいかかります。リアルタイムではないです。)

CloudFrontでDistributionsを選択すると「Invalidations」というタブがあるので、ここで「Create Invalidation」ボタンをクリックします。

クリアするファイルを指定する必要があるので、例えば「/index.html」とか入力します。
私の場合、フロントのリソースは結合&minify&バージョニングして最適化してしまうので、普段はindex.htmlだけで十分です。

あとはキャッシュがクリアされるまで気長に待ちましょう。

まとめ

「S3+CloudFront」を使うことでお手軽にAngularJSで作成したWebアプリケーションをホスティングすることができました。しかも勝手にスケールするし、クラウドサービス偉大過ぎます。

しかし、上には上がいる!

今回の「S3+CloudFront」はまだ大関構成なようですね。個人的には頑張ったと思うのですが。。。orz
こちらの記事を読むと、この上の「S3+CloudFront+Route53」横綱構成があるようです。

AWSにおける静的コンテンツ配信パターンカタログ(アンチパターン含む) | Developers.IO

もっと稽古します。

(2015/01/20 追記)
/以外のURLでアクセスした場合に403(access denied)エラーになるのですが、CloudFront DistributionsのError Pages設定で、403エラーの場合のエラーページを/index.htmlにすることで回避することができましたー。
うぇーーーーい!!って無理矢理感が半端ないw