AWS Developer Tools Blog

New AWS SDK for JavaScript – Developer Preview

We’re happy to announce the developer preview of the AWS SDK for JavaScript, version 3. This version of the SDK is a major rewrite of the 2.x code base. It’s written in TypeScript and adds frequently requested features, like modularized packages. Many aspects of the SDK have been refactored and cleaned up in addition to generating service client packages instead of hydrating services at SDK runtime. The developer preview is your chance to influence the direction of the new AWS SDK for JavaScript. Tell us what you like and what you don’t like. Your feedback matters to us. Find details on various ways to give feedback at the bottom of this post.

The new AWS SDK for JavaScript can run alongside the version 2.x SDK in the same package to allow partial migration to the new product. As we get close to general availability for version 3, we’ll share a more detailed plan on how we’ll support the 2.x line.

Getting started

Let’s walk through setting up a project with the SDK that depends on Amazon DynamoDB and makes a simple service call. The following steps use npm as an example. These steps assume that you have Node.js and npm already installed.

  1. Create a new Node.js project.
  2. Inside the project, run: npm install --save @aws-sdk/client-dynamodb-v2-node@preview
  3. Create a new file called index.js and create a DynamoDB service client.
    const {DynamoDB} = require('@aws-sdk/client-dynamodb-v2-node');
    async function example() {
      const client = new DynamoDB({region: 'us-west-2'});
    }
    example();
  4. Make a service request and do something with the response.
    try {
      const results = await client.listTables({});
      console.log(results.TableNames.join('\n');
    } catch (err) {
      console.error(err);
    }

New features

The AWS SDK for JavaScript, version 3, offers a variety of new features.

Modularized packages

The SDK is now split across multiple packages. The 2.x version of the SDK contained support for every service. This made it very easy to use multiple services in a project. Due to the limitations around reducing the size of the SDK when only using a handful of services or operations, many customers requested having separate packages for each service client.

We have also split up the core parts of the SDK so that service clients only pull in what they need. For example, a service that sends responses in JSON will no longer need to also have an XML parser as a dependency.

For those that were already importing services as submodules from the version 2.x SDK, the import statement doesn’t look too different. Here’s an example of importing the AWS Lambda service in version 2.0 of the SDK, and the developer preview:

// import the Lambda client constructor in version 2.0 of the SDK
const Lambda = require('aws-sdk/clients/lambda');

// import the Lambda client constructor in version 3.0 developer preview of the SDK for Node.js
const {Lambda} = require('@aws-sdk/client-lambda-node');

It is also possible to import both versions of the Lambda client by changing the variable name that stores the Lambda constructor.

Separate packages for browser and Node.js

In addition to publishing separate packages for each service client, each package has both a browser and Node.js version. In version 2.x of the SDK, we used special fields in package.json to enable writing code against the aws-sdk package for use in either browsers or Node.js. This has a few limitations. To import the SDK into a project, you must use build tools that know how to parse the browser field to get the browser version of the SDK. This causes problems in Electron apps, where the Node.js version of the SDK is wanted, but build tools are also being used to create a JavaScript bundle. This causes the browser version of the SDK to be used. For TypeScript support, this also required Node.js and dom typings to be present.

By publishing separate packages for Node.js and browser environments, we’ve removed the guesswork around which version your builds will use. This also allows us to use environment-specific typings. For example, streams are implemented with different interfaces in Node.js and browsers. Depending on which package you are using, the typings will reflect the streams for the environment you’ve chosen.

API changes

We’ve made several public API changes to improve consistency, make the SDK easier to use, and remove deprecated or confusing API calls. The following are some of the bigger changes included in the new AWS SDK for JavaScript developer preview.

Configuration

In version 2.x of the SDK, service configuration could be passed to individual client constructors. However, these configurations would first be merged automatically into a copy of the global SDK configuration: AWS.config. Also, calling AWS.config.update({/* params *}) only updates configuration for service clients that were instantiated after the update call was made, not any existing clients. This behavior was a frequent source of confusion and made it difficult to add configuration to the global object that only affects a subset of service clients in a forward-compatible way.

In the developer preview, there is no longer a global configuration managed by the SDK. Configuration must be passed to each service client that is instantiated. It is still possible to share the same configuration across multiple clients but that configuration is not automatically merged with a global state.

Middleware

Version 2.x of the SDK allows modifying a request throughout multiple stages of a request’s lifecycle by attaching event listeners to a request. Some feedback we received frequently was that it can be difficult to debug what went wrong during a request’s lifecycle.

We’ve now switched to using a middleware stack to control the lifecycle of an operation call. This gives us a few benefits: each middleware in the stack calls the next middleware after making any changes to the request object. This makes debugging issues in the stack much easier since you can see exactly which middleware was called leading up to an error. Here’s an example of adding a custom header using middleware:

lambda.middlewareStack.add(
  (next, context) => (args) => {
    args.request.headers['Custom-Header'] = 'value';
    return next(args);
  },
  {
    step: 'build'
  }
);

lambda.putObject(params);

In the above example, we’re adding a middleware to our AWS Lambda client’s middleware stack. The first argument is a function that accepts next, the next middleware in the stack to call, and context, an object that contains some information about the operation being called. It returns a function that accepts args, an object that contains the parameters that are passed to the operation and the request. It also returns the result from calling the next middleware with args.

Giving feedback and contributing

We appreciate both positive and negative feedback. While the SDK is in preview, you may encounter bugs. If you do, please feel free to open an issue on our GitHub repository. Our GitHub issues page also includes work that we know still needs to be done before exiting a preview state.

Feedback

GitHub issues. Customers who are comfortable giving public feedback can open a GitHub issue in the new repository. This is the preferred mechanism to give feedback so that other customers can engage in the conversation or add their +1 to issues. Issues that you open will be evaluated and included in our roadmap for the GA launch.

Gitter channel. For informal discussion or general feedback, you may join the Gitter chat for the new repository. The Gitter channel is also a great place to get help with the developer preview, although you can open an issue as well.

Contributing

You can open pull requests for fixes or additions to the new AWS SDK for JavaScript developer preview. All pull requests must be submitted under the Apache 2.0 license and will be reviewed by an SDK team member before merging. Accompanying unit tests are appreciated.