Lerna+Webpack+Serverless
Tags: serverless, webpack, lerna
Published: 2020-02-09 22:03:01

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](https://github.com/lerna/lerna),a tool for managing JavaScript projects with multiple packages, mostly used for [Monorepo](https://en.wikipedia.org/wiki/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:

```my-lerna-repo/
  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`...

```json
{
  "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](https://serverless.com/) gives us the ability to deploy a serverless application (GCP,AWS,AZURE)


A basic example of yml file defining a Lambda:
```yml
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](https://github.com/serverless-heaven/serverless-webpack)

All the work needed, is just adding it to the serverless file:
```yml
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:
```js
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:

```js
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
```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:

```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:

```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.