angularjsawss3cloudfrontspa

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

January 15, 2015

8 min read

mitsuruogMitsuru Ogawa

最近は、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