内容
AWS CDKのLambda実装で@aws-lambda-powertools/logger
を使用した際、
以下エラーが発生したため対応方法メモ
{
"errorType": "Error",
"errorMessage": "Dynamic require of \"node:crypto\" is not supported",
"stack": [
"Error: Dynamic require of \"node:crypto\" is not supported",
" at file:///var/task/index.mjs:1:383",
" at file:///var/task/index.mjs:13:15027",
" at file:///var/task/index.mjs:1:499",
" at file:///var/task/index.mjs:13:23037",
" at file:///var/task/index.mjs:1:499",
" at file:///var/task/index.mjs:15:1062",
" at async file:///var/task/index.mjs:15:1026"
]
}
開発環境
- aws-cdk: v2 (2.66.1)
- aws-sdk: v3 (3.348.0)
- Lambdaランタイム: Nodejs.18.x
- @aws-lambda-powertools/logger: 1.9.0
原因
ESM、CJS関連は複雑なため詳細には理解できていないが、ESMとCJSが混在する場合は注意が必要
混在する場合、import、requireの可/不可が存在する
LambdaランタイムにNodejs.18.xを使用する場合ESMとなり、
CJSパッケージは数多く存在するため、どうしても混在することが多い
今回、TypeScript 4.7 と Native Node.js ESMに記載されているように、
ESMからCJSの Dynamic Import
、require
ができないためエラーとなった
cryptoに記載されているように、
自身で実装するESMのコードから crypto
をimportする場合、以下のように await
でimport可能
(今回は、@aws-lambda-powertools/logger
内でrequireされている crypto
でエラーとなっているため不可)
const { createHmac } = await import('node:crypto');
ESM、CJS関連参考
- TypeScript 4.7 と Native Node.js ESM
- TypeScriptのESMでハマる
- Using a JavaScript library (without type declarations) in a TypeScript project.
- AWS Lambda向けにTypeScriptをビルドする
- When using esbuild with external react I get Dynamic require of "react" is not supported
対策
以下2つの方法でエラーの解消ができた
1. require を使えるようにする
How to fix "Dynamic require of "os" is not supported"にあるように、
banner
を指定することで、バンドル後のmjsファイルの先頭に
import { createRequire } from 'module';const require = createRequire(import.meta.url);
を組み込み
require
を使えるようにする
CDKの場合、
NodejsFunctionのパラメータ bundling
に banner
を指定する
const bundling = {
banner: "import { createRequire } from 'module';const require = createRequire(import.meta.url);",
minify: true,
sourceMap: true,
tsconfig: path.join(__dirname, '../../tsconfig.json'),
format: OutputFormat.ESM,
};
2. @aws-lambda-powertools/logger をバンドルしない
NodejsFunctionのパラメータ bundling
の nodeModules
にパッケージを指定し、バンドル対象外にする
const bundling = {
minify: false,
sourceMap: true,
tsconfig: path.join(__dirname, '../../tsconfig.json'),
format: OutputFormat.ESM,
nodeModules: ['@aws-lambda-powertools/logger'],
};