Using AWS SDK for JavaScript v3 in Browser
When developing Web applications using AWS, the best practice is to use the AWS SDK for JavaScript.
The SDK is available in two versions: v2 and v3.
In this article, we will review how to develop a web app using AWS SDK for JavaScript v3.
Environment
Create an S3 bucket and enable the static website hosting feature. Prepare content by placing HTML files inside.
Obtain credentials to access AWS resources from a browser script in the Cognito ID Pool. This time, grant permission to invoke Lambda.
The code to be executed by the Lambda function, but we will choose Python 3.8 and assume it returns the current date.
CloudFormation template files
The above configuration is built with CloudFormation.
The following URL contains the CloudFormation template, browser scripts, etc.
https://github.com/awstut-an-r/awstut-fa/tree/main/034
Browser Script Creation Procedure
Refer to the following official AWS page for creation.
https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html
https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/webpack.html
Installation and initialization of npm
To develop web applications using AWS SDK for JavaScript v3, npm must be installed.
Please refer to the following page for the installation procedure.
https://docs.npmjs.com/downloading-and-installing-node-js-and-npm
After installation is complete, initialization process is executed.
$ 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)
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 is now created.
Webpack installation and configuration
Webpack is required to use AWS SDK for JavaScript v3 from a browser script.
Install the two packages from npm.
$ npm install --save-dev webpack
...
+ webpack@5.70.0
...
$ npm install --save-dev path-browserify
...
+ path-browserify@1.0.1
...
Code language: Bash (bash)
Create the webpack.config.js file to configure Webpack.
The following is the content of 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)
Also modify the package.json file.
{
"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)
Installing SDK for JavaScript
In v3, the SDK is divided into multiple packages, and only the necessary ones are installed using npm.
In this case, we will deal with Cognito and Lambda, so we will install a total of 4 packages.
$ 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)
Browser Script Creation
Write code in browser.js as specified in webpack.config.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)
The purpose of this article is to provide an overview of the development method, so a detailed explanation of the code is omitted.
Load the necessary classes and functions from the packages already installed with import.
Create a Cognito ID pool and a client object for Lambda. Execute a Lambda function using them, define a function (showLambdaResult) to embed the retrieved string in HTML, and register it in the windows object.
Once the file is complete, build it.
$ 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)
If the build completes successfully, main.js is created. This is also as configured in webpack.config.js.
HTML file creation
Finally, we also create the HTML files that users will access.
<!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)
A simple HTML file.
Execute the function we defined earlier (showLambdaResult).
(Reference) CloudFormation template files
The purpose of this article is to provide an overview of the development method, so a detailed explanation of the template file is omitted.
S3 static website hosting capabilities
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)
The key point is the static website hosting feature.
Please see the following page for details.
Inline definition of code to be executed by Lambda functions
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)
The ZipFile property allows the code to be defined inline. This time, the current date is returned.
See the following page for more details.
Creating credentials in 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 can be used to generate credentials to access AWS resources.
For more information, please see the following page.
Architecting
Use CloudFormation to build this environment and check its actual behavior.
Create CloudFormation stacks and check resources in stacks
Create a CloudFormation stacks.
For information on how to create stacks and check each stack, please refer to the following pages.
After checking the resources in each stack, information on the main resources created in this case is as follows.
- Bucket name: fa-034
- Cognito ID pool: ap-northeast-1:f78ed244-a960-481d-b20d-54649660f668
- Lambda function name: fa-034-function
Place HTML file/script in S3 bucket
Place 2 files from AWS CLI.
$ 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)
Verification of Operation
Now that you are ready, access the HTML file.
For this configuration, the URL is as follows
http://fa-034.s3-website-ap-northeast-1.amazonaws.com/
The current date was returned.
From the above, we were able to execute Lambda using the AWS SDK for JavaScript v3.
Summary
We have reviewed how to develop a web application using AWS SDK for JavaScript v3.