serverless-esbuild
serverless-esbuild copied to clipboard
ESM modules are not loaded by AWS lambda
Describe the bug
When packaging a lambda function with platform: neutral
, the lambda fails at runtime with:
{
"errorType": "Runtime.UserCodeSyntaxError",
"errorMessage": "SyntaxError: Unexpected token 'export'",
"stack": [
"Runtime.UserCodeSyntaxError: SyntaxError: Unexpected token 'export'",
" at _loadUserApp (file:///var/runtime/index.mjs:997:17)",
" at async Object.UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1035:21)",
" at async start (file:///var/runtime/index.mjs:1200:23)",
" at async file:///var/runtime/index.mjs:1206:1"
]
}
This suggests the runtime is trying to load it as CJS. This document explains that either package.json
must indicate the type as module
or the lambda file should have a .mjs
file extension: https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda/
As a workaround, it is fortunately possible to specify outputFileExtension
as .mjs
which fulfils the second condition and might be what you had in mind when enabling ESM support (judging by the test cases), but this is neither mentioned in the documentation for serverless-esbuild nor selected by default.
To Reproduce
- Have a project setup with
type: module
- Configure esbuild with
platform: neutral
- Include a minimal demo lambda
- Verify that when built, the artifact ZIP file includes a .js file containing a top-level async method as expected
- Deploy and try to invoke on AWS
Expected behavior
I expected a package.json
file containing only type: module
to be included with the bundle.
This is what SST does out of the box.
Screenshots or Logs n/a
Versions (please complete the following information):
- OS: Mac
- Serverless Framework Version: 3.24.0
- Plugin Version: 1.32.8
Additional context Looks like there is a workaround as indicated.
+1 I had the same issue as OP.
I was unable to include the package.json at all using the documented method for packaging e.g.
// serverless.yml
package:
patterns:
- '!node_modules/@aws-sdk/**'
- package.json
Fortunately i was able to add outputFileExtension: .mjs
to achieve this too thanks to OP
The workaround isn't enough when using sls invoke local
: https://github.com/serverless/serverless/issues/11308#issuecomment-1366781871