LocalStack + Terraform + Node.js Lambda で Lambda をデプロイしたときに、以下のエラーでハマりました。
/var/runtime/index.mjs
Cannot find module 'index'
結論から言うと、原因は Terraform の archive_file ではなく、LocalStack が ZIP 内の index.js を ESM と誤判定すること です。
つまり、ZIP の中身や展開自体は問題ではなく、LocalStack がモジュール形式を判定する段階で誤っている のが原因です。
LocalStack の Node.js 20 ランタイム(あるいは内部の ZIP 処理)が、CommonJS の index.js を ESM と誤判定して index.mjs を読み込もうとするため発生します。
結果として以下のようなエラーが出ます。
Require stack:
この問題を回避するには、以下の方法があります
Terraform では ZIP を読むだけにする Terraform に ZIP を作らせず、自前でビルドスクリプトで ZIP を作る方法が安全です。
const esbuild = require("esbuild");
const { zip } = require("zip-a-folder");
(async () => {
await esbuild.build({
entryPoints: ["src/index.ts"],
bundle: true,
minify: false,
platform: "node",
target: "es2021",
outfile: "dist/index.js",
});
await zip("dist", "build/payment_initiator.zip");
})();
resource "aws_lambda_function" "payment_initiator" {
filename = "${path.module}/build/payment_initiator.zip"
source_code_hash = filebase64sha256("${path.module}/build/payment_initiator.zip")
handler = "index.handler"
runtime = "nodejs20.x"
role = aws_iam_role.lambda_role.arn
depends_on = [aws_iam_role_policy.lambda_ddb_policy]
}
Cannot find module ‘index’ は LocalStack の Node.js ランタイムによる ESM 誤判定バグ Terraform では ZIP を作らせず、ビルドスクリプトで ZIP を作るのがシンプル