背景・目的
Webアプリケーションの調査および検証をする機会があり、簡単に作成できる仕組みがAWSにあるか調べてみたところAmplifyがあったので試してみます。
まとめ
Amplifyは、フロントエンド開発を構築するツールです。
利用することで、簡単にバックエンドと通信でき素早くデプロイできる機能を有しています。
また、SPAフレームワークや、SSGをサポートすることで、最新のWebアプリケーション開発にも対応されています。
概要
Amplifyとは?
フロントエンジニアがAWSでフルスタックアプリケーションを素早く構築する専用ツールと機能です。
Amplifyでは、以下のサービスを提供しています。
- Amplify Hosting
- Amplify Studio
Amplify Hostingでは、CI/CDでフルスタックサーバレスウェブアプリをホストするためのgitベースのワークフローを提供しているとのことです。
Amplify Hostingの機能
以下の機能を有します。
- SPAフレームワークのサポート。以下に例を記載します。
- React
- Angular
- Vue.js
- lonic
- Ember
- 静的サイトジェネレータのサポート。以下に例を記載します。
- Gatsby
- Eleventy
- Hugo
- VuePress
- Jekyll
- 新しいブランチで、フロントエンドとバックエンドの本番環境と、ステージング環境を管理する
- アプリケーションをカスタムドメインに接続する
- Next.jsを使用して作成されたSSR Webアプリケーションをデプロイし、ホストする。
- エンドツーエンドのテストで、アプリの品質を向上させる。
- Webアプリをパスワード保護し、新しい機能を一般公開せずに作業可能にする。
- リライトとリダイレクトにより、SEOランキングを維持し、クライアントアプリの要件に基づいてトラフィックをルーティングする。
- インスタントキャッシュの無効化により、コードがコミットされる都度アプリが即時に更新される。
- アトミックデプロイは、デプロイ全体が終了した後にのみWebアプリが更新されるようにすることで、メンテンナンスウィンドウを排除する。これによりファイルが正しくアップロードされないシナリオが排除される。
- 様々なモバイルデバイスでレンダリングされたアプリのスクショをとり、レイアウトの問題を特定する。
私が理解していないSPAと、静的サイトジェネレータについては、簡単に調べたので以降に記載します。
SPAとは?
- Single Page Application(SPA)のこと。
Wikipediaの「シングルページアプリケーション」の説明によると、以下の記載がありました。
シングルページアプリケーション(英: single-page application、SPA)とは、単一のWebページのみから構成することで、デスクトップアプリケーションのようなユーザ体験を提供するWebアプリケーションまたはWebサイトである。必要なコード(HTML、JavaScript、CSS)は最初にまとめて読み込むか[1]、ユーザの操作などに応じて動的にサーバと通信し、必要なものだけ読み込みを行う。
単一のWebページから構成され、デスクトップアプリのようなUXを提供する。とのことです。
また、AWSのページにも記載がありました。
Modern SPA web applications
This user guide is intended for customers who have a basic understanding of modern single-page web applications (SPA). Modern web applications are constructed as SPAs that package all application components into static files. Traditional client-server web architectures led to poor experiences; every button click or search required a round trip to the server, re-rendering the entire application. Modern web apps offer a native app-like user experience by serving the app frontend, or user interface, efficiently to browsers as prebuilt HTML/JavaScript files that can then invoke backend functionality without reloading the page.
最新のWebアプリケーションは、全てのアプリケーションコンポーネントを静的ファイルにパッケージ化するSPAとして構築されています。
従来のクライアントサーバWebアーキテクチャでは、ボタンのクリックや検索する度にサーバへのリクエストが発生し、アプリケーション全体が読み込まれていた。
最新のWebアプリケーションでは、ページをリロードせずにバックエンドを呼び出すことができるビルド済みHTML/JSファイルにより、ネイティブアプリのようなUXを提供しています。
静的サイトジェネレータとは?
- Static Site Generator(SSG)のこと。
こちらの記事によると、以下の記載がありました。
静的サイトジェネレータ (Static Site Generator = SSG) は、入力ファイルから静的ページを構築するためのツールです。コンテンツ(ヘッドレスCMSなど)を取り込み、選択したテンプレートを適用して、静的なHTMLページを生成します。
コンテンツを用意しておいて、予め用意されたテンプレートを元にHTMLを生成するツールとのことです。
また、対局にあるものとして、動的WebサイトのWordPressがあり、WordPressの場合は、ユーザリクエストの際にページを構築するようです。SSGの場合、既に構築したページがCDNに保存されていて、ユーザリクエスト時にダウンロードするので、レイテンシに違いが出るとのことです。
実践
- AWSの「基本的なウェブアプリケーションを構築する」を参考に環境を構築したいと思います。
1.Webアプリケーション
コードの準備
- 以下のコードを,index.htmlファイルとして保存し、zip圧縮します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
Hello World
</body>
</html>
Amplifyトップページ
- Amplifyのマネコンで「使用を開始する」をクリックします。

- ウェブアプリケーションをホストで「使用を開始する」をクリックします。

デプロイ
- 「Gitプロバイダーなしでデプロイ」を選択し、「続行」をクリックします。

- 以下を入力し、保存してデプロイをクリックします。
- アプリケーションの名前:GettingStarted
- 環境名:dev
- 方法:ドラッグアンドドロップ
- ファイルは、index.html.zipを選択。(コードの準備で作成し、zip圧縮したもの。)

- しばらくするとデプロイが完了します。

確認
2.サーバレス関数を作成する
Lambdaトップページ
コード
- 以下のコードを貼り付けて、「Deploy」をクリックします。
# import the JSON utility package since we will be working with a JSON object
import json
# define the handler function that the Lambda service will use an entry point
def lambda_handler(event, context):
# extract values from the event object we got from the Lambda service
name = event['firstName'] +' '+ event['lastName']
# return a properly formatted JSON object
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda, ' + name)
}
確認
- Testボタンをクリックします。
- 以下を入力し、「保存」をクリックします。
- イベント名:HelloWorldTestEvent
- イベントJSONに以下を入力
{
"firstName": "Ada",
"lastName": "Lovelace"
}
- Testボタンをクリックし、以下が表示されました。
- 上記で作成したLambdaは、firstNameとlastNameから値を取得し、JSONフォーマットのbody属性に埋め込むコードでした。
- 結果を見ると、HelloWorldTestEventで引数に渡した、AdaとLovelaceが表示されてるので成功ですね。
Test Event Name
HelloWorldTestEvent
Response
{
"statusCode": 200,
"body": "\"Hello from Lambda, Ada Lovelace\""
}
Function Logs
START RequestId: 614a7680-a599-475a-9379-7f7ba35e702f Version: $LATEST
END RequestId: 614a7680-a599-475a-9379-7f7ba35e702f
REPORT RequestId: 614a7680-a599-475a-9379-7f7ba35e702f Duration: 1.38 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used: 37 MB Init Duration: 138.99 ms
Request ID
614a7680-a599-475a-9379-7f7ba35e702f
3.サーバーレス関数をウェブアプリケーションにリンクする
- API Gatewayを作成し、Lambda関数とつなぎます。
新しいREST APIを作成
-
以下を入力し、「APIの作成」をクリックします。
新しいリソースとメソッドを作成
-
以下を入力し、保存をクリックします。
-
「API Gateway に、Lambda 関数を呼び出す権限を与えようとしています:」と表示されるので、OKをクリックします。
-
POSTメソッドを選択した状態で、アクション>CORSの有効化をクリックします。

- メソッドにPOSTが選択されていることを確認し、「CORSを有効にして既存のCORSヘッダーを置換」をクリックします。
Access-Control-Allow-Originについて
今回のWebアプリケーションでは、Amplifyにデプロイした静的コンテンツから、ボタンをクリックした際にJavaScriptが実行され、API Gatewayにリクエストされます。
デフォルトのままで動かすと、AmplifyにデプロイしたドメインとAPI Gatewayのドメインが異なるため、ブラウザの制限で動作しません。
そのため、CORS(Cross-origin Resource Sharing)を有効にし、動作させます。
以下のキャプチャでは、Access-Control-Allow-OriginがXXXXXXXとなっていますが、実際にはAmplifyのオリジンを指定しています。

- メソッド変更の確認で「はい、既存の値を置き換えます」をクリックします。
APIのデプロイ

- 「変更を保存」をクリックします。
APIの検証
- ナビゲーションペインの「リソース」をクリックします。

- POSTをクリックし、テストをクリックします。

- 以下をリクエスト本文フィールドに貼り付けて、テストをクリックします。
{
"firstName":"Grace",
"lastName":"Hopper"
}
-
リクエスト本文に設定したfirstNameとlastNameがレスポンスに表示されました。
-
レスポンスヘッダーにも設定した値が反映されていました。
4.データテーブルを作成
今回は、Amplifyの挙動を確認するだけなので、DynamoDBの作成は省略しています。
5.ウェブアプリケーションに対話性を追加
- Amplifyでデプロイしたhtmlから、API Gatewayをつなぎます。
コードの修正
- 以下のコードをindex.htmlに貼り付け、41行目のYOUR-API-INVOKE-URLをAPI Gatewayのオリジンに置き換えます。また、同様にZip圧縮します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<!-- Add some CSS to change client UI -->
<style>
body {
background-color: #232F3E;
}
label, button {
color: #FF9900;
font-family: Arial, Helvetica, sans-serif;
font-size: 20px;
margin-left: 40px;
}
input {
color: #232F3E;
font-family: Arial, Helvetica, sans-serif;
font-size: 20px;
margin-left: 20px;
}
</style>
<script>
// define the callAPI function that takes a first name and last name as parameters
var callAPI = (firstName,lastName)=>{
// instantiate a headers object
var myHeaders = new Headers();
// add content type header to object
myHeaders.append("Content-Type", "application/json");
// using built in JSON utility package turn object to string and store in a variable
var raw = JSON.stringify({"firstName":firstName,"lastName":lastName});
// create a JSON object with parameters for API call and store in a variable
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
// make API call with parameters and use promises to get response
fetch("YOUR-API-INVOKE-URL", requestOptions)
.then(response => response.text())
.then(result => alert(JSON.parse(result).body))
.catch(error => console.log('error', error));
}
</script>
</head>
<body>
<form>
<label>First Name :</label>
<input type="text" id="fName">
<label>Last Name :</label>
<input type="text" id="lName">
<!-- set button onClick method to call function we defined passing input values as parameters -->
<button type="button" onclick="callAPI(document.getElementById('fName').value,document.getElementById('lName').value)">Call API</button>
</form>
</body>
</html>
- Amplifyのマネコンで、先ほど作成したウェブアプリケーションを選択して、zipファイルを置き換えます。

ウェブアプリケーションをテスト
- リクエストし、画面を表示する。FirstNameとLastNameに適当に文字列を入れて、Call APIをクリックする。

考察
- Amplifyにより、簡単に静的コンテンツがデプロイできバックエンド(API Gateway、Lambda)と通信ができました。他にも多くの機能やGithubと連携したデプロイなど試せてないので今後、確認したいと考えています。
参考