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

Question: support for Lambda Layers in TypeScript?

Open zirkelc opened this issue 2 years ago • 9 comments

I could't find any indication in the documentation, but does serverless-esbuild support lambda layers written in Typescript? There's currently an open issue with serverless-webpack (https://github.com/serverless-heaven/serverless-webpack/issues/556) which does not compile the TS into JS before packaging the layer.

I was hoping I could use this package to deploy may layers.

zirkelc avatar Sep 30 '21 07:09 zirkelc

This could be an interesting thing to add. I think there would be a question around how to set entry points.

I think if they specify only a path, we should treat every file in there as an entry point. Though we should encourage people to specify what files they want as entry points.

If they have a nodejs folder we should leave it untouched to preserve the library dependency behaviour of lambda

samchungy avatar Oct 02 '21 01:10 samchungy

Yes I agree. I think a convention would make sense here that if a layer points to a folder, then every file should be treated as entry point. If the layer points to a specific file like index.ts/js, then only this should be considered an entry point.

layers:
  layerOne:
    path: src/layers/one # take every file as entry point
    name: layerOne
  layerTwo:
    path: src/layers/two/index.ts # take this file as entry point
    name: layerTwo

Alternatively, the layers property inside serverless.yml could be extended with an entries property.

What would be a good starting point here? I found the [rootFileNames](https://github.com/floydspace/serverless-esbuild/blob/d9f9b41df87388dfd4d3f0d79997b4126fe2ecd3/src/index.ts#L190) as point that must potentially be extended to return functions and layers.

What else needs to be considered?

zirkelc avatar Oct 02 '21 10:10 zirkelc

Sounds like you're keen to contribute this, very nice! Some consideration will definitely need to be taken around packaging patterns + exclude.

A few questions come to mind:

  • Should the external esbuild functionality affect the packaging of layers?
  • What if the user wants to pack some static files in the layer? Should they use package patterns? Or should we include them by default when they specify a path? (Some documentation would definitely be needed around this)

Need to also handle ignoring lambda layers which are ARNs.

Might need to check with the big man Floydspace himself. I've been using this for about a couple months only.

samchungy avatar Oct 02 '21 13:10 samchungy

Hi @chriszirkel @samchungy what is the common scenario of using layers? So far in my experience, I have used layers to push there some heavy artifacts (chrome binary from puppeteer for instance) or pre-installed node_modules folder. Could you share your use case, do you push there like shared helper functions? then I have a couple of questions: do you need them to be bundled or just transpiled? Are layers one and two are managed by separate package.jsons, or the same with the app? And apparently, lambdas reference the code from layers, so we also somehow have to avoid bundling these files, currently, it's not supported, only packages from node_modules can be marked as external.

floydspace avatar Oct 03 '21 11:10 floydspace

Ah yep that makes sense. I haven't used layers in a while but my usecase was similar. I would pre-install node_modules too. So I guess we can ignore external. I think if we make users manage their own lambda layer nodejs folder & nodejs/package.json it would make more sense. Then we don't need to worry about it. I think the logic should be just to copy over the nodejs folder in the layer path if we see it.

When I used layers before -> I would use it almost like a common lib between lambdas to avoid having to re-upload the same files so yep, a mix of shared functions and heavy artifacts.

I think there could be a usecase for both bundling and/or transpiling layers

samchungy avatar Oct 03 '21 22:10 samchungy

I currently use layers to share common code and dependencies between multiple services. Also my serverless service only contains layers and doesn't contain any functions, so I don't have the issue of lambdas referencing the code from the layer.

I agree to @samchungy logic about layer/nodejs folder. I think the existence of a package.json file inside that folder could determine the way forward. If package.json exists, the layer should be bundled and transpiled. If it doesn't exist, just transpiling all files in that folder should be enough. This distinction also affects the way the code is imported in the lambda function. When the layer is attached to a lambda function, its content gets merged with the existing /opt/nodejs folder (https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html).

If the layer contains a package.json file, the layer itself should be considered a package and should be imported by its package name. Therefore, the bundled and transpiled files should be outputted into its own layer/nodejs/node_modules/<package_name> folder. Then the lambda function can require('package_name') it like a normal package. On the other hand, if the layer only contains source code files, then these files should be transpiled and outputted in the same folder layer/nodejs/<file_name>. These files are available during runtime in /opt/nodejs and can be required as require('./file_name.js').

What do you think?

zirkelc avatar Oct 04 '21 12:10 zirkelc

Guys, any solution for this? I'm trying to use layers in a serverless project with esbuild but without success. The deploy is done successfully but I have an import error

fzanfolim avatar Sep 05 '22 14:09 fzanfolim

the layers problem is actually an AWS bug with the ES module. There's a serverless plugin to fix this problem (by creating a symlink from the node_modules folder inside all the lambdas). Follow the link: https://www.npmjs.com/package/serverless-esm-layer

luisdemarchi avatar Sep 18 '22 22:09 luisdemarchi

the layers problem is actually an AWS bug with the ES module. There's a serverless plugin to fix this problem (by creating a symlink from the node_modules folder inside all the lambdas). Follow the link: https://www.npmjs.com/package/serverless-esm-layer

That is not an aws issue i guess. The lambda layers are not getting packaged or transpiled

debarkamondal avatar Sep 23 '23 06:09 debarkamondal