Amplifyを使えば5分でNext.js環境を公開できちゃう
はじめに
はい、詐欺タイトルです
何も知らない状態から Amplify を使って Next.js をデプロイするのに私は 1 日半ほど費やしました
ただ、デプロイするまでにいくつかあるつまづきポイントを超えるとほんとに簡単にデプロイして公開できるので、そのつまづきポイントをご紹介できれば
記事のターゲット
- S3 + CloudFront に Next.js 環境をデプロイしたい人
- Amplify 使ってみたい人
- Amplify でのデプロイ は GitHub 連携じゃなくて CLI 使って手動でしたい人
概要
なんと! 今なら!! たったの 5 ステップで!!!
- Amplify CLI のインストール
- デプロイ権限がある IAM の作成
amplify init
amplify add hosting
amplify publish
環境
関係ありそうなのだけ
@aws-amplify/cli
はグローバルにインストールしてます
"@aws-amplify/cli": "4.41.2",
"next": "10.0.6",
"react": "17.0.1",
"react-dom": "17.0.1",
"typescript": "4.1.3",
Next.js は CSR でデプロイする前提です
いざ参る
1. Amplify CLI のインストール
npm install -g @aws-amplify/cli
して AmplifyCLI をインストール
つまづきポイント 1
最初に amplify の設定をするのにamplify init
をする際に
自分のリポジトリ配下に@aws-amplify/cli
を yarn でインストールしたらうまくいかなかった
amplify init
の設定中に下記エラーが発生する
(node:98501) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'value' of undefined
issue を読み漁るとnpm install -g @aws-amplify/cli
してねとのこと
2. デプロイ権限がある IAM の作成
今回は事前にデプロイ用の IAM が用意されていたのでやっていないが
amplify configure
すると aws console からいくつかの手順を進めると AdministratorAccess 権限を持った User を作成してくれる親切設計
amplify init
3. Amplify App を作るための初回設定
実行すると CLI 上で設定に必要な情報を登録する流れに
❯ amplify init
Initializing new Amplify CLI version...
Done initializing new version.
Scanning for plugins...
Plugin scan successful
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project {プロジェクト名}
? Enter a name for the environment dev
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path: src
? Distribution Directory Path: out
? Build Command: yarn build
? Start Command: yarn start
Using default provider awscloudformation
? Do you want to use an AWS profile? No
? accessKeyId: ***
? secretAccessKey: ***
? region: ap-northeast-1
accessKey と secretAccessKey はデプロイ権限を持ってるやつ
無事に終わるとルート直下にamplify
ディレクトリが生成される
つまづきポイント 2
Next.js を S3 の静的ホスティング(or CloudFront で CDN 配信)するには build 時のコマンドを変えとく
下記のように build コマンドを変更すると build されたファイルが/out
ディレクトリに生成される
"scripts": {
"build": "next build && next export",
},
amplify add hosting
4. どのようにホスティングするか設定する
❯ amplify add hosting
? Select the plugin module to execute: Hosting with Amplify Console
? Choose a type: Manual deployment
無事に終わるとamplify/backend/hosting/amplifyhosting
が追加される
つまづきポイント 3
❯ Hosting with Amplify Console (Managed hosting with custom domains, Continuous deployment)
Amazon CloudFront and S3
え、当たり前のようにAmazon CloudFront and S3
使うんしょって思ってそっち選ぶとAccessDenied の壁を超えられず
できた CloudFront や S3 のバケットの中を見る感じ、うまくできてるはずなんだけど・・
TODO: Amazon CloudFront and S3 でも公開できるようにする
amplify publish
amplify publish
で設定した内容でデプロイしてくれる
番外編: CICD に組み込みたい(CircleCI 編)
-
amplify init
を Headless mode で定義する - local で
amplify init
する - local で
amplify add hosting
する -
config.yml
にデプロイ step を追加する
amplify init
を Headless mode で定義する
1. CICD で実行できるように Headless mode なるものが Amplify CLI にはある
サンプルに書かれているものを shell で定義した
#!/bin/sh
set -e
IFS='|'
ACCESS_KEY=""
SECRET_KEY=""
usage () {
cat <<EOM
Usage: $(basename "$0") [OPTION]...
-h Display help
-a ACCESS_KEY Access key of AWS
-s SECRET_KEY secret key of AWS
EOM
exit 2
}
while getopts "a:s:h" OPT
do
case $OPT in
"a" ) ACCESS_KEY="$OPTARG";;
"s" ) SECRET_KEY="$OPTARG";;
'-h'|'--help'|* ) usage ;;
esac
done
REACTCONFIG="{\
\"SourceDir\":\"src\",\
\"DistributionDir\":\"out\",\
\"BuildCommand\":\"yarn build\",\
\"StartCommand\":\"yarn start\"\
}"
AWSCLOUDFORMATIONCONFIG="{\
\"configLevel\":\"project\",\
\"useProfile\":false,\
\"profileName\":\"default\",\
\"accessKeyId\":\"$ACCESS_KEY\",\
\"secretAccessKey\":\"$SECRET_KEY\",\
\"region\":\"ap-northeast-1\"\
}"
# project-nameには任意のproject名
AMPLIFY="{\
\"projectName\":\"project-name\",\
\"envName\":\"dev\",\
\"defaultEditor\":\"code\"\
}"
FRONTEND="{\
\"frontend\":\"javascript\",\
\"framework\":\"react\",\
\"config\":$REACTCONFIG\
}"
PROVIDERS="{\
\"awscloudformation\":$AWSCLOUDFORMATIONCONFIG\
}"
amplify init \
--amplify $AMPLIFY \
--frontend $FRONTEND \
--providers $PROVIDERS \
--yes
ほぼやってることはサンプルコードと一緒だが AWS のアクセスキーとシークレットキーを CircleCI の Context から受け取れるように引数でもらってる
amplify init
とamplify add hosting
2. 前段で記載した通り
プロジェクトに設定情報を保存するため、ローカルで必ず一度実行する
amplify init
に関しては定義した shell を実行すれば良き
config.yml
にデプロイ step を追加する
deploy_stg:
executor: default
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Install amplify cli
command: curl -sL https://aws-amplify.github.io/amplify-cli/install | bash && $SHELL
- run:
name: Update path
command: echo 'export PATH="$HOME/.amplify/bin:$PATH"' >> $BASH_ENV
- run:
name: Init amplify
# contextから環境変数は取得する
command: sh scripts/amplify_init/main.sh -a "$AWS_ACCESS_KEY_ID" -s "$AWS_SECRET_ACCESS_KEY"
- run:
name: Deploy
command: amplify publish --yes
つまづきポイント 4
つまづきポイント 5
cimg/node:14.15.4
のコンテナ内で build すると下記のようなエラーを吐く
> Build error occurred
Error: Cannot find module 'sharp'
Require stack:
- /home/circleci/src/node_modules/next/dist/build/index.js
- /home/circleci/src/node_modules/next/dist/cli/next-build.js
- /home/circleci/src/node_modules/next/dist/bin/next
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
at Function.resolve (internal/modules/cjs/helpers.js:94:19)
at /home/circleci/src/node_modules/next/dist/build/index.js:11:1029
at /home/circleci/src/node_modules/next/dist/build/tracer.js:1:1331
at NoopTracer.withSpan (/home/circleci/src/node_modules/@opentelemetry/api/build/src/trace/NoopTracer.js:47:16)
at ProxyTracer.withSpan (/home/circleci/src/node_modules/@opentelemetry/api/build/src/trace/ProxyTracer.js:36:34)
at traceFn (/home/circleci/src/node_modules/next/dist/build/tracer.js:1:1301)
at /home/circleci/src/node_modules/next/dist/build/index.js:11:365
at async /home/circleci/src/node_modules/next/dist/build/tracer.js:1:1441 {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/home/circleci/src/node_modules/next/dist/build/index.js',
'/home/circleci/src/node_modules/next/dist/cli/next-build.js',
'/home/circleci/src/node_modules/next/dist/bin/next'
]
}
error Command failed with exit code 1.
yarn add sharp
せえよとのこと
番外編: Amplify コンソールは Basic 認証がめっちゃ楽
Cloud Front + S3 環境だと Cloud Front 側で Basic 認証の設定するような Lambda を実装してたけど、Amplify コンソールでは画面ぽちぽちですぐ Basic 認証できる
Discussion