A JavaScript user’s First AWS Lambda function
I’m using JavaScript about 80% of my coding time at work, mostly for frontend. I enjoy the work and recent JS ecosystem. It empowers not only frontend developers, but also backend developers. Also, lately, Serverless technology is one of many hot topics for me. Because I hear a lot of good things about AWS, I started reading “ Serverless Archtecture on AWS” written by Peter Sbarski. It explains how to deploy a serverless app from scratch with AWS and Firebase. I just finished “just reading”, and now, by following the instructions, have jumped into the AWS console for creating the example app. I admit I was not comfortable being in the AWS console before reading the book, but now I’m getting used to it ❤
I really like the book so far. You can also read the book at this website. In chapter 3, they explain how to create a lambda function. You can see the code here. Because the book’s main focus is about serverless architectures, it’s not mentioning everything else. In this post, I’d like to add some features to improve the steps from a JS user’s perspective.
The target readers of this post are whom started learning modern JS development tools such as node, npm, and git. I think my work experience with JS is limited, so feedback from experts is much appreciated.
The pre-condition is that you have to setup a proper IAM user and AWS CLI. If you haven’t, I recommend you read Appendix-B.
Table of contents
- Have something working (Copy code, run the simple test)
- Be responsible — Write unit tests (Jest)
- Tidy up — Format code (ESLint, Prettier)
- Commit — Let’s run tests automatically (husky, lint-staged)
- Deploy — We should not upload devDependencies (npm prune)
1. Have something working (Copy code, run the simple test)
NOTE: You can skip this step if you have built a lambda function with node.js.
I want you to download some files from his repository. I hope you have package.json, index.js, tests/ and tests/event.json in your working directory. Let's install dependencies first with this command:
$ npm installI assume you can also run the test command:
$ npm run testthen you can see “Welcome” from the console.log() as the result. Did you see it? Awesome! For this blog post, we're actually not going to use index.js. Let's copy the file and name it as handler.js. Then open the file and change it like below so we can test!
2. Be responsible — Write unit tests (Jest)
The purpose of writing tests is to guarantee that the module is always working as expected. If you didn’t have any tests, and someone changed the module after, nobody knows the module is working like it did before the module got changed. Let’s use for unit testing. Install jest with this command:
$ npm install -D jestLet’s make a directory named __tests__. Jest automatically checks if there are test files in the directory.
We shall name the test file as handler.spec.js and save it under __tests__.
The test code I wrote looks like this:
This simple test code checks if each key got generated correctly, against the input file (../tests/event.json). We'd also like to add "jest": "jest" in scripts of the package.json for running the test command.
When you are ready, let’s run the unit test with this command:
$ npm run jestYou should see this message below:
✓ correct keys get generated (4ms)
Congrats! Your first test checks all the keys. This way, even if someone else changes the handler.js, the value of keys won't change because the test will detect otherwise.
3. Tidy up — Format code (ESLint, Prettier)
ESLint is a linting utility that finds some problematic patterns. It’s been widely used in JS community. Prettier is a code formatter that makes your code look “prettier”. They are both great tools. Let’s try them out! Install them with this command:
$ npm install -D eslint prettier eslint-config-prettier eslint-plugin-prettierFirst, we need to initialize ESLint:
$ npx eslint --initIt will ask multiple questions. Let me leave my answers corresponding to the questions below:
? How would you like to use ESLint? To check syntax and find problems
? What type of modules does your project use? JavaScript modules (import/export)
? Which framework does your project use? None of these
? Where does your code run? Node
? What format do you want your config file to be in? JavaScript
Local ESLint installation not found.
The config that you’ve selected requires the following dependencies:
? Would you like to install them now with npm? Yes
Then, integrate Prettier with ESLint. On Prettier’s website, they tell you how to integrate. Check the section for ESLint and try setting up.
Get Wataru Oguchi’s stories in your inbox
Join Medium for free to get updates from this writer.
Now, let’s run this command below for linting handler.js
$ npx eslint handler.jsIt’ll mention something like this:
5:59 error Replace
'·'with"·"prettier/prettier
Isn’t it handy? This process recommends where to fix the code, and rules what your code should look like. You can also change the rules on your own by changing .eslintrc.json. Please take a look at their documents for further information. Also, if you run the following command, it might auto-fix the issues.
$ npx eslint --fix handler.js 4. Commit — Let’s run tests automatically (husky, lint-staged)
In the previous steps, you learned how to test, and how to tidy up code. However, you may forget running tests, or running the ESLint command before you git-commit the changes. In this step, I’d like to run the scripts automatically when you git-commit.
There are many ways to run commands when you git-commit. Using .git/hooks/pre-commit.sample is one way. This time, I'd like to use husky and lint-staged. The advantage of using these tools is that you only need to write a small amount of code. husky generates actual scripts for you. Just one note - you should be careful if you want to use husky in ongoing projects, because it will conflict with existing git hooks.
Install those tools with:
$ npm install -D lint-staged huskyThen add this snippet in package.json:
The configurations for lint-staged work for any JavaScript files except the ones in __tests__ directory. When the tool finds a JavaScript file, it checks the format and tidies it up like we did in Step 3. Then when there's any changes, add it with git add. Finally, run the test powered by jest, just like we did in Step 2.
The configurations for husky, I set lint-staged to be executed when you run git-commit. When you run git-push, husky executes jest to check all unit tests.
Try running git-commit and make sure both your test and linter will run.
5. Deploy — We should not upload devDependencies (npm prune)
In your package.json, you should have deploy and predeploy in scripts. If you don't, check out the book author's repository.
Those scripts will be executed when you run the deploy command.
Firstly, let’s simply run the deploy command:
$ npm run deployYou should be able to see that a zip file “Lambda-Deployment.zip” was created after the command completed.
Now, please have a look at CodeSize in the logs. It's an output of the aws lambda update-function-code command.
In my case, the code size was 26.3 MB (26,312,199 bytes). This is too huge! It’s because we’re uploading EVERYTHING we have in the working directory. It could slow down AWS Lambda, while also taking so much time to upload the zip file to AWS. This is BAD.
What we don’t need in AWS Lambda is devDependencies. In previous steps, we installed multiple modules to write tests, and to format code, but they won’t be used in AWS Lambda. Let’s remove devDependencies.
How we remove devDependencies from your working directory is running npm prune --production. It will remove the packages specified in your devDependencies [ docs]. When we run this before deploying, we must be able to reduce the size.
Also, we should get back those packages deleted after deploying. npm i --offline looks useful. It installs packages from cache, thus it doesn't require any network access. You can read more about the command here.
Let’s use these npm commands in your package.json:
We’re removing all packages in devDependencies in “predeploy” before zipping the file, then getting back the packages in “postdeploy”.
Now, try deploying once again!
$ npm run deployThen have a look at CodeSize in the logs. Mine was like this below:
In my case, CodeSize became 5.6 MB (5,665,493 bytes), it’s like 20% of what we’ve uploaded before. AWESOME!
Through this post, we learned how to be responsible for your code, and how to make your code maintainable/readable, with no huge impact on our code size. I hope you enjoyed this post with the book. Again, the book is really good, I highly recommend it.
Thank you for reading! Happy coding!

