1
votes

I'm new in nodejs and aws lambda. I'm trying to create layer with common functions for my bunch of lambda functions. In lambda handler the import of custom module has the following definition: let commonService = require('@common/service');

The zip with the module file has the following structure:

nodejs
--node_modules
  --@custom
    --service
    --index.js
    --package.json  

But I get the error: "errorMessage": "Error: Cannot find module '@common/service'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",

The @custom/service module package.json contains the following:

{
  "name": "@common/service",
  "version": "1.0.0",
  "main": "index.js",
  "license": "ISC",
  "dependencies": {
    /***
  }
}

Thanks in advance!

1

1 Answers

0
votes

Try using AWS Lambda Layers.

Using Layers has two major benefits.

  • It allows you to deploy your base dependencies in one place and manage them centrally.
  • It shrinks the size of your Lambda app deployments. No more massive node_modules folder hierarchy to upload every time.

How to use them? It's a rather in-depth topic, but the gist of it is that you can:

  1. build and deploy a Layer in AWS. A Layer is nothing more than a "bare" npm project, really. You install your commonly-used NodeJS modules in it, nothing else.
  2. Assuming you're using the serverless application model to deploy your AWS Lambda functions, you configure your Lambda function to use the Layer. Here's a stripped-down version of a SAM yaml file that illustrates this:
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: My Serverless App
Parameters:
  # ...

Globals:
  Function:
    Runtime: nodejs10.x
  #   Environment:
  #     Variables:
  #       NODE_ENV: test

Resources:

  CommonDependenciesLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: my-common-deps
      Description: Common dependencies for my NodeJS apps
      ContentUri: ../common-deps/
      RetentionPolicy: Retain
    Metadata:
      BuildMethod: nodejs10.x

  performSomeFunction:
    Type: 'AWS::Serverless::Function'
    Properties:
      FunctionName: performSomeFunction
      Handler: lambda.someFunction
      Layers:
        # You can either Ref a layer defined in this SAM file like this.
        # - !Ref CommonDependenciesLayer

        # ... or you can hard-code an external ARN
        # - arn:aws:lambda:us-east-1:nnnnnnnnnnnnn:layer:myapp-common-deps:5
      CodeUri: ./
      # ...
  1. In your Lambda code, all you do is use the normal CJS require syntax. For example, suppose I put the mysql library in my CommonDependenciesLayer, above. As long as my Lambda function points to the layer in the SAM file, all I have to do is require('mysql') in my code. It'll be there.

As you get it working, there are some subtleties to think about with respect to Layer deployment.

  • Do I want to build the Layer every time? (Probably not, but I recommend you do this as you're learning how Layers and your Lambdas work together).
  • How often do my Layer components change?
  • Do I want to make my Layer publicly available?
  • Do I want to user a publicly available Layer from another account?