top of page
1-modra.jpg
ClsoeIT Logo

Starting AWS SAM folder structure (NodeJS)

When I started putting together my first AWS SAM project, I was confused with the project structure - as always, when I’m starting new project with new technology. You can easily make a bloated project where code is duplicated in each lambda function.


I had a few goals to achieve:


  • simple and general structure which is a good starting point for smaller applications

  • each lambda function has its own dependencies

  • common code is shared in layers

  • no external dependencies in the repository - every dependency is defined in package.json


In the project folder, I created folder Lambdas. Each lambda is in its own folder with package.json. The package.json contains dependencies only required by this function.


Folder Layers will contain folders with layers. Because the structure is just a starting point, I will have only two layers. One called SharedInternalDependencies with my own library code which I want to share and one called SharedExternalDependencies with third-party libraries used in lambdas and in internal shared dependencies.


SharedExternalDependencies just contain package.json. Dependencies will be downloaded by SAM during the build process. Yes, SAM can build not only lambdas but also layers. But you should use the newest version of SAM, because this feature wasn’t always there.


SharedInternalDependencies is not built by SAM, so we have to create a valid folder structure for Node. The correct structure is nodejs/node_modules/my_module. Or nodejs/node_modules/my_module.js. If you use a different language, the path has to be different. You can find the correct paths in the AWS documentation.


The final structure will look like this:

  • MySAMProject

  • template.yml

  • Lambdas

  • Lambda-1

  • lambda-1.js

  • package.json

  • Lamda-2

  • lambda-2.js

  • package.json

  • Layers

  • SharedInternalDependencies

  • nodejs

  • node_modules

  • my-library-module.js

  • SharedExternalDependencies

  • package.json


The last step is to configure lambdas and layers in template.yml. My example will have these 4 resources.

lambda1:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: Lambdas/Lambda-1/
      Handler: lambda-1.myExportedFunction
      Runtime: nodejs12.x
      MemorySize: 128
      Timeout: 100
      Description: My first lambda function.
      Layers:
        - !Ref externalDep
        - !Ref internalDep
        
  lambda2:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: Lambdas/Lambda-2/
      Handler: lambda-2.myExportedFunction
      Runtime: nodejs12.x
      MemorySize: 128
      Timeout: 100
      Description: Second lambda.
      Layers:
        - !Ref externalDep
        - !Ref internalDep
  
  externalDep:
    Type: AWS::Serverless::LayerVersion
    Properties:
        LayerName: SharedExternalDependencies
        Description: Shared external dependencies.
        ContentUri: Layers/SharedExternalDependencies/.
        CompatibleRuntimes:
            - nodejs12.x
        RetentionPolicy: Retain
    Metadata:
        BuildMethod: nodejs12.x
  
  internalDep:
    Type: AWS::Serverless::LayerVersion
    Properties:
        LayerName: SharedInternalDependencies
        Description: Shared internal dependencies.
        ContentUri: Layers/SharedInternalDependencies/.
        CompatibleRuntimes:
            - nodejs12.x
        RetentionPolicy: Retain

Notice the definition of external layer has Metadata. The selected BuildMethod will build the layer. If you open .aws-sam, you can notice that the correct path nodejs/node_modules with downloaded modules was created.

Related Posts

See All

Validating and generating Atlassian JWT

When developing a add-on to cloud Jira, a usual need is to communicate with the Jira using REST API. The authentication is done using JWT and it took us a while to figure out how to validate and gener

MGS integration with antivirus

One of the MGS features is to manage model-related files and documents. Of course, common and other model non-related files can be uploaded also to the public folder, users' private folder, or shared

Flattening Docker images

Docker images are stored as layers. To be more precise, the filesystem is layered, so each change (RUN, COPY,…) will result in adding a new layer. This approach has many advantages - images can be bui

bottom of page