aws-sam-cli: Bug: Wrong handler mapping after esbuild
Description:
When running esbuild on a Lambda function, the output doesn’t mantain the same folder structure as the enry points, and this remains unchange in the built template, resulting in SAM not finding the lambda Handler:
Steps to reproduce:
Project structure:
- package.json
- template.yaml
-- src
--- functions
---- FunctionName
----- app.js
--- utils
---- some-util.js
Template.yaml:
FunctionName:
Type: AWS::Serverless::Function
Metadata:
BuildMethod: esbuild
Properties:
Handler: src/functions/FunctionName/app.Handler
Events:
HttpEvent:
....
Observed result:
code is budled to FunctionName folder in .aws-build resulting in:
- .aws-build
-- build
--- template.yaml
--- FunctionName
---- app.js
However, the built template results in:
FunctionName:
Type: AWS::Serverless::Function
Metadata:
BuildMethod: esbuild
Properties:
CodeUri: FunctionName
Handler: src/functions/FunctionName/app.Handler
Events:
HttpEvent:
....
Resulting in an error since FunctionName/src/functions/FunctionName/app.Handler
Expected result:
Handler in built template should match esbuild output. I.E:
FunctionName:
Type: AWS::Serverless::Function
Metadata:
BuildMethod: esbuild
Properties:
CodeUri: FunctionName
Handler: app.Handler
Events:
HttpEvent:
....
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 17 (9 by maintainers)
I’ve found a similar problem when using regular
sam init(v 1.57):Quick Start, Hello World, nodejs16.x, Zip, Typescript.
First thing to note is that if I invoke
sam buildand thensam local start-api -d 3099and then attach my debugger as I invoke a curl command, I am able to set breakpoints inhello-world/app.tsand step through with my debugger.If I then add two subfolders:
Then I’m faced with a conundrum:
If, for each
AWS::Serverless::Function, I pointCodeUrito a subfolder like/hello-world/hello1, it complains about not finding a package.json. It sayspackage.json file not found. Bundling source without dependencies.The resultantapp.js.mapin.aws-samdoes have an accuratesourcesentry though, e.g."sources": ["../../../hello-world/hello1/app.ts"],If I instead revert
CodeUrito point to the folder with package.json, then I need to indicate the path to the new function a different way. If I chooseHandler, e.g.Handler: hello1/app.lambdaHandler, (assuming Handler evaluates from theCodeUridirectory), then it appears to build correctly but.aws-sam/build/HelloOneFunctionincludes the wrong source, meaning the source forHelloWorldFunctioninstead. Additionally, theapp.js.mapfile refers to a file inprivate/var/foldersthat does not exist:(everything up through the
/Texists, but thetmp...folder does not.)EntryPoints, e.g.hello2/app.ts, then.aws-sam/build/HelloTwoFunction/app.jsincludes the correct source, but itsapp.js.mapagain points to a file inprivate/var/foldersthat does not exist.If I leave those folders in place in the filesystem, but remove them from template.yaml, then I can still set breakpoints on the original
hello-world/app.tsfunction. However, if I addAWS::Serverless::Functiondefinitions for either of the two new subfolder functions into template.yaml, then the breakpoints don’t work anymore - not even on the originalhello-world/app.tsfunction.I believe that for codebases with multiple functions, it would be preferable to share one package.json that is from a common parent folder, and to also be able to use a debugger on these functions.
@mildaniel any news on this?
I did some digging and found the issue is with how we bundle. I’ve explained it in #4216, but essentially we bundle straight into the artifact directory, at which point we’ve already lost the file tree from the code URI to the handler. e.g. esbuild takes the entry point (
src/functions/FunctionName/app.Handler) and bundles that into a single file (app.js) then takes that file and moves it into the artifact directoryFunctionName@lucashuy Actually, this is something that is even included in one of SAM’s examples https://github.com/aws/aws-sam-cli-app-templates/tree/master/nodejs16.x/cookiecutter-quick-start-web so how come it is not actually supported? Furthermore, this limits us to only having the possibility to have the handler at the root level of the codeUri (You can’t have something like ./src/app.js for example, because the output from esbuild would be wrongly mapped) And sharing a single node_modules at root level implies Only one npm install is run for all of your lambda functions, which would make the build process much faster.
Hi, thanks for opening this issue! Having root level node_modules is not a case that SAM CLI supports right now. The solution would be to set the CodeUri according to your folder structure and Handler to your functions like mentioned previously.
Please feel free to reopen or open a new issue if anything else arises.