Share on facebook
Share on twitter
Share on linkedin

5 new Amplify features to take your app to any scale

Michael Liendo
Michael Liendo

Just before re:Invent 2021, AWS launched a set of features for Amplify that both simplify and enhance how customers build their applications while both prototyping and deploying to production. In this post, Michael Liendo (Senior Developer Advocate at AWS Amplify), talks about five of those features to better understand their use cases and how to get started!


Save 40% on ACG!
Looking to get AWS certified or level up your cloud career? Learn by doing with ACG’s hands-on courses, labs, learning paths, and sandbox software.


What is AWS Amplify?

AWS Amplify is a suite of tools aimed at front-end developers wanting to create full stack applications on AWS. Using its CLI, customers can use terminal prompts to automate writing their application’s backend.

The Amplify libraries and pre-built components allow for a seamless frontend-to-backend solution, and applications can be hosted on Amplify Hosting with a few clicks.

Lastly, customers can ideate on their data models in our Admin UI without even having to have an AWS account.

The best part is that the suite of products integrate with one another so that they can be used as a whole, or as a single offering, depending on the needs of your team.

Here are five new Amplify features to help take your app to any scale.

1. Override Amplify generated resources

Many customers love that Amplify generates default configurations when adding resources like Cognito user or identity pools, or S3 buckets. However, we understand that organizations can have different compliance and governing standards. For that reason, we introduced a new command to the CLI: amplify override <category>.

This takes in the specified category and creates a TypeScript file where the resource can then be accessed and reconfigured to your needs. Common scenarios we’ve heard from our customers include enabling a TTL on an AWS DynamoDB table items, and setting an existing function as the trigger to migrate Amazon Cognito users from one user pool to another.

In the case a user were to type amplify override storage, with a few lines, bucket versioning can be enabled.

import { AmplifyS3ResourceTemplate } from '@aws-amplify/cli-extensibility-helper'

export function override(resources: AmplifyS3ResourceTemplate) {
    resources.s3Bucket.versioningConfiguration = {
        status: 'Enabled',
    }
}

It’s worth pointing out that the new @aws-amplify/cli-extensibility-helper module seen in the above code snippet is automatically installed and the proper import statement is automatically handled by the CLI.

2. Add custom resources with the AWS CDK

Out of the box, Amplify supports adding AWS services such as AppSync, Lambda, S3, Cognito, Fargate, API Gateway, Amazon Location maps, and more all through its CLI. However, customers often want to add other services depending on the application they’re building and the requirements to build it.

Fortunately, instead of adding all 175+ services to our CLI, we instead introduced a new command: amplify add custom

This command supports resources created via the AWS CDK (TypeScript) and AWS CloudFormation.

Now, the simplicity of the Amplify ecosystem and the vastness of the AWS ecosystem to come together in a single project.

The below code snippet shows how an SNS topic can be created with a name that includes both the project name, and the Amplify environment.

import * as cdk from '@aws-cdk/core';
import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper';
import * as sns from '@aws-cdk/aws-sns';
import * as subs from '@aws-cdk/aws-sns-subscriptions';

export class cdkStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) {
    super(scope, id, props);

    /* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */
    new cdk.CfnParameter(this, 'env', {
      type: 'String',
      description: 'Current Amplify CLI env name',
    });

    const projectName = AmplifyHelpers.getProjectInfo().projectName;

    const topic = new sns.Topic(this, 'sns-topic', {
      topicName: `sns-topic-${projectName}-${cdk.Fn.ref('env')}`
    });

    topic.addSubscription(new subs.EmailSubscription("<your-email-address>"));
  }
}

Pro tip: Combine custom resources with custom IAM policies for Lambda!

3. Lambda and container support for custom IAM policies

Amplify natively supports the creation of both Lambda functions, and Fargate containers via its CLI. Often times, customers will need to integrate preexisting resources, created outside of the Amplify ecosystem. For this reason, we now generate a custom-policies.json file whenever a Lambda or container is created:

[
{"Action": ["s3:CreateBucket"],"Resource": ["arn:aws:s3:::${env}my-bucket"]},

{``"Action"``:`` ``[``"iam:GetPolicy"``]``,``"Resource"``:`` ``[``"arn:aws:iam:::policy/*"``]``}
]

This simple file takes in array of policies and automatically applies them to the execution role of the corresponding function or container.

It’s worth pointing out that while the Effect is allow by default, policies can be set to deny as well. In addition, note that wildcards are supported as well as adding in the current Amplify environment, which is handy for multi-environment scenarios.

4. Custom command hooks

Whether it is ensuring a specific version of the Amplify CLI is used, or wanting to send out a slack notification to your team when a build succeeds or fails, custom command hooksare the solution.

When initializing a new Amplify project, we now generate an amplify/hooks directory. In this directory, the filenames take a “when-what” approach. For example, a file named pre-push.js will run before a project is pushed up to AWS. Additionally, a file named post-add-function.js will run after a function has been successfully added to a project using the amplify add function command.

Revisiting the use case of wanting to enforce a specific version of Amplify, the code to do so would look like this:

const fs = require('fs');
const parameters = JSON.parse(fs.readFileSync(0, { encoding: 'utf8' }));

// Get the running Amplify CLI major version number
const currentCLIMajorVersion = parameters.data.amplify.version.split('.')[0]
console.log('Amplify CLI major version: ', currentCLIMajorVersion)

const MINIMUM_MAJOR_AMPLIFY_CLI_VERSION = 5
console.log('Minimum required Amplify CLI major version: ', MINIMUM_MAJOR_AMPLIFY_CLI_VERSION)

if (currentCLIMajorVersion < MINIMUM_MAJOR_AMPLIFY_CLI_VERSION) {
  // Non-zero exit code will stop the Amplify CLI command's execution
  console.log('Minimum CLI version requirement not met.')
  process.exit(1) 
} else {
  console.log('Minimum CLI version requirement met.')
  process.exit(0) 
}

It’s worth noting that in addition to JavaScript, build hooks also support shell scripts by default, and custom scripting runtimes like python can be enabled as well!

5. Export your Amplify backend as a CDK stack

Our last item on the list!

This feature allows for the utmost flexibility, but I’ll add that it is advanced and was created with a particular customer in mind. So while most customers will never need this ability, it further strengthens the position that Amplify can be used for production applications.

amplify export

By running this command, the Amplify CLI will export your entire Amplify backend as a CDK stack. This can then be brought into an existing CDK pipeline, and deployed alongside the rest of your infrastructure.

Note that this is not ejecting out of Amplify. This command can be ran many times while an Amplify project is being iterated on.

Exporting an Amplify project is simple, though let’s see what it looks like to integrate the generated stack into an existing pipeline by looking at a sample stage:

import { CfnOutput, cfnTagToCloudFormation, Construct, Stage, StageProps } from '@aws-cdk/core';
import { AmplifyExportedBackend } from '@aws-amplify/cdk-exported-backend';
import * as path from 'path'
import * as cdk from '@aws-cdk/core'

export class AmplifyStage extends Stage {

  constructor(scope: Construct, id: string, props?: StageProps) {
    super(scope, id, props);

    // ADD AMPLIFY EXPORTED BACKEND STACK HERE
    const amplifyStack = new AmplifyExportedBackend(this, "amplifyexportedbackend", {
      path: path.resolve(__dirname, '..', 'amplify-export-mytodoapp'),
      amplifyEnvironment: "dev"
    })
  }
}

This should look familiar to CDK developers if they’ve deployed a pipeline before. Note that the @aws-amplify/cdk-exported-backend package handles the necessary bindings.

More details can be found on the documentation page.


Conclusion

In this post we looked at the newly released features that allow Amplify applications to be more extensible. This is in addition to features such as the ability to import existing resources into your Amplify project.

Now, not only do customers have finer-grained control with features like custom build hooks, but the ability to override and add resources mean less time in the AWS Console, and more time focusing on building out your product.

For more information on AWS Amplify visit our docs page, and to stay up to date with me, you can follow me on Twitter.

About the author

Michael Liendo is a Senior Developer Advocate @ AWS Amplify. You can follow him on Twitter @mtliendo.


Keep up with all things cloud by following A Cloud Guru on Twitter and Facebooksubscribe to A Cloud Guru on YouTube for weekly updates, and join the conversation on Discord. You can also check out our current crop of free courses!

Recommended

Get more insights, news, and assorted awesomeness around all things cloud learning.

Sign In
Welcome Back!

Psst…this one if you’ve been moved to ACG!

Get Started
Who’s going to be learning?