floydspace / serverless-esbuild

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

node_modules as lambda layer #297

Open GioPat opened 2 years ago

GioPat commented 2 years ago

I'm currently developing several functions that share the same libraries. It's working great and I'm able to get my functions deployed correctly. The only thing I'm struggling with is reducing the size (each simple lambda is 1.7MB) by sharing the node_modules between them.

I tried to manually create a layer containing the node_modules folder and deploying the function using the following esbuild config (in the serverless.ts file:

...
  esbuild: {
    ...
    exclude: ['aws-sdk', 'pg-hstore'],
    external: ['./node_modules/*'],
    ...
  }
...

But the lambda is not able to "understand" the dependencies. This is an example of the lambda output: Must use import to load ES Module: /opt/node_modules/sequelize/lib/index.mjs

Is there any example to configure function that shares a layer with the node_modules?

Thanks

luisdemarchi commented 2 years ago

@GioPat the layers issue is actually an AWS bug with ES Module. I made a serverless plugin to fix this problem (by creating a symbolic link from the node_modules folder inside all the lambdas). Follow the link: https://www.npmjs.com/package/serverless-esm-layer

kaykhan commented 2 years ago

@GioPat the layers issue is actually an AWS bug with ES Module. I made a serverless plugin to fix this problem (by creating a symbolic link from the node_modules folder inside all the lambdas). Follow the link: https://www.npmjs.com/package/serverless-esm-layer

Hi, @luisdemarchi

How do you handle this problem when you are using patterns to try and pull external files and they are not necessarily from node_modules folder but from another folder/path e.g .prisma-layer .

  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",
        ],
      },
    },
  },

see the reproducable example - https://github.com/kaykhan/prisma-typescript-example

luisdemarchi commented 2 years ago

@kaykhan the .prisma-layer folder is executed locally where serverless will ziped what is inside, but the final path will always be: /opt/nodejs/node_modules.

It looks like the plugin will work normally