I've been really enjoying playing with the Serverless framework recently. The FaaS (Function-as-a-Service) model really appeals to me, and I think it's going to be A Big Deal in the future. The Serverless framework makes interacting with AWS Lambda, API GateWay, and CloudFormation really really easy.
Unfortunately, because your code runs on other-people's-computers (aka. The Cloud) the development workflow is still in its early days. As a developer you spend a lot of time waiting for your function to be packaged (with any dependencies it required), and pushed across the network. Waiting is lame, so I wanted to investigate what I could use to speed up the development process.
While there's a number of libraries for simulating AWS Lambda locally, I narrowed down the ones I would try with the fantastic NPM Compare tool I only recently discovered. It makes it super quick and easy to look at the high-level metrics of NPM packages (e.g. stars on Github, frequency of updates, number of maintainers, etc); While these metrics aren't the be-all and end-all, they're a good indication of the "health" of a library.
This package has been out for a couple of years, which given AWS Lambda was introduced in 2014 is impressive - that combined with the number of releases suggests a lot of effort has gone in to it.
I found the interface to
node-lamba a bit unintuitive; If you call the base command with
-h you get a stack trace - it only works properly on the commands like
run, etc. Calling commands like
run without command line options also results in stack traces. Fortunately the project docs are quite decent, but I do like a tool that takes the time to help you use it rather than just taking a dump on your terminal...
The arguments expected by the
node-lambda run command were also strange; Why is specifying the
event.json done with
-j and the
-c are more intuitive? The long arguments even start with those letters, and they're not taken by other commands (
--contextFile respectively). Strange.
Once I'd worked out the correct commands and arguments to use, it worked as expected. I like that specifying the handler function matched what's used in
serverless.yml. Here's an example command based on my Serverless directory structure (which I will elaborate on later):
$ node-lambda run -H index.handler -j event.json -x context.json
node-lambda also has commands related to packaging and deploying Lambda functions, but these weren't really relevant because I have Serverless to take care of that for me.
Here's the same (nested) function call:
$ lambda-local -f index.js -c context.json -e event.json
One of the things I liked about
aws-lambda-local was that the event and context arguments are optional. In the case of the
context.json file/object, if you didn't specify it an automatically generated context object was created for you (with sensible fake data). Oh, and the arguments made much more sense to me...
Unfortunately the tool expects only the
handler function to be exported from the function file (i.e. it assumes the first exported function it finds is your handler, and there's no way to configure this). This meant my practice of exporting my functions (so they can be tested) didn't play nicely. To get it working I had to make sure I exported my handler function first in all my files. Not a big deal, but not something I would've changed otherwise.
For now I'll go with aws-lambda-local because it's lightweight and doesn't duplicate a bunch of Serverless functionality.
I can run my local test from
npm with scripts in my
package.json like this one (assuming
aws-lambda-local is installed globally):
"install:invoke": "cd functions/install && lambda-local -f index.js -e event.json -c context.json"