S3+CloudFrondでNuxt.js(vue)のHTTPS静的サイトを構築・デプロイ

初めての構築だったので自分用にメモ

# やったこと
・route53にてドメインの登録
・S３にてバケットを作成
・CloudFrontにてDistributionを作成
・ACMにてSSL証明書を発行
・gulpfile.jsを作成してファイルをアップロード
・デプロイ

# route53にてドメインを登録
example.comという仮のドメインを取得。

Route53の画面のHosted Zoneを選択
さらにCreate Hosted Zoneボタンを選択、

Domain Name: example.com
Comment: (任意)
Type: Public Hosted Zone

上記を記入してCreateボタンをクリックして登録完了。

Hosted zoneの画面でexample.comを選択し、4つのNSレコードを、ドメインを取得した会社の設定ページ（ネームサーバー変更）に登録。

# S3バケットを作成
S3の画面上で『＋バケットを作成する』を選択。

バケット名：　example.com
リージョン：　アジアパシフィック（東京）

オプションの設定
アクセス許可の設定

は特にいじらず上記で作成。

その後S3の画面のexample.comのバケットを選択して『プロパティ』の画面にて
『Static website hosting』を選択

・このバケットを使用してウェブサイトをホストするを選択して
インデックスドキュメントの欄に『index.html』と記入して保存。

# CloudFrontの設定
CloudFrontの画面にて『CreateDistribution』を選択。
Webにて『Get Started』を選択。

Original Domain Name：　example.com.s3.amazonaws.com
Restrict Bucket Access：　Yes
Origin Access Identity：　Create a New Identity
Grant Read Permissions on Bucket：　Yes,Update Bucket Policy
Viewer Protocol Policy: Redirect HTTP to HTTPS
Alternate Domain Names(CNAMEs)： example.com
SSL Certificate: Custom SSL Certificate (example.com):
Default Root Object->index.html

途中SSL Certificate: の欄にて
『Request or Import a Certificate with ACM』
を選択してSSL証明書を発行。
ACM画面でドメイン名を設定(*.も追加して登録)して、DNS認証にてCNAMEを作成して証明書を発行。
※なぜかリージョンがパージニア北部にて作成しないと設定ができなかった。

先ほどのCloudFrontの画面で作成した証明書を選択してDistributionを作成完了する。

# CloudFrontへ独自ドメインでアクセスする。
Route53でAレコードを追加

Name: example.com
Alias: Yes
Alias Target: xxx.cloudfront.net(CloudFrontのalias)
Routing Pollicy: Simple
Evaluate Target Health: No

上記で設定する。
# ユーザーにポリシーを追加
ポリシー内容は
・バケットのコンテンツを更新する
・cloudfront distribution でのキャッシュ削除（変更を素早くユーザに伝播させる）

下の二つの example.com をあなたの S3 バケット名に置き換えて、ユーザにポリシーを追加する。

```
{
    "Version": "2012-10-17",
    "Statement": [ {
            "Effect": "Allow",
            "Action": [ "s3:ListBucket" ],
            "Resource": [
                "arn:aws:s3:::example.com"
            ]
        }, {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:GetObject",
                "s3:GetObjectAcl",
                "s3:DeleteObject",
                "s3:ListMultipartUploadParts",
                "s3:AbortMultipartUpload"
            ],
            "Resource": [
                "arn:aws:s3:::example.com/*"
            ]
        }, {
            "Effect": "Allow",
            "Action": [
                "cloudfront:CreateInvalidation",
                "cloudfront:GetInvalidation",
                "cloudfront:ListInvalidations",
                "cloudfront:UnknownOperation"
            ],
            "Resource": "*"
        }
    ]
}
```

#  AWSにてユーザーのアクセスキーとシークレットアクセスキーを取得
・AWS_ACCESS_KEY_ID="key"
・AWS_SECRET_ACCESS_KEY="secret"

# Nuxt.jsプロジェクトとコマンドラインに Gulp を追加

```
npm install --save-dev gulp gulp-awspublish gulp-cloudfront-invalidate-aws-publish concurrent-transform
npm install -g gulp
```
# `deploy.sh` スクリプトを作成
プロジェクトファイルに`deploy.sh`を作成して、下記を記入しビルドスクリプトをセットアップする。
AWS_ACCESS_KEY_ID="key"
AWS_SECRET_ACCESS_KEY="secret"
AWS_BUCKET_NAME="example.com"
AWS_CLOUDFRONT="UPPERCASE"
はそれぞれ取得したもの、作成した物・IDを記入する。

```deploy.sh
#!/bin/bash

# nvm (node version manager) のロード、node のインストール (バージョン指定は .nvmrc ファイルにある)、 npm パッケージのインストール
[ -s "$HOME/.nvm/nvm.sh" ] && source "$HOME/.nvm/nvm.sh" && nvm use
# 既にインストールされていなければ、 npm をインストールする
[ ! -d "node_modules" ] && npm install

npm run generate
AWS_ACCESS_KEY_ID="key" AWS_SECRET_ACCESS_KEY="secret" AWS_BUCKET_NAME="example.com" AWS_CLOUDFRONT="UPPERCASE" gulp deploy
```

# `deploy.sh`を実行可能にする。
コマンドラインでファイルのパーミッションを変更して実行可能にする。

```
chmod +x deploy.sh
```
# `.gitignore` に追記

Gitのコミットから除外するものを指定

```html:.gitignore
# Don't commit build files
node_modules
dist
.nuxt
.awspublish
deploy.sh
```
# `gulpfile.js` を作成
プロジェクトファイルに`gulpfile.js`を作成し、以下を記入してAWS S3にアップロード出来るようにする。

```gulpfile.js
var gulp = require('gulp');
var awspublish = require('gulp-awspublish');
var cloudfront = require('gulp-cloudfront-invalidate-aws-publish');
var parallelize = require('concurrent-transform');

// https://docs.aws.amazon.com/cli/latest/userguide/cli-environment.html

var config = {

  // 必須
  params: { Bucket: process.env.AWS_BUCKET_NAME },
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,

  // 任意
  deleteOldVersions: false,                 // PRODUCTION で使用しない
  distribution: process.env.AWS_CLOUDFRONT, // Cloudfront distribution ID
  region: process.env.AWS_DEFAULT_REGION,
  headers: { /*'Cache-Control': 'max-age=315360000, no-transform, public',*/ },

  // 適切なデフォルト値 - これらのファイル及びディレクトリは gitignore されている
  distDir: 'dist',
  indexRootPath: true,
  cacheFileName: '.awspublish',
  concurrentUploads: 10,
  wait: true,  // Cloudfront のキャッシュ削除が完了するまでの時間 (約30〜60秒)
}

gulp.task('deploy', function() {
  // S3 オプションを使用して新しい publisher を作成する
  // http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
  var publisher = awspublish.create(config, config);

  var g = gulp.src('./' + config.distDir + '/**');
    // publisher は、上記で指定した Content-Length、Content-Type、および他のヘッダーを追加する
    // 指定されていない場合、 x-amz-acl はデフォルトで public-read に設定される
  g = g.pipe(parallelize(publisher.publish(config.headers), config.concurrentUploads))

  // CDN のキャッシュを削除する
  if (config.distribution) {
    console.log('Configured with Cloudfront distribution');
    g = g.pipe(cloudfront(config));
  } else {
    console.log('No Cloudfront distribution configured - skipping CDN invalidation');
  }

  // 削除したファイルを同期する
  if (config.deleteOldVersions) g = g.pipe(publisher.sync());
  // 連続したアップロードを高速化するために、キャッシュファイルを作成する
  g = g.pipe(publisher.cache());
  // アップロードの更新をコンソールに出力する
  g = g.pipe(awspublish.reporter());
  return g;
});
```
# デプロイとデバッグ
コマンドラインで実行する。
S3のバケットに、npm run generateによって作成された```dist```フォルダの中身がアップロードされる。

実行する前にS3バケットの
アクセス権限の中の
『パブリックアクセス設定』
のブロックをfalseにして解除すると無事アップロード出来ました。

```
./deploy.sh
```

これで成功すれば独自ドメインでアクセス出来るはず！！！

後半は公式ドキュメントと全く同じです。
https://ja.nuxtjs.org/faq/deployment-aws-s3-cloudfront/