In this Guide we will learn how to write Serverless services in Monorepo style.
When I tried to write a solutions combine Serverless, Webpack and Lerna together, I can't find any good guide how to do this, then, after implementing it I feel like I want to share my finding with the community,
What is Lerna?
Lerna,a tool for managing JavaScript projects with multiple packages, mostly used for Monorepo, Monorepo is beneficial strategy to keep all your repositories in a one global repository, contains all the common infrastructure and build tools, while each sub 'package' contains a different business project.
So if I have different services, I'll keep all of them in one repository, each one in a different package.
You have a file structure that looks like this:
package.json
packages/
package-1/
package.json
package-2/
package.json
My root package.json
contains some common dependencies like aws-sdk
and some dev-dependencies like webpack
...
{
"name": "root",
"private": true,
"dependencies": {
"aws-sdk": "^2.531.0",
"request-promise": "^4.2.5",
"request": "^2.88.0"
},
"devDependencies": {
"express": "4.17.1",
"lerna": "^3.19.0",
"serverless-webpack": "^5.3.1",
"webpack": "^4.40.2",
"webpack-cli": "^3.3.9"
}
}
Read more about Lerna and it's feature in Lerna github.
Let's serverless it:
Serverless framework gives us the ability to deploy a serverless application (GCP,AWS,AZURE)
A basic example of yml file defining a Lambda:
service: MyService
provider:
name: aws
runtime: nodejs12.x
package:
exclude:
- node_modules/**
functions:
myFunction:
handler: index.myFunction
Let's bundle it, Adding webpack to the party:
We obviously won't want to deploy the full code to AWS, and we may want to use webpack to bundle it into one huge index file.
In order to do that I use serverless-webpack plugin
All the work needed, is just adding it to the serverless file:
service: MyService
provider:
name: aws
runtime: nodejs12.x
package:
exclude:
- node_modules/**
plugins:
- serverless-webpack
functions:
myFunction:
handler: index.myFunction
And the index file wii look like this:
module.exports.myFunction = async (event, context) => {
//doing all stuff needed :)
};
We mention that package is a business service unit, and it can be split to multiple Lambdas, for example UserService, can be split to 3 Lambdas for create, delete and update.
index.js will be like:
module.exports.createUser = async (event, context) => {
//doing all stuff needed :)
};
module.exports.updateUser = async (event, context) => {
//doing all stuff needed :)
};
module.exports.deleteUser = async (event, context) => {
//doing all stuff needed :)
};
With its equivalent serverless.yml
service: UserService
provider:
name: aws
runtime: nodejs12.x
package:
exclude:
- node_modules/**
plugins:
- serverless-webpack
functions:
createUser:
handler: index.createUser
updateUser:
handler: index.updateUser
deleteUser:
handler: index.deleteUser
What can I achieve from managing all my lambdas in the same repo?
Sure, I can have one yml file contains my VPC configuration, security groups, subnet ids, common environment variables and more, and all of them in a one root yml file. this can be referred from any serverless.yml:
provider:
name: aws
stage: prod
runtime: nodejs12.x
vpc:
securityGroupIds: ${file(../../.root.yml):securityGroupIds}
subnetIds: ${file(../../.root.yml):subnetIds}
environment:
${file(../../.root.yml):environment}
And the root.yml:
securityGroupIds:
- "sg-xxxxx"
subnetIds:
- "subnet-xxxxx1"
- "subnet-xxxxx2"
- "subnet-xxxxx3"
environment:
KEY1: value1
KEY2: value2
SumUp
In this Guide we implement monorepo contains some services, each service can contains multiple lambdas, and each lambda is deployed using serverless framework, and we set some common configuration in the root folder to affect all sub packages.
Top comments (0)