AWS LambdaのNode.jsランタイムを16から18にしたらaws-sdkがインポートできなくなった

はじめに

AWSのLambdaで使っているランタイムのNode.js16がサポート終了とのことで、Node.js18にしたところ、動かしていたプログラムが以下のエラーを吐いた。

“Runtime.ImportModuleError: Error: Cannot find module ‘aws-sdk'”

原因

エラー内容からもわかるように、aws-sdkモジュールがインポートできていない。

調べてみると、今まで使っていたaws-sdkは、v2というバージョンでNode.js18では使えない事がわかった。代わりにv3を使う必要があるとのこと。

対応方法

aws-sdk v3をインポートする。

ただ、インポート部分だけでなくクライアントサービスの使い方も変わったので、コード内の記述も修正しなければいけないようです。S3サービスを例に修正方法をご紹介します。

S3オブジェクトを取得する例

修正前(aws-sdk v2)

const AWS = require('aws-sdk');
const s3 = new AWS.S3();

export const main = async () => {
    const params = {
        Bucket: "test-bucket",
        Key: "hello-s3.txt",
    };

    try {
        const response = await s3.getObject(params).promise();
        const str = await response.Body.transformToString();
        console.log(str);
    } catch (err) {
        console.error(err);
    }
};

修正後(aws-sdk v3)

const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
const s3 = new S3Client({});

export const main = async () => {
    const command = new GetObjectCommand({
        Bucket: "test-bucket",
        Key: "hello-s3.txt",
    });

    try {
        const response = await s3.send(command);
        const str = await response.Body.transformToString();
        console.log(str);
    } catch (err) {
        console.error(err);
    }
};

requireの代わりにimportを使う場合

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

参考

AWS SDK を使用して、Amazon S3 バケットからオブジェクトを取得する
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/example_s3_GetObject_section.html

自動移行ツール

コマンド1つでv2からv3へ自動的にコード変換してくれるツールがあるようです。自分は使ってないですが、修正箇所が多い場合は活用してみるのもいいかもですね。

まとめ

古い技術がサポート終了などで使えなくなるケースがありますが、バージョンアップすると今まで使っていたライブラリなども連鎖して影響受けたりして修正が意外と大変だったりしますね。