LoginSignup
1
0

CloudFront Lambda@Edge で新しい NodeJS ランタイムを利用する場合に Cannot find module 'aws-sdk' というエラーが発生する

Last updated at Posted at 2023-11-18

問題

これまで NodeJS 14 ランタイムで利用していた Lambda@Edge のコードでは以下のように aws-sdk を利用するコードを書いていた。

const aws = require("aws-sdk");

しかし、NodeJS 18 にランタイムを更新してデプロイすると、このコードがエラーになってしまったのでその原因と対処方法を調査した。

原因

NodeJS 18 ランタイムからは require('aws-sck') によって利用される AWS SDK v2 ではなく、新たに AWS SDK v3 がデフォルトで同梱されるようになり、v2 を意味する require('aws-sck') がデフォルトでは利用できなくなったため。

v3 を利用する場合は、ドキュメントに従って適切なモジュールを利用することになる。

今回のケースでは v2 では以下のように利用していた。

const aws = require("aws-sdk");
const ddb = new aws.DynamoDB.DocumentClient({
  apiVersion: "2012-08-10",
  region: "ap-northeast-1",
});

これを v3 に置き換えたい場合は、例えば以下のように修正して DynamoDBClient を利用するようにする。 v3 のドキュメントでは import を使う ES6 スタイルとなっているが、これまで通り exports.handler = ... として定義している場合は CommonJS スタイルとなるので、require を使ってコンテンツをインポートする。

const { DynamoDBClient, GetItemCommand } = require("@aws-sdk/client-dynamodb");
const { unmarshall } = require("@aws-sdk/util-dynamodb");

const ddbClient = new DynamoDBClient({});
// v2 と違って、Key の中で指定する場合に型情報が必要になった。 以下は文字列の場合
const command = new GetItemCommand({
  TableName: TABLE_NAME,
  Key: {
    key: { S: "key..." },
  },
});

const res = await ddbClient.send(command);
// v2 と違って Item は DynamoDB の特定データ形式で返されるので、
// v2 と同じように扱いたい場合は unmarshall する必要あり
const item = res.Item ? unmarshall(res.Item) : {};

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0