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 build
and thensam local start-api -d 3099
and then attach my debugger as I invoke a curl command, I am able to set breakpoints inhello-world/app.ts
and 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 pointCodeUri
to 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.map
in.aws-sam
does have an accuratesources
entry though, e.g."sources": ["../../../hello-world/hello1/app.ts"],
If I instead revert
CodeUri
to 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 theCodeUri
directory), then it appears to build correctly but.aws-sam/build/HelloOneFunction
includes the wrong source, meaning the source forHelloWorldFunction
instead. Additionally, theapp.js.map
file refers to a file inprivate/var/folders
that does not exist:(everything up through the
/T
exists, but thetmp...
folder does not.)EntryPoints
, e.g.hello2/app.ts
, then.aws-sam/build/HelloTwoFunction/app.js
includes the correct source, but itsapp.js.map
again points to a file inprivate/var/folders
that 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.ts
function. However, if I addAWS::Serverless::Function
definitions 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.ts
function.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.