【AWS】CloudFront で SPA 環境を構築する

Skrumエンジニアの根岸です。
SPA(シングルページアプリケーション)のフロントエンドアプリケーション(Vue.js, React.js 等)は CDN(コンテンツデリバリネットワーク)に配置して運用する場合が多いです。今回は AWS の CDN サービスである Amazon CloudFront で SPA 環境を構築する方法をご紹介します。
- S3 バケットを作成
- ACM で SSL 証明書を発行
- CloudFront ディストリビューションを作成
- S3 バケットのバケットポリシーを設定
- デフォルトルートオブジェクトを設定
- カスタムエラーレスポンスを作成
- フロントエンドアプリケーションのデプロイ
CloudFront のドメインはデフォルトのものではなく独自ドメインを設定するようにします。
1. S3 バケットを作成
CloudFront にコンテンツを配置するためには、そのオリジンとなる S3 バケットを作成する必要があります。
設定は全てデフォルトで問題ありません。(「ACL 無効」と「パブリックアクセスをすべてブロック」にチェックが入っていることを確認しましょう。)

2. ACM で SSL 証明書を発行
CloudFront に独自ドメインを設定しアクセスを SSL 化する場合、ACM で SSL 証明書を発行しましょう。
SSL 証明書の発行方法は以前書いた記事「【AWS】ACMでSSL証明書を発行する」を参照してください。
なお、CloudFront で SSL 証明書を利用するためには、ACM のリージョンを「バージニア北部」で発行する必要がありますので注意しましょう。
3. CloudFront ディストリビューションを作成
CloudFront のページを開いて「ディストリビューションを作成」からディストリビューションを作成しましょう。
まず、オリジンとなる S3 バケットを選択します。手順1で作成したバケットが選択肢に表示されていますのでそれを選択します。
オリジンを選択するとその下の項目「名前」は自動で設定されます。通常はデフォルト設定のままで問題ありません。

次に、オリジンアクセスを設定します。
SPA 環境を構築する場合、ほとんどの場合は S3 バケットはフロントエンドアプリケーション配置専用のバケットとなるでしょう。よって S3 バケットへのアクセスは CloudFront のみからとなるため「Origin access control settings (recommended)」を選択します。

OAC はデフォルトの設定のまま作成すれば問題ありません。

今回は SSL 証明書を設定して HTTPS 通信としますので、「ビューワープロトコルポリシー」は「Redirect HTTP to HTTPS」を選択します。
「許可された HTTP メソッド」は「GET, HEAD, OPTIONS」を選択して「オプション」にチェックします。

CloudFront に設定する独自ドメインを「代替ドメイン名 (CNAME)」に設定します。(手順2で発行したSSL証明書のドメインと同じドメインを指定します。)
次に「カスタム SSL 証明書」のプルダウン選択肢から手順2で発行した SSL 証明書を選択します。ACM で発行した証明書が選択肢として表示されない場合は、リージョンを「バージニア北部」以外のリージョンで作成してしまっているというミスが多いです。

最後に一番下の「ディストリビューションを作成」ボタンをクリックするとディストリビューションが作成されます。

4. S3 バケットのバケットポリシーを設定
CloufFront ディストリビューションの作成は完了しました。続いて CloudFront が S3 バケットからコンテンツを取得できるようにバケットポリシーを編集します。
まずは CloudFront のオリジンの編集画面から 設定する S3 バケットポリシーをコピーします。


次にコピーしたポリシーを当該 S3 バケットのバケットポリシーにペーストして保存します。



5. デフォルトルートオブジェクトを設定
SPA のフロントエンドアプリケーション(Vue.js, React.js 等)を CloudFront に配置する場合、デフォルトルートオブジェクトを指定する必要があります。これは CloudFront に設定した独自ドメイン(例えば「cdn-test.skrum.co.jp」)をブラウザの検索バーに入れてアクセスした場合に、デフォルトで返すオブジェクトの指定です。
例えば、デフォルトルートオブジェクトを指定しない場合、
https://cdn-test.skrum.co.jp にアクセスすると “AccessDenied” が表示されます。これはルート”/”へのアクセスが許可されていないからです。
一方で、オブジェクトを指定して、
https://cdn-test.skrum.co.jp/hoge.png にアクセスすると正常にコンテンツが表示されます。
デフォルトルートオブジェクトに例えば hoge.png を指定した場合、
https://cdn-test.skrum.co.jp にアクセスすると hoge.png のコンテンツが表示されるようになります。
ほとんどの SPA フロントエンドアプリケーションは “index.html” がデフォルトルートオブジェクトとなるでしょう。
下記のように設定しましょう。


6. カスタムエラーレスポンスを作成
リロードした際に S3 内のオブジェクトを直接読み込んでしまうことを防ぐために下記のカスタムエラー設定をします。

これで、CloudFront, S3 の設定は全ての作業が完了です。
7. フロントエンドアプリケーションのデプロイ
S3 と CloudFront にビルドしたフロントエンドアプリケーション(Vue.js, React.js 等)をデプロイすると、SPA アプリとして機能するようになります。
フロントエンドアプリケーションのデプロイ方法については次回の記事でご紹介予定です。