ブラウザでAWS SDK for JavaScript v3を扱う
AWSを使用してWebアプリを開発する場合、AWS SDK for JavaScriptの使用がベストプラクティスとなります。
同SDKには2つのバージョンがあります。v2とv3です。
今回はAWS SDK for JavaScript v3を使用して、Webアプリを開発する方法を確認します。
構築する環境
S3バケットを作成し、静的ウェブサイトホスティング機能を有効にします。内部にHTMLファイルを設置して、コンテンツを用意します。
Cognito IDプールで、ブラウザスクリプトからAWSリソースへアクセスするためのクリデンシャルを取得します。今回はLambdaを実行する権限を付与します。
Lambda関数で実行するコードですが、Python3.8を選択し、現在の日付を返すものとします。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLに、CloudFormationテンプレートに加え、ブラウザスクリプト等を配置してます。
https://github.com/awstut-an-r/awstut-fa/tree/main/034
ブラウザスクリプトの作成手順
以下のAWS公式ページを参考にして作成します。
https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v3/developer-guide/welcome.html
https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v3/developer-guide/webpack.html
npmのインストール・初期化
AWS SDK for JavaScript v3を使用してWebアプリを開発する場合、npmのインストールが必要となります。
インストール手順は、以下のページをご確認ください。
https://docs.npmjs.com/downloading-and-installing-node-js-and-npm
インストール完了後、初期化処理を実行します。
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
...
Press ^C at any time to quit.
package name: (034)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
<meta charset="utf-8">About to write to /path/to/your/directory/package.json:
{
"name": "034",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this OK? (yes)
Code language: Bash (bash)
これでpackage.jsonが作成されました。
Webpackインストール・設定
ブラウザスクリプトからAWS SDK for JavaScript v3を使用する場合、Webpackが必要です。
npmから、2つのパッケージをインストールします。
$ npm install --save-dev webpack
...
+ webpack@5.70.0
...
$ npm install --save-dev path-browserify
...
+ path-browserify@1.0.1
...
Code language: Bash (bash)
webpack.config.jsファイルを作成して、Webpackの設定を行います。
以下がwebpack.config.jsの中身です。
var path = require("path");
module.exports = {
entry: [path.join(__dirname, "browser.js")],
output: {
path: __dirname,
filename: 'main.js'
},
resolve:{
fallback: { path: require.resolve("path-browserify")}
}
};
Code language: JavaScript (javascript)
package.jsonファイルの修正も行います。
{
"name": "034",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"path-browserify": "^1.0.1",
"webpack": "^5.70.0"
}
}
Code language: JSON / JSON with Comments (json)
Webpackでビルドするように設定します。
SDK for JavaScriptのインストール
v3の場合、SDKは複数のパッケージに分割されており、必要なものだけをnpmでインストールすることになります。
今回はCognito、Lambdaを扱いますので、合計4パッケージをインストールします。
$ npm install @aws-sdk/client-cognito-identity
...
+ @aws-sdk/client-cognito-identity@3.56.0
...
$ npm install @aws-sdk/credential-provider-cognito-identity
...
+ @aws-sdk/credential-provider-cognito-identity@3.56.0
...
$ npm install @aws-sdk/client-lambda
...
+ @aws-sdk/client-lambda@3.56.0
...
$ npm install @aws-sdk/util-utf8-browser
...
+ @aws-sdk/util-utf8-browser@3.55.0
...
Code language: Bash (bash)
ブラウザスクリプト作成
webpack.config.jsで指定した通り、browser.jsにコードを記載します。
import {
CognitoIdentityClient
} from "@aws-sdk/client-cognito-identity";
import {
fromCognitoIdentityPool
} from "@aws-sdk/credential-provider-cognito-identity";
import {
LambdaClient,
InvokeCommand
} from "@aws-sdk/client-lambda";
import {
toUtf8
} from "@aws-sdk/util-utf8-browser";
const REGION = "ap-northeast-1";
const IDENTITY_POOL_ID = "[ID of Cognito ID Pool]";
const FUNCTION_NAME = "[Lambda Function Name]";
const lambdaClient = new LambdaClient({
region: REGION,
credentials: fromCognitoIdentityPool({
client: new CognitoIdentityClient({ region: REGION }),
identityPoolId: IDENTITY_POOL_ID
}),
});
const showLambdaResult = async () => {
try {
const response = await lambdaClient.send(
new InvokeCommand({ FunctionName: FUNCTION_NAME })
);
document.getElementById("viewer").innerHTML = `<p>${toUtf8(response.Payload)}</p>`
} catch (err) {
console.log(err);
}
};
window.showLambdaResult = showLambdaResult;
Code language: JavaScript (javascript)
今回は開発方法の概要を確認することを目的としていますので、コードの詳細な解説は割愛します。
importでインストール済みのパッケージから、必要なクラスや関数を読み込みます。
Cognito IDプールとLambda用のクライアントオブジェクトを作成します。それらを使用してLambda関数を実行し、取得した文字列をHTMLに埋め込むように関数(showLambdaResult)を定義し、windowsオブジェクトに登録しておきます。
ファイルが完成したら、ビルドします。
$ npm run build
> 034@1.0.0 build /path/to/your/directory
> webpack
asset main.js 180 KiB [emitted] [minimized] (name: main) 1 related asset
...
Code language: Bash (bash)
ビルドが正常に完了すると、main.jsが作成されます。こちらもwebpack.config.jsで設定した通りです。
HTMLファイル作成
最後にユーザーがアクセスするHTMLファイルも作成します。
<!DOCTYPE html>
<html>
<head>
<title>fa-034</title>
</head>
<body>
<div id="viewer"></div>
<script type="text/javascript" src="./main.js"></script>
<script>
showLambdaResult();
</script>
</body>
</html>
Code language: HTML, XML (xml)
シンプルなHTMLファイルです。
先ほど定義した関数(showLambdaResult)を実行します。
(参考)CloudFormationテンプレートファイル
今回は開発方法の概要を確認することを目的としていますので、テンプレートファイルの詳細な解説は割愛します。
S3の静的ウェブサイトホスティング機能
Resources:
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref Prefix
PublicAccessBlockConfiguration:
BlockPublicAcls: false
BlockPublicPolicy: false
IgnorePublicAcls: false
RestrictPublicBuckets: false
WebsiteConfiguration:
IndexDocument: index.html
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Prefix
PolicyDocument:
Statement:
Action:
- s3:GetObject
Effect: Allow
Resource:
- !Sub "arn:aws:s3:::${Bucket}/*"
Principal: "*"
Code language: YAML (yaml)
ポイントは静的ウェブサイトホスティング機能です。
詳細は以下のページをご確認ください。
Lambda関数で実行するコードをインラインで定義
Resources:
Function:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${Prefix}-function"
Runtime: python3.8
Role: !GetAtt FunctionRole.Arn
Handler: index.lambda_handler
Code:
ZipFile: |
import datetime
def lambda_handler(event, context):
return str(datetime.date.today())
Code language: YAML (yaml)
ZipFileプロパティを使用することで、コードをインラインで定義することができます。今回は現在の日付を返します。
詳細は以下のページでご確認ください。
Cognitoでクリデンシャル作成
Resources:
IdentityPool:
Type: AWS::Cognito::IdentityPool
Properties:
AllowUnauthenticatedIdentities: true
IdentityPoolName: !Sub "${Prefix}-IdentityPool"
IdentityPoolRoleAttachment:
Type: AWS::Cognito::IdentityPoolRoleAttachment
Properties:
IdentityPoolId: !Ref IdentityPool
Roles:
unauthenticated: !GetAtt IdentityPoolAuthenticatedRole.Arn
IdentityPoolAuthenticatedRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRoleWithWebIdentity
Principal:
Federated: cognito-identity.amazonaws.com
Condition:
StringEquals:
cognito-identity.amazonaws.com:aud: !Ref IdentityPool
ForAnyValue:StringLike:
cognito-identity.amazonaws.com:amr: unauthenticated
Policies:
- PolicyName: IdentityPoolUnauthenticatedPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource:
- !Ref FunctionArn
Code language: YAML (yaml)
Cognitoを使用することで、AWSリソースにアクセスするためのクリデンシャルを生成することができます。
詳細は以下のページをご確認ください。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- バケット名:fa-034
- Cognito IDプール:ap-northeast-1:f78ed244-a960-481d-b20d-54649660f668
- Lambda関数名:fa-034-function
S3バケットにHTMLファイル・スクリプトを配置する
AWS CLIから2ファイルを配置します。
$ aws s3 cp index.html s3://fa-034
upload: ./index.html to s3://fa-034/index.html
$ aws s3 cp main.js s3://fa-034
upload: ./main.js to s3://fa-034/main.js
Code language: Bash (bash)
動作検証
準備が整いましたので、HTMLファイルにアクセスします。
今回の構成ですと、以下のURLとなります。
http://fa-034.s3-website-ap-northeast-1.amazonaws.com/
現在の日付が返ってきました。
以上のことから、AWS SDK for JavaScript v3を使用して、Lambdaを実行することができました。
まとめ
AWS SDK for JavaScript v3を使用して、Webアプリを開発する方法を確認しました。