DEV Community

Cover image for An efficient way to build your serverless microservices. Part 1. Local Development.
Andrii Melashchenko
Andrii Melashchenko

Posted on • Originally published at blog.javatask.dev

An efficient way to build your serverless microservices. Part 1. Local Development.

Level:

Advanced

Source code:

https://github.com/javatask/graphql-serverless

The Goal of this series of articles

I had worked with AWS lambdas from days when there was no AWS SAM, and it was the early days of Serverless Frameowork. It was an interesting time to find the best tools and approaches to building serverless applications.
I started with bash, webpack, npm .npmrc configs variables and console.log :)
But after all these years, the industry found better, not yet perfect :), ways to develop serverless apps.
In this series, I'll share the NodeJS project boilerplate that shows state-of-the-art tooling that can be used to develop, test, deploy, test, log, trace, monitor, upgrade any serverless business logic.

Introduction

Building the lifecycle for NodeJS Backend for Frontend (BFF) with good Dev user experiences (UX) is challenging. But to add an additional requirement to use serverless stack and hopefully, it is still possible to prevail.

Note. This article is not targeting AWS AppSync. This article uses "raw" AWS API Gateway and AWS Lambda to build GraphQL BFF. AWS AppSync is not used in our use cases because there is a need to have an on-prem version of BFF.

Prerequirements

Knowledge of

Quick start

For those who want to go directly to code, please follow https://github.com/javatask/graphql-serverless

To run the function, you need to install dependencies on your machine:

git clone https://github.com/javatask/graphql-serverless.git 
cd graphql-serverless 
npm i
npm test 
npm run local-run
Enter fullscreen mode Exit fullscreen mode

Part 2. Development in the Cloud
This article guides developers through the deployment and live coding capabilities of AWS SAM
https://blog.javatask.dev/an-efficient-way-to-build-your-serverless-microservices-part-2-development-in-the-cloud

Note. At the end of article there are changes to boilerplate for support of source maps

Note. These commands should work on Linux or MacOS

Criteria for good serverless Dev UX

There is need to account for list of features like:

After defining the criteria, there is need to check offered implementation offered in https://github.com/javatask/graphql-serverless.

Local development of Lambdas

Tooling and package.json

{
...
  "type": "module",
...
  "dependencies": {
    "@apollo/server": "^4.3.0",
    "@as-integrations/aws-lambda": "^1.1.0",
    "graphql-tag": "^2.12.6"
  },
  "devDependencies": {
    "esbuild": "0.16.12",
    "jest": "^29.2.1"
  },
  "scripts": {
    "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js",
    "local-run": "npm run build && sam local invoke --event ./events/graphql-post.json --env-vars env.json GraphqlServerFunction",
    "local-api": "npm run build && sam local start-api --env-vars env.json",
    "build": "sam build",
    "deploy": "sam deploy --guided",
    "build-deploy": "npm run build && npm run deploy",
    "cloud-watch": "sam sync --stack-name graphql-serverless --watch",
    "cloud-logs": "sam logs -n GraphqlServerFunction --stack-name graphql-serverless"
  }
...
}
Enter fullscreen mode Exit fullscreen mode

ESM

To enable ESM by default, there is directive "type":"module" in package.json, it will instruct node to treat all js files as ESM.

Dependencies section

  • @apollo/server: This is the Apollo Server package, which is a popular GraphQL server for Node.js.

  • @as-integrations/aws-lambda: This is the AWS Lambda integration for Apollo Server. It allows you to deploy an Apollo Server instance as an AWS Lambda function.

  • graphql-tag: This is a utility package for parsing GraphQL queries.

And Dev dependencies

  • esbuild: This is a JavaScript and TypeScript bundler and minifier. It can be used to build and optimize the project for production.

  • jest: This is a popular test runner for JavaScript projects. It can be used to run and automate tests.

Scripts section

Scripts sections define next scripts:

  • test: This script runs the test suite for the project. It uses the jest test runner to execute the tests. There are two tests: 1)First test for business logic; 2) Second test for GraphQL query

  • local-run: This script builds the project and invokes the AWS Lambda function locally using the sam local invoke command. It passes the event data from the ./events/graphql-post.json file and the environment variables from the env.json file.

  • local-api: This script builds the project and then starts the local API Gateway using the sam local start-api command. It uses the environment variables from the env.json file. After running this command, you can query the local instance of the server with the next command

curl --request POST 
--url http://127.0.0.1:3000/graphql 
--header 'Content-Type: application/json' 
 --data '{"query":"query Test {state}"}'
Enter fullscreen mode Exit fullscreen mode
  • build: This script builds the project using the sam build command.

  • deploy: This script deploys the project to AWS using the sam deploy command. To deploy the stack, you need to pass your samconfig.toml file or use --guided key with this command

  • build-deploy: This script runs the build and deploys scripts consecutively.

  • cloud-watch: This script syncs the local file changes with the stack running in the cloud and restarts the function if needed using the sam sync command.

  • cloud-logs: This script fetches the logs for the specified AWS Lambda function using the sam logs command.

Tips and tricks for local development

When writing this article, there was no easy way to watch code changes while running the npm run local-api command. To update code for your local running server, you need to run the npm run build command and do NOT restart npm run local-api command. I recommend running two terminal windows, one running npm run local-api server and the second running npm run build command after code changes.

But the better approach is to use jest --watch to develop your business logic. You are then using jest to test your GraphQL revolvers and queries. Finally, after good code coverage is reached, run your local server to do your GraphQL service integration tests.

Note. Local server also can be used to implement integration tests with other parts of your system

Note. What if I need to use AWS service X.Y.Z. for business logic? In this case I can recommend using Hexagonal architecture to mock this services with Jest mocking user modules

*Congratulations!!! Your lambda works locally!!! *

Summary

AWS Serverless Application Model (SAM) gives many tools to improve developer user experiences while developing serverless microservices. Among these features are:

  • support of latest LTS NodeJS

  • integration with state-of-the-art JavaScript bundler - esbuild

  • support for local invocation of Lambdas

  • support for local invocation of API Gateway

This article references the code repository https://github.com/javatask/graphql-serverless and illustrates all these features. Including Jest configuration.

Part 2. Development in the Cloud

This article guides developers through the deployment and live coding capabilities of AWS SAM
https://blog.javatask.dev/an-efficient-way-to-build-your-serverless-microservices-part-2-development-in-the-cloud

Top comments (0)