fastify / aws-lambda-fastify

Insipired by aws-serverless-express to work with Fastify with inject functionality.
MIT License
498 stars 32 forks source link

Running Fastify on AWS Lambda: Dynamic require of "events" is not supported #191

Open richardm opened 8 months ago

richardm commented 8 months ago

Prerequisites

Issue

This is not a bug with aws-lambda-fastify so much as trying to compile with esbuild and run it on AWS, but given how many people use esbuild, I think the README could make the DX much easier.

Background: I spent many hours this week trying to get my Fastify API deploying to AWS lambda. I'm running all the latest versions and used the boilerplate from this readme, but kept encountering this issue, even when I reduced it to the most minimal Fastify instance possible:

{
  "errorType": "Error",
  "errorMessage": "Dynamic require of \"events\" is not supported",
  "trace": [
    "Error: Dynamic require of \"events\" is not supported",
    "    at file:///var/task/dist/lambda.mjs:12:9",
    "    at node_modules/avvio/boot.js (file:///var/task/dist/lambda.mjs:1482:14)",
    "    at __require2 (file:///var/task/dist/lambda.mjs:15:50)",
    "    at node_modules/fastify/fastify.js (file:///var/task/dist/lambda.mjs:44355:17)",
    "    at __require2 (file:///var/task/dist/lambda.mjs:15:50)",
    "    at file:///var/task/dist/lambda.mjs:72691:30",
    "    at ModuleJob.run (node:internal/modules/esm/module_job:217:25)",
    "    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)",
    "    at async _tryAwaitImport (file:///var/runtime/index.mjs:1008:16)",
    "    at async _tryRequire (file:///var/runtime/index.mjs:1057:86)"
  ]
}

At various points, I tried switching to commonjs as a work-around, but that was not possible due to this error:

✘ [ERROR] Top-level await is currently not supported with the "cjs" output format

    src/lambda.ts:10:32:
      10 │ export default awsLambdaFastify(await buildFastifyApi());
         ╵                                 ~~~~~

To get my Fastify API building as ESM with esbuild, I ultimately just had to add one line to my esbuild script adding a banner, but I did not see this mentioned in any of the docs or tutorials I tried to follow:

esbuild
  .build({
    entryPoints: ['src/lambda.ts'],
    banner: { js: "import { createRequire } from 'module';const require = createRequire(import.meta.url);" },
    bundle: true,
    format: 'esm',
    platform: 'node',
    target: 'node20',
    outfile: 'dist/lambda.mjs'
  })
  .catch(() => process.exit(1));

Adding a disclaimer to the README about needing to use a banner if using esbuild would have saved me many hours this week.

Uzlopak commented 8 months ago

You are welcome to add this to the Readme via a PR ;)