serverless-esbuild icon indicating copy to clipboard operation
serverless-esbuild copied to clipboard

ESM modules are not loaded by AWS lambda

Open asquithea opened this issue 2 years ago • 2 comments

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

  1. Have a project setup with type: module
  2. Configure esbuild with platform: neutral
  3. Include a minimal demo lambda
  4. Verify that when built, the artifact ZIP file includes a .js file containing a top-level async method as expected
  5. 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.

asquithea avatar Dec 06 '22 14:12 asquithea

+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

dan-newscorp avatar Jan 16 '23 23:01 dan-newscorp

The workaround isn't enough when using sls invoke local: https://github.com/serverless/serverless/issues/11308#issuecomment-1366781871

NemoStein avatar Jan 18 '23 15:01 NemoStein