CloudFormation's ZipFile still does not support ESM imports
Probably the last place I need to use require() instead of ESM module import is with CloudFormation ZipFile:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Runtime: nodejs20.x
Code:
ZipFile: |
const {IAMClient, AttachUserPolicyCommand} = require("@aws-sdk/client-iam");
exports.handler = async (event) => {
const res = await new IAMClient().send(new AttachUserPolicyCommand({
UserName: process.env.UserName,
PolicyArn: "arn:aws:iam::aws:policy/AWSDenyAll",
}));
console.log(res);
};
Why can't it support import?
When CloudFormation uploads the package, it puts the contents into a file and calls it index.js
. Because of the naming, when NodeJS executes the file, it treats it as a commonJS module. A package.json would help as that could specify that all js files are ESM modules, but CloudFormation does not provide an option to upload multiple files.
There are a couple of things that might fix this on the NodeJS side. First, Node recently got an experimental ability to detect the module automatically. From the docs for --experimental-detect-module:
Node.js will inspect the source code of ambiguous input to determine whether it contains ES module syntax; if such syntax is detected, the input will be treated as an ES module.
This is opt-in and behind an experimental flag, so I don't expect it will be enabled by default any time soon.
The other is that require
will be supported in ES modules as well via --experimental-require-module:
Supports loading a synchronous ES module graph in require().
Why is this interesting? That would allow CloudFormation to default to index.mjs instead of index.js without breaking existing code (well, hopefully).
In the meantime, I would really like an option for the AWS::Lambda::Function
resource type to allow me to use modules with ZipFile. It could be a property that sets the "type": "module" in a package.json or the ability to specify the filename for the ZipFile.