floydspace / serverless-esbuild

💨 A Serverless framework plugin to bundle JavaScript and TypeScript with extremely fast esbuild
MIT License
445 stars 137 forks source link

Working with lamda layers #368

Open kaykhan opened 1 year ago

kaykhan commented 1 year ago

Hi friends,

I use the serverless framework and the typescript template which uses serverless-esbuild.

I am wondering if serverless-esbuild works with layers?

Layers are important when working with prisma and serverless functions. However ive found that the .esbuild folder is largly empty of anything ive packaged in the prisma layer.

    functions: {
        main: {
            handler: "handler.MainHandler",
            timeout: 300,
            layers: [{ Ref: "PrismaLambdaLayer" }],
        },
    },
    layers: {
        prisma: {
            path: ".prisma-layer",
            description: "Layer for prisma clients",
            package: {
                patterns: [
                    "!nodejs/node_modules/@prisma/engines/*",
                    "!nodejs/node_modules/.prisma/**/libquery_engine-*",
                    "nodejs/node_modules/.prisma/**/libquery_engine-rhel-openssl-1.0.x.so.node",
                    "!nodejs/prisma/**",
                    "nodejs/prisma/*.db",
                    "nodejs/node_modules/.prisma/client/schema.prisma",
                ],
            },
        },
    },

This is ofourse an issue for me as i end up with the following error when i try to run locally. sls invoke local -f main

✖ Error: ENOENT: no such file or directory, open '/home/app1/.esbuild/.build/schema.prisma'

oreporan commented 1 year ago

Running into the same issue with ffmpeg

I've been using serverless-webpack together with a lambda layer for ffmpeg and its been working. Now I'm trying to make the move to esbuild and getting this from my lambda:

{
    "errorType": "Runtime.ImportModuleError",
    "errorMessage": "Error: Cannot find module './lib/fluent-ffmpeg'\nRequire stack:\n- /var/task/src/functions/api/lambda.js\n- /var/runtime/UserFunction.js\n- /var/runtime/Runtime.js\n- /var/runtime/index.js",
    "stack": [
        "Runtime.ImportModuleError: Error: Cannot find module './lib/fluent-ffmpeg'",
        "Require stack:",
        "- /var/task/src/functions/api/lambda.js",
        "- /var/runtime/UserFunction.js",
        "- /var/runtime/Runtime.js",
        "- /var/runtime/index.js",
        "    at _loadUserApp (/var/runtime/UserFunction.js:221:13)",
        "    at Object.module.exports.load (/var/runtime/UserFunction.js:279:17)",
        "    at Object.<anonymous> (/var/runtime/index.js:43:34)",
        "    at Module._compile (internal/modules/cjs/loader.js:1085:14)",
        "    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)",
        "    at Module.load (internal/modules/cjs/loader.js:950:32)",
        "    at Function.Module._load (internal/modules/cjs/loader.js:790:12)",
        "    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)",
        "    at internal/main/run_main_module.js:17:47"
    ]
}

My configuration (which works fine with webpack)

 api:
    name: ${self:custom.api.talk.lambda.name}
    handler: src/functions/api/lambda.handler
    layers:
      - arn:aws:lambda:us-west-2:899016509520:layer:ffmpeg:1
sxppro commented 1 year ago

Hi, is there any update on how to get Lambda layers working with Node 18 (since it has ES6 support?)

sxppro commented 1 year ago

Hi, is there any update on how to get Lambda layers working with Node 18 (since it has ES6 support?)

I got lambda layers working by setting the relevant dependencies to external in custom esbuild config:

layers:
  dependencies:
    path: ./path/to/<your-layer-name>/
    description: Dependencies layer for service
    # Optional
    compatibleRuntimes:
      - 'nodejs18.x'

custom:
  esbuild:
    # Dependencies to be retrieved from lambda layer
    exclude: ['aws-sdk', 'aws-serverless-express', 'cors', 'express', ... ]

Then wherever in your serverless project you want, create <your-layer-name>/nodejs/, then within that directory create a new npm project with npm init (or yarn) with the dependencies to be stored in the layer. I believe using pnpm causes some issues due to symbolic linking but there are workarounds.

The node_modules should end up at <your-layer-name>/nodejs/node_modules or they won't be automatically included in the PATH. See here for more info on layer paths.

pursual commented 1 year ago

What if you have custom code (not an npm package) in a layer that you also want to exclude?

debarkamondal commented 11 months ago

I am currently facing the same issue. As a workaround i have decided to compile it and bundle it before packaging and setting the paths in serverless.yml to the build folder.