AWS SDK for JavaScriptはV2とV3の2種類あるぞ!

AWS SDK for JavaScriptのV2とV3の違いをS3 GetObjectの例を交えつつ見ていきます。
2021.09.09

Node.jsでAWS SDKを使おうとした際、現状V2とV3という2つの選択肢があるのですが、それぞれで違う部分が結構あります。

リポジトリもそれぞれ分離しています。

V2

https://github.com/aws/aws-sdk-js

V3 (別リポジトリになってる)

https://github.com/aws/aws-sdk-js-v3

今回はS3からデータをGetObjectする例を交えて違いを見ていきます。

環境

Node.js

❯ node -v
v15.8.0

プロジェクトの準備

npm init
npm install -D typescript
npm install -D ts-node
npm install -D tslib @types/node

あと、package.jsonに実行用のコマンドを追加しておきます。

{
  "scripts": {
    "exec": "ts-node",
  },
},

SDKのインストール

V2

npm install aws-sdk

V3

npm install @aws-sdk/client-s3

@をつけないとV2がインストールされてしまうので注意が必要です。

V3の特徴としては必要なモジュールだけ個別にインストールすることが可能です。

公式ドキュメントによるとV3は現在安定しており、今後はこちらの使用が推奨されているようです。

https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/index.html

S3でGetObjectするときの例

V2の場合

import { S3 } from 'aws-sdk';
import * as fs from 'fs';

const s3 = new S3({
  region: 'ap-northeast-1'
});

const bucket = 'sample-bucket';
const objectKey = 'xxxxxx/xxxxxx.pdf';

function main() {
  const result = s3.getObject({
    Bucket: bucket,
    Key: objectKey,
  });
  // Readable型を取得
  const readStream = result.createReadStream();
  console.log({ readStream });

  const writer = fs.createWriteStream("xxxxxx.pdf");
  readStream.pipe(writer);
}

main();
npm run exec v2.ts

V3の場合

import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
import * as fs from 'fs';

const s3 = new S3Client({
  region: 'ap-northeast-1'
});

const bucket = 'sample-bucket';
const objectKey = 'xxxxxx/xxxxxx.pdf';

async function main() {
  const result = await s3.send(new GetObjectCommand({
    Bucket: bucket,
    Key: objectKey,
  }));

  const { Body } = result;
  console.log({ Body }); // これがReadable型

  const writer = fs.createWriteStream("file2.pdf");
  Body.pipe(writer);
}

(async () => {
  await main();
})();
npm run exec v3.ts

この例だけでも結構違いがあるのがわかると思います。

個人的にはV3を使っているのにcreateReadStreamを使用しようとしたりしてハマってしまいました。

検索するとV2の情報がまだまだ多いです。

また、V3でも以下のようにs3.getObjectのようなV2までと同じような形で記述することも可能です。

import { S3 } from '@aws-sdk/client-s3';
import * as fs from 'fs';

const s3 = new S3({
  region: 'ap-northeast-1'
});

const bucket = 'sample-bucket';
const objectKey = 'xxxxxx/xxxxxx.pdf';

async function main() {
  const result = await s3.getObject({
    Bucket: bucket,
    Key: objectKey,
  });

  const { Body } = result;
  console.log({ Body }); // これがReadable型

  const writer = fs.createWriteStream("xxxxxx.pdf");
  Body.pipe(writer);
}

(async () => {
  await main();
})();

ただし、S3の操作に関する全てのコードが含まれるため、インポートされるコードが増え、パフォーマンスが低下するようです。

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/index.html#high-level-concepts

V2から移行するとき等にはこちらでも良いかもしれませんが、

この例のように操作によってはV2と戻り値が異なる場合もあるので都度微調整は必要そうです。

最後に

公式でも推奨されていますが、今後は可能な限りV3を使っていくのが良さそうです。

V2を使用している場合は公式で移行ガイドも用意されているのでそちらを参照するのも良いと思います。

https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v3/developer-guide/migrating-to-v3.html