Nuxt を Amazon Web Services にデプロイする
S3 Amplify と CloudFront による AWS 上の静的ホスティング
AWS とは Amazon Web Services の略です。 S3 は静的サイトホスティング用の設定が行える静的ストレージです。CloudFront はそれらの CDN です(コンテンツ・デリバリー・ネットワーク)。
Amplify Console と AWS
Amplify Console を使用した AWS での静的に生成された Nuxt アプリケーションのホスティングはパワフルで安上がりです。
はじめに、任意の Git プロバイダーに Nuxt アプリケーションをプッシュしてください。そのあと Amplify Console にアクセスしてください。Amplify Hosting を使用したことがない場合、Deploy ヘッダー下の GET STARTED ボタンをクリックし、そうでなければ Connect App ボタンをクリックしてください。
From your existing code
"From your existing code" ページでは、Git プロバイダーを選択し Continue をクリックしてください。
Add repository branch
"Add repository branch" ページでは、デプロイしたいリポジトリとブランチを選択してください。その後 Next をクリックしてください。
ビルド設定
"Configure build settings" ページでは、"Build and test settings" の Edit
ボタンをクリックしてください。また以下のように変更を行なってください:
-
build commands に
npm run generate
を設定します。 -
baseDirectory
の場所にdist
を設定します。
編集が完了した設定は以下のようになります:
version: 1
frontend:
phases:
preBuild:
commands:
- yarn install
build:
commands:
- npm run generate
artifacts:
# 重要 - ビルド出力ディレクトリを確認してください
baseDirectory: dist
files:
- '**/*'
cache:
paths:
- node_modules/**/*
その後、Save と Next をクリックしてください。
レビュー
レビューページでは、Save and deploy をクリックしてください。
その後、アプリケーションがデプロイされます。この作業には数分かかります。
Provision
、Build
、Deploy
、そして Verify
が緑になり、Amplify Console が提供する URL をクリックするとサイトが表示されます。
AWS と S3 + CloudFront
S3 + CloudFront を使用した AWS での静的に生成された Nuxt アプリケーションのホスティングはパワフルで安上がりです。
AWS は徐々に衰退しています。もし見逃しているステップがあれば、このドキュメントを更新するために PullRequest を提出してください。
概要
複数の AWS のサービスで非常に安くホストします。簡単にまとめると:
-
S3
- web サイトのファイルのためにクラウドデータ "bucket" があります
- 静的な web サイトをホストするよう設定できます
-
CloudFront
- CDN(コンテンツ・デリバリー・ネットワーク)
- HTTPS 証明書を無料で提供します
- サイトの読み込みを高速化します
以下のようにサイトをプッシュします:
Nuxt Generate -> Local folder -> AWS S3 Bucket -> AWS CloudFront CDN -> Browser
[ nuxt generate ] [ gulp deploy ]
[ deploy.sh ]
はじめに、nuxt generet
e(<= v2.12)でサイトを作成してください。次に Gulp を使用して S3 バケットにファイルを公開し、CloudFront CDN を無効にしてください。
デプロイスクリプトでは以下の環境変数を設定する必要があります:
- AWS_BUCKET_NAME="example.com"
- AWS_CLOUDFRONT="UPPERCASE"
- AWS_ACCESS_KEY_ID="key"
- AWS_SECRET_ACCESS_KEY="secret"
このようなファイルがあります:
deploy.sh - `nuxt generate` と `gulp deploy` を実行します
gulpfile.js - S3 にファイルをプッシュし、CloudFront を無効にする `gulp deploy` コードです
設定方法
- S3 バケットを作成し、静的サイトのホスティング用に設定します
- CloudFront ディストリビューションを作成します
- セキュリティ・アクセスの設定をします
- プロジェクトでビルドスクリプトを設定します
AWS: S3 バケットと CloudFront ディストリビューションの設定
ステップ 1、2 は S3 と CloudFront 設定のチュートリアル にしたがって進めてください。
これでデータが揃います:
- AWS_BUCKET_NAME="example.com"
- AWS_CLOUDFRONT="UPPERCASE"
AWS: セキュリティ・アクセスの設定
ステップ 3 では、以下のことができるユーザーを作成する必要があります:
- バケット・コンテンツを更新する
- CloudFront ディストリビューションを無効にする(変更をより早くユーザーに伝えられます)
NOTE: 2x
example.com
を以下の S3 バケット名に置き換えてください。このポリシーは指定したバケットへのプッシュを許可し、CloudFront ディストリビューションを無効にします。
{
"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_ACCESS_KEY_ID="key"
- AWS_SECRET_ACCESS_KEY="secret"
ラップトップ: プロジェクトのビルドスクリプトの設定
4.1) deploy.sh
スクリプトを作成してください。オプションの nvm(node バージョンマネージャー) を参照してください。
#!/bin/bash
export AWS_ACCESS_KEY_ID="key"
export AWS_SECRET_ACCESS_KEY="secret"
export AWS_BUCKET_NAME="example.com"
export AWS_CLOUDFRONT="UPPERCASE"
# nvm(node バージョンマネージャー)の読み込み、node のインストール(.nvmrc でのバージョン)、そして npm でのパッケージのインストールをします
[ -s "$HOME/.nvm/nvm.sh" ] && source "$HOME/.nvm/nvm.sh" && nvm use
# まだインストールされていない場合、Npm でインストールします
[ ! -d "node_modules" ] && npm install
npm run generate
gulp deploy
4.2) deploy.sh
を実行可能にして、Git をチェックしないようにします(deploy.sh にはシークレットがあります)
chmod +x deploy.sh
echo "
# Don't commit build files
node_modules
dist
.nuxt
.awspublish
deploy.sh
" >> .gitignore
4.3) プロジェクトとコマンドラインに Gulp を追加します
npm install --save-dev gulp gulp-awspublish gulp-cloudfront-invalidate-aws-publish concurrent-transform
npm install -g gulp
4.4) ビルドスクリプトで gulpfile.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 = {
// 必須
params: {
Bucket: process.env.AWS_BUCKET_NAME
},
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
signatureVersion: 'v3'
},
// 任意
deleteOldVersions: false, // NOT FOR 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 オプションを使用した新しいパブリッシャーの作成
// http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
const publisher = awspublish.create(config)
let g = gulp.src('./' + config.distDir + '/**')
// パプリッシャーは 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
})
4.5) デプロイとデバッグ
以下を実行してください:
./deploy.sh
以下のような出力が得られるはずです:
$ ./deploy.sh
Found '/home/michael/scm/example.com/www/.nvmrc' with version <8>
Now using node v8.11.2 (npm v5.6.0)
> [email protected] generate /home/michael/scm/example.com/www
> nuxt generate
nuxt:generate Generating... +0ms
nuxt:build App root: /home/michael/scm/example.com/www +0ms
nuxt:build Generating /home/michael/scm/example.com/www/.nuxt files... +0ms
nuxt:build Generating files... +36ms
nuxt:build Generating routes... +10ms
nuxt:build Building files... +24ms
████████████████████ 100%
Build completed in 7.009s
DONE Compiled successfully in 7013ms 21:25:22
Hash: 421d017116d2d95dd1e3
Version: webpack 3.12.0
Time: 7013ms
Asset Size Chunks Chunk Names
pages/index.ef923f795c1cecc9a444.js 10.6 kB 0 [emitted] pages/index
layouts/default.87a49937c330bdd31953.js 2.69 kB 1 [emitted] layouts/default
pages/our-values.f60c731d5c3081769fd9.js 3.03 kB 2 [emitted] pages/our-values
pages/join-us.835077c4e6b55ed1bba4.js 1.3 kB 3 [emitted] pages/join-us
pages/how.75f8cb5bc24e38bca3b3.js 2.59 kB 4 [emitted] pages/how
app.6dbffe6ac4383bd30a92.js 202 kB 5 [emitted] app
vendor.134043c361c9ad199c6d.js 6.31 kB 6 [emitted] vendor
manifest.421d017116d2d95dd1e3.js 1.59 kB 7 [emitted] manifest
+ 3 hidden assets
Hash: 9fd206f4b4e571e9571f
Version: webpack 3.12.0
Time: 2239ms
Asset Size Chunks Chunk Names
server-bundle.json 306 kB [emitted]
nuxt: Call generate:distRemoved hooks (1) +0ms
nuxt:generate Destination folder cleaned +10s
nuxt: Call generate:distCopied hooks (1) +8ms
nuxt:generate Static & build files copied +7ms
nuxt:render Rendering url /our-values +0ms
nuxt:render Rendering url /how +67ms
nuxt:render Rendering url /join-us +1ms
nuxt:render Rendering url / +0ms
nuxt: Call generate:page hooks (1) +913ms
nuxt: Call generate:page hooks (1) +205ms
nuxt: Call generate:page hooks (1) +329ms
nuxt: Call generate:page hooks (1) +361ms
nuxt:generate Generate file: /our-values/index.html +2s
nuxt:generate Generate file: /how/index.html +0ms
nuxt:generate Generate file: /join-us/index.html +0ms
nuxt:generate Generate file: /index.html +0ms
nuxt:render Rendering url / +2s
nuxt: Call generate:done hooks (1) +4ms
nuxt:generate HTML Files generated in 11.8s +5ms
nuxt:generate Generate done +0ms
[21:25:27] Using gulpfile ~/scm/example.com/www/gulpfile.js
[21:25:27] Starting 'deploy'...
Configured with CloudFront distribution
[21:25:27] [cache] README.md
[21:25:27] [cache] android-chrome-192x192.png
[21:25:27] [cache] android-chrome-512x512.png
[21:25:27] [cache] apple-touch-icon.png
[21:25:27] [cache] browserconfig.xml
[21:25:27] [cache] favicon-16x16.png
[21:25:27] [cache] favicon-32x32.png
[21:25:27] [cache] favicon.ico
[21:25:27] [cache] favicon.svg
[21:25:27] [cache] logo-branches.svg
[21:25:27] [cache] logo-small.svg
[21:25:27] [cache] logo.svg
[21:25:27] [cache] mstile-150x150.png
[21:25:27] [cache] og-image.jpg
[21:25:27] [cache] safari-pinned-tab.svg
[21:25:27] [cache] site.webmanifest
[21:25:28] [create] _nuxt/manifest.421d017116d2d95dd1e3.js
[21:25:29] [update] 200.html
[21:25:30] [create] videos/flag.jpg
[21:25:30] [create] _nuxt/vendor.134043c361c9ad199c6d.js
[21:25:34] [create] videos/flag.mp4
[21:25:34] [cache] _nuxt/pages/how.75f8cb5bc24e38bca3b3.js
[21:25:34] [cache] _nuxt/pages/join-us.835077c4e6b55ed1bba4.js
[21:25:34] [cache] _nuxt/pages/our-values.f60c731d5c3081769fd9.js
[21:25:36] [update] our-values/index.html
[21:25:36] [create] _nuxt/layouts/default.87a49937c330bdd31953.js
[21:25:36] [create] _nuxt/app.6dbffe6ac4383bd30a92.js
[21:25:37] [create] _nuxt/pages/index.ef923f795c1cecc9a444.js
[21:25:38] [update] join-us/index.html
[21:25:38] [update] how/index.html
[21:25:43] [create] videos/flag.webm
[21:25:43] [update] index.html
[21:25:43] CloudFront invalidation created: I16NXXXXX4JDOA
[21:26:09] Finished 'deploy' after 42 s
また CloudFront invalidation created: XXXX
は CloudFront invalidation の npm パッケージからの唯一の出力です。それが確認できない場合、上手く働いていません。