はじめに
こんにちは!
CI事業部ソリューション開発セクションの古賀です。
CloudFront Hosting Toolkitは以下の構成の
フロントエンドのホスティングとCI/CDパイプラインを簡単に構築できる強力なツールです。
標準でサポートされているフレームワークには、ReactやVue.jsなどがありますが
これら以外のフレームワークを使用したい場合もあるでしょう。
今回はCloudFront Hosting Toolkitの基本的な使用方法と
標準でサポートされていないフレームワークを使用する方法を紹介します。
事前準備
以下のツールをインストールして、設定しておく必要があります。
- Node.js 18+
- AWS CLI v2(プロファイルを設定しておく)
※CloudFront Hosting Toolkitにはプロファイルを渡せない
- CloudFront Hosting Toolkit
npm install -g @aws/cloudfront-hosting-toolkit
※グローバルインストールする
- アプリのソースをgithubにあげておく。
基本的な流れ
設定ファイルの準備
cloudfront-hosting-toolkit init
使用するgithubリポジトリ、ブランチ、フレームワーク
ドメイン(オプション)を設定します。
. └── cloudfront-hosting-toolkit ├── cloudfront-hosting-toolkit-build.yml ├── cloudfront-hosting-toolkit-cff.js └── cloudfront-hosting-toolkit-config.json
cloudfront-hosting-toolkitフォルダと、その配下に設定ファイルが作成されます。
ファイル名 | 内容 |
cloudfront-hosting-toolkit-build.yml | CodeBuildのbuildspec.yml |
cloudfront-hosting-toolkit-cff.js | CloudFront Functionsの関数コード |
cloudfront-hosting-toolkit-config.json | `cloudfront-hosting-toolkit init`で設定した内容 |
デプロイ
cloudfront-hosting-toolkit deploy
1.に記載のURLを開き、保留中となっている接続を設定します。
設定したらターミナルでokを入力して待ちます。
数分後にデプロイが完了します。
削除
デプロイで作成したリソースを削除します
cloudfront-hosting-toolkit delete
標準でサポートしていないフレームワークを使用する
標準では以下のフレームワークとフレームワークなしをサポートしています。
React.js Next.jx Angular.js Vue.js Astro
Next.jsはサポートしているのに、Nuxt.jsはサポートしていないので
Nuxt.jsを使ってデプロイしてみます。
Nuxt.jsのソースを準備する
以下のコマンドでNuxt.jsのプロジェクトを作成します。
npx nuxi@latest init nuxt-app
SSGを行うために、nuxt.config.tsにssr: false,
を追記します。
Cloudfront Hosting Toolkitを設定する
以下のコマンドでグローバルインストールしたnpmパッケージが配置される
ディレクトリを確認します。
npm root -g
出力例
/home/vscode/.nvm/versions/node/v20.17.0/lib/node_modules
この出力例の場合だとcloudfront-hosting-toolkitは
/home/vscode/.nvm/versions/node/v20.17.0/lib/node_modules/@aws
にあります。
cloudfront-hosting-toolkit/resources ├── build_config_templates │ ├── hosting_angularjs.yml │ ├── hosting_basic.yml │ ├── hosting_nextjs.yml │ ├── hosting_reactjs.yml │ ├── hosting_vuejs.yml │ └── s3_build_config.yml ├── cff_templates │ ├── index_angularjs.js │ ├── index_basic.js │ ├── index_nextjs.js │ ├── index_reactjs.js │ └── index_vuejs.js ...
resources/build_config_templates配下にhosting_[フレームワーク名].ymlを作成します。
今回はhosting_nuxtjs.ymlを作成します。
hosting_Nuxtjs.yml
version: 0.2 phases: build: commands: - npx npm install - npx npm run generate - cd dist - echo aws s3 cp ./ s3://$DEST_BUCKET_NAME/$CODEBUILD_RESOLVED_SOURCE_VERSION/ --recursive #don't change this line - aws s3 cp ./ s3://$DEST_BUCKET_NAME/$CODEBUILD_RESOLVED_SOURCE_VERSION/ --recursive #don't change this line
resources/cff_templates配下にindex_[フレームワーク名].jsを作成します。
今回はindex_nuxtjs.jsを作成します。
index_Nuxtjs.js
import cf from 'cloudfront'; const kvsId = '__KVS_ID__'; // This fails if the key value store is not associated with the function const kvsHandle = cf.kvs(kvsId); function pointsToFile(uri) { return /\/[^/]+\.[^/]+$/.test(uri); } var rulePatterns = { "/$": "/index.html", // When URI ends with a '/', append 'index.html' "!file": ".html", // When URI doesn't point to a specific file and doesn't have a trailing slash, append '.html' "!file/": "/index.html",// When URI has a trailing slash and doesn't point to a specific file, append 'index.html' }; // Function to determine rule and update the URI async function updateURI(uri) { let pathToAdd = ""; try { pathToAdd = await kvsHandle.get("path"); } catch (err) { console.log(`No key 'path' present : ${err}`); return uri; } // Check for trailing slash and apply rule. if (uri.endsWith("/") && rulePatterns["/$"]) { return "/" + pathToAdd + uri.slice(0, -1) + rulePatterns["/$"]; } // Check if URI doesn't point to a specific file. if (!pointsToFile(uri)) { // If URI doesn't have a trailing slash, apply rule. if (!uri.endsWith("/") && rulePatterns["!file"]) { return "/" + pathToAdd + uri + rulePatterns["!file"]; } // If URI has a trailing slash, apply rule. if (uri.endsWith("/") && rulePatterns["!file/"]) { return "/" + pathToAdd + uri.slice(0, -1) + rulePatterns["!file/"]; } } return "/" + pathToAdd + uri; } // Main CloudFront handler async function handler(event) { var request = event.request; var uri = request.uri; //console.log("URI BEFORE: " + request.uri); // Uncomment if needed request.uri = await updateURI(uri); //console.log("URI AFTER: " + request.uri); // Uncomment if needed return request; }
2つのファイル作成後にcloudfront-hosting-toolkit init
を行うとフレームワークを選択する部分で
nuxtjsが表示されるようになります。
今回追加したNuxt.jsだけnuxtjsと表示される原因として
標準でサポートしているフレームワークは
@aws/cloudfront-hosting-toolkit/bin/cli/shared/constants.js内で
以下の定数が定義されていました。
exports.FRAMEWORKS = { reactjs: "React Framework", nextjs: "Next.js Framework", angularjs: "AngularJS Framework", vuejs: "Vue.js Framework", astro: "Astro Framework", basic: "No FrontEnd framework used; Basic implementation (no build required)", };
Nuxt.jsも追記すると、他のフレームワークと同様に表示されます。
exports.FRAMEWORKS = { reactjs: "React Framework", nextjs: "Next.js Framework", angularjs: "AngularJS Framework", vuejs: "Vue.js Framework", nuxtjs: "Nuxt.js Framework", astro: "Astro Framework", basic: "No FrontEnd framework used; Basic implementation (no build required)", };
以降は基本的な流れと同じ手順でデプロイができます。
おまけ
v13.3以降のNext.jsをデプロイする際の注意点
cloudfront-hosting-toolkit v1.1.7では
hosting_nextjs.ymlは以下の内容となっています。
hosting_nextjs.yml
version: 0.2 phases: build: commands: - n install 18.17.0 - npx npm install - npx next build - npx next export - cd out - echo aws s3 cp ./ s3://$DEST_BUCKET_NAME/$CODEBUILD_RESOLVED_SOURCE_VERSION/ --recursive #don't change this line - aws s3 cp ./ s3://$DEST_BUCKET_NAME/$CODEBUILD_RESOLVED_SOURCE_VERSION/ --recursive #don't change this line
Next.jsのv13.3以降ではStatic exportの方法がnpx next export
を実行する方法から
next.config.jsでoutput: 'export'
を指定する方法に変更となっています。
そのため、Next.jsのv13.3以降を使用する場合では以下の2点の対応が必要です。
- next.config.jsに
output: 'export'
を記載します。 -
build_config_templates/hosting_nextjs.ymlから
npx next export
を削除してcloudfront-hosting-toolkit init
を実行する
または、cloudfront-hosting-toolkit init
実行後にcloudfront-hosting-toolkit-build.ymlから- npx next export
を削除する