【nuxt.js】S3・CloudFront構成　CodeBuildでのデプロイ自動化

# 概要

Nuxt.jsで作成したプロジェクトをgulp, CodeBuildを使って自動デプロイする手順をまとめます。

# 参考URL

以下のURLを参考に、CodeBuildの設定を変更しています。

https://tech.actindi.net/2018/10/19/083000

https://ja.nuxtjs.org/docs/2.x/deployment/deployment-amazon-web-services/


# 事前準備

- yarnコマンドを使えるようにする

https://qiita.com/suisui654/items/1b89446e03991c7c2c3d

# 手順

## 1. gulpのインストール

`yarn add gulp`

今回はローカル環境にyarnを使ってインストール

gulpfileで使用しているモジュールを追加

`yarn add gulp-awspublish`
`yarn add gulp-cloudfront-invalidate-aws-publish`
`yarn add concurrent-transform`

## 2. gulpfile.jsを作成

gulpfile.jsをプロジェクトのルートディレクトリに作成します。
ここでは、[公式ページ](https://ja.nuxtjs.org/docs/2.x/deployment/deployment-amazon-web-services/)からコピーして、以下を変更します。

- credentialsを削除（CodeBuildのIAMポリシーを使うため不要）
- deleteOldVersionsをtrueに変更（S3上の古いファイルを削除）
- headersに`'x-amz-acl': 'private'`を追加（[S3のパブリックアクセスブロックへの対処](https://qiita.com/GussieTech/items/3ae77dbcb1e79222a9bc)）

```js
const gulp = require('gulp')
const awspublish = require('gulp-awspublish')
const cloudfront = require('gulp-cloudfront-invalidate-aws-publish')
const parallelize = require('concurrent-transform')

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

const config = {
  // Required
  params: {
    Bucket: process.env.AWS_BUCKET_NAME,
  },

  // Optional
  deleteOldVersions: true, // S3上の古いファイルを削除する
  distribution: process.env.AWS_CLOUDFRONT, // CloudFront distribution ID
  region: process.env.AWS_DEFAULT_REGION,
  headers: {
    /* 'Cache-Control': 'max-age=315360000, no-transform, public', */
    'x-amz-acl': 'private',
  },

  // Sensible Defaults - gitignore these Files and Dirs
  distDir: 'dist',
  indexRootPath: true,
  cacheFileName: '.awspublish',
  concurrentUploads: 10,
  wait: true, // wait for CloudFront invalidation to complete (about 30-60 seconds)
}

gulp.task('deploy', function () {
  // create a new publisher using S3 options
  // http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
  const publisher = awspublish.create(config)

  let g = gulp.src('./' + config.distDir + '/**')
  // publisher will add Content-Length, Content-Type and headers specified above
  // If not specified it will set x-amz-acl to public-read by default
  g = g.pipe(
    parallelize(publisher.publish(config.headers), config.concurrentUploads)
  )

  // Invalidate 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'
    )
  }

  // Delete removed files
  if (config.deleteOldVersions) {
    g = g.pipe(publisher.sync())
  }
  // create a cache file to speed up consecutive uploads
  g = g.pipe(publisher.cache())
  // print upload updates to console
  g = g.pipe(awspublish.reporter())
  return g
})

```


## 3. ソースを設定

使用中のリポジトリに合わせて、CodePipelineで設定します。
ここでは説明を省略します。

## 4. buildspec.ymlを作成

プロジェクトファイルのルートディレクトリでbuildspec.ymlを作成。
[参考URL](https://tech.actindi.net/2018/10/19/083000)のまま（Ubuntuのイメージを利用）だと、うまくできなかったため、AmazonLinuxを利用するように変更しています。
Node.jsのバージョンは10以上が推奨されているようです（2021年5月現在）

```yml
version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 12
  pre_build:
    commands:
      - echo 'Start pre_build phase'
      - yum update -y
      - yum -y install wget
      - wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo
      - curl --silent --location https://rpm.nodesource.com/setup_12.x | bash -
      - yum install yarn
      - yarn install
  build:
    commands:
      - echo 'Start build phase'
      - yarn generate
  post_build:
    commands:
      - echo 'Start post_build phase'
      - ./node_modules/.bin/gulp deploy
```



## 5. CodePipeline、CodeBuildの設定

環境を以下のように設定します。
CodeBuildの環境変数には、
- DEPLOY_ENV：S3
- AWS_CLOUDFRONT：デプロイ先CloudFrontディストリビューションのID
- AWS_BUCKET_NAME：デプロイ先S3のバケット名
を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369237/c24d8aac-8ca4-0a1a-bd19-f4d08c76a69a.png)

### 補足

- Codebuildを使う際は、[イメージとruntimeの対応](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-env-ref-available.html)を調べておくと良さそうです。
- 特権付与は必要ないかもしれません。