Vue.js を CloudFront+S3 で公開する手順
🎯ゴール
Vue.jsで作成されたプロジェクトを AWS の CloudFront + S3 のインフラ構成で公開する

💡前提
- すでに Vue.js プロジェクトが作成されている
 - GitHub に Vue.js プロジェクトのリポジトリが作成されていること
 - CI/CDツールには GitHub Actions を利用しています
 - GitHub Actions のワークフローで AWS 認証する方法として OIDC を利用する方法もありますが、今回はクレデンシャル情報を利用して認証しています
 
🏃手順
1.GitHub Actions でデプロイするワークフローを作成します
Vue.jsで作成されたプロジェクトに以下の YAML ファイルを作成してください。
# プロジェクトへのパスは変えてください
cd path/to/your-vue-project
mkdir -p .github/workflows
vim deploy-production.yaml
.github/workflows/deploy-production.yaml
※ env.AWS_REGION は適切なリージョンに書き換えてください。
※ AWS 認証には OIDC を利用する方法もありますが、今回はクレデンシャル情報を利用して認証しています
name: Deploy to Production
on:
  push:
    branches:
      - main
env:
  AWS_REGION: "ap-northeast-1"
jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18.x]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "::set-output name=dir::$(yarn cache dir)"
      - name: cache
        id: yarn-cache
        uses: actions/cache@v3
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: yarn install
        run: |
          yarn install
      - name: eslint
        run: |
          yarn lint
      - name: build
        run: |
          yarn run build
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}
      - name: deploy
        run: |
          aws s3 sync --exact-timestamps --delete ./dist s3://${{ secrets.AWS_BUCKET_NAME }}/
          aws cloudfront create-invalidation --distribution-id ${{ secrets.CF_DISTRIBUTION_ID }} --paths "/*"
2.S3 バケットを作成する
バケットを作成する

S3 Management Console にアクセスして、「バケットを作成」をクリックしてください。

「バケット名」を入力し、「AWS リージョン」で適当なリージョンを選択し、オブジェクト所有者は「ACL 無効(推奨)」を選択してください。

「パブリックアクセスをすべてブロック」を全て無効にして、公開アクセス可能な状態にします。

「バケットを作成」ボタンをクリックして、バケットを作成してください。
プロパティを更新する

バケットを作成したら、「プロパティ」画面を開いてください。

「静的ウェブサイトホスティング」の編集ボタンをクリックしてください。

静的ウェブサイトホスティングを有効にして、ホスティングタイプ、インデックスドキュメントを選択、入力してください。
アクセス許可を更新する

「アクセス許可」画面を開いてください。

バケットポリシーを編集し、バケットにアップロードされるオブジェクトを読み込みできるようにします。
バケットポリシー
※バケット名は書き換えてください。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::バケット名/*"
        }
    ]
}
3.CloudFront を構築する

CloudFront | Global にアクセスして、「バケットを作成」をクリックしてください。

「オリジンドメイン」に先ほど作成した S3 バケットを選択し、「Web サイトのエンドポイントを使用」を選択してください。

Httpsにリダイレクトするようにして、GET, HEAD の HTTP メソッドしか許可しないように設定します。
4.「404 Not Found」が発生しないようにする
vue-routerを利用したVue.jsのプロジェクトの場合、ブラウザで「/items/1」などのトップページ以外の画面でロードすると以下のようにエラー画面が表示されてしまいます。そのため、画面が表示されるように設定します。


「エラーページ」を選択し、「カスタムエラーレスポンスを作成」ボタンを押してください。

「HTTPエラーコード」が「404:Not Found」のときに「/index.html」を「200:OK」で返すように設定します。
これで完了です。
5.GitHub にクレデンシャル情報を登録する
GitHub Actions のワークフローで扱う以下のクレデンシャル情報を GitHub の Vue.js プロジェクトのリポジトリに登録しておきます。
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_BUCKET_NAMECF_DISTRIBUTION_ID

6.GitHub リポジトリに push する
# プロジェクトへのパスは変えてください
cd path/to/your-vue-project
git add .
git commit -m "first commit"
git push origin main
push したら、Actions タブ画面でワークフローが実行され、S3 にオブジェクトがアップロードされて、CloudFront のキャッシュが削除されて、閲覧できるようになります。

📝補足
独自ドメインで公開したい
🔗APPENDIX
1.AWS
- CloudFrontとS3で作成する静的サイト構成の私的まとめ | DevelopersIO
 - 【AWS】S3+CloudFrontを使って静的サイトをHttpsで公開する方法解説
 - Vue.jsで作ったWebサイトをAmazon S3+CloudFrontで公開する - じゅころぐAR
 - nuxt generate+S3+CloudFrontで403エラーを防ぐ方法 - Qiita
 
Discussion